314 lines
8.9 KiB
C++
314 lines
8.9 KiB
C++
#include "gtl_scr_spec_harms.h"
|
|
|
|
namespace gtl
|
|
{
|
|
namespace scr
|
|
{
|
|
spec_harms::spec_harms(QObject *parent)
|
|
: QObject(parent)
|
|
, _tolerance(1)
|
|
, _is_visible(true)
|
|
{
|
|
|
|
}
|
|
|
|
spec_harms::spec_harms(QObject *parent, qreal freq, int k, int color, qreal weight)
|
|
: QObject(parent)
|
|
, _tolerance(1)
|
|
, _is_visible(true)
|
|
{
|
|
for(int i = 0; i < k; i++)
|
|
add_harm(new spec_harm(this, freq*(i + 1), color, weight));
|
|
}
|
|
|
|
spec_harms::~spec_harms()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
QVariant spec_harms::get_harms() const
|
|
{
|
|
return QVariant::fromValue(static_cast<QList<spec_harm*>>(*this));
|
|
}
|
|
|
|
QVariant spec_harms::get_modulating() const
|
|
{
|
|
return QVariant::fromValue(_modulating_harms);
|
|
}
|
|
|
|
void spec_harms::get_harms(std::back_insert_iterator<std::vector<spec_harm *>> harms)
|
|
{
|
|
for(auto harm : *this)
|
|
{
|
|
harms = harm;
|
|
harms++;
|
|
}
|
|
|
|
for(auto modulating_harms : _modulating_harms)
|
|
modulating_harms->get_harms(harms);
|
|
}
|
|
|
|
void spec_harms::update()
|
|
{
|
|
for(int i = 0; i < size(); i++)
|
|
at(i)->update();
|
|
|
|
for(int i = 0; i < _modulating_harms.size(); i++)
|
|
_modulating_harms[i]->update();
|
|
|
|
}
|
|
|
|
void spec_harms::save_state(QJsonObject &root)
|
|
{
|
|
root["name"] = _name;
|
|
int idx = 0;
|
|
|
|
QJsonArray harms;
|
|
for(auto harm : *this)
|
|
{
|
|
QJsonObject harm_object;
|
|
harm->save_state(harm_object);
|
|
|
|
|
|
if(idx < _modulating_harms.size())
|
|
{
|
|
QJsonObject modulatings;
|
|
_modulating_harms[idx]->save_state(modulatings);
|
|
harm_object.insert("modulatings", modulatings);
|
|
}
|
|
|
|
harms.append(harm_object);
|
|
idx++;
|
|
}
|
|
|
|
root["harms"] = harms;
|
|
|
|
}
|
|
|
|
void spec_harms::restore_state(const QJsonObject &root)
|
|
{
|
|
set_name(root["name"].toString());
|
|
clear();
|
|
|
|
QJsonArray harms = root["harms"].toArray();
|
|
for(auto it: harms)
|
|
{
|
|
spec_harm *harm = new spec_harm(this);
|
|
add_harm(harm);
|
|
|
|
harm->restor_state(it.toObject());
|
|
|
|
QJsonObject modulating = it.toObject()["modulatings"].toObject();
|
|
|
|
if(modulating.empty())
|
|
continue;
|
|
|
|
spec_harms *harms = new spec_harms(this);
|
|
|
|
harms->set_tolerance(_tolerance);
|
|
|
|
connect(harms, &spec_harms::get_peak_freq, this, &spec_harms::get_peak_freq);
|
|
connect(harms, &spec_harms::get_harm_amplitude, this, &spec_harms::get_harm_amplitude);
|
|
connect(harms, &spec_harms::get_harm_base, this, &spec_harms::get_harm_base);
|
|
connect(harms, &spec_harms::get_max_harm_level, this, &spec_harms::get_max_harm_level);
|
|
connect(harms, &spec_harms::integral_index_changed, this, &spec_harms::integral_index_changed);
|
|
|
|
_modulating_harms.push_back(harms);
|
|
|
|
harms->restore_state(modulating);
|
|
|
|
}
|
|
}
|
|
|
|
qreal spec_harms::tolerance() const
|
|
{
|
|
return _tolerance;
|
|
}
|
|
|
|
QString spec_harms::name() const
|
|
{
|
|
return _name;
|
|
}
|
|
|
|
bool spec_harms::is_visible() const
|
|
{
|
|
return _is_visible;
|
|
}
|
|
|
|
void spec_harms::get_max_ampl(qreal &max_ampl)
|
|
{
|
|
for(int j = 0; j < size(); j++)
|
|
at(j)->get_max_level(max_ampl);
|
|
|
|
for(auto harm : _modulating_harms)
|
|
harm->get_max_ampl(max_ampl);
|
|
}
|
|
|
|
qreal spec_harms::integral_index() const
|
|
{
|
|
qreal value = 0;
|
|
for(int j = 0; j < size(); j++)
|
|
value += at(j)->integral_index();
|
|
|
|
return value;
|
|
}
|
|
|
|
void spec_harms::add_harm(spec_harm *harm)
|
|
{
|
|
push_back(harm);
|
|
|
|
harm->set_tolerance(_tolerance);
|
|
|
|
connect(harm, &spec_harm::get_peak_freq, this, &spec_harms::get_peak_freq);
|
|
connect(harm, &spec_harm::get_amplitude, this, &spec_harms::get_harm_amplitude);
|
|
connect(harm, &spec_harm::get_base, this, &spec_harms::get_harm_base);
|
|
connect(harm, &spec_harm::get_max_harm_ampl, this, &spec_harms::get_max_harm_level);
|
|
connect(harm, &spec_harm::get_modulating_harms_integral_index, this, &spec_harms::get_modulating_harms_integral_index);
|
|
connect(harm, &spec_harm::amplitude_changed, this, &spec_harms::integral_index_changed);
|
|
}
|
|
|
|
int spec_harms::get_cnt_harms(int from, int step)
|
|
{
|
|
int cnt = 0;
|
|
for(int i = from; i < size(); i += step)
|
|
{
|
|
if(at(i)->is_present())
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void spec_harms::modulate(qreal freq, int k, int color, qreal weight)
|
|
{
|
|
for(int j = 0; j < size(); j++)
|
|
{
|
|
spec_harms *harms = new spec_harms(this);
|
|
|
|
harms->set_tolerance(_tolerance);
|
|
|
|
connect(harms, &spec_harms::get_peak_freq, this, &spec_harms::get_peak_freq);
|
|
connect(harms, &spec_harms::get_harm_amplitude, this, &spec_harms::get_harm_amplitude);
|
|
connect(harms, &spec_harms::get_harm_base, this, &spec_harms::get_harm_base);
|
|
connect(harms, &spec_harms::get_max_harm_level, this, &spec_harms::get_max_harm_level);
|
|
|
|
_modulating_harms.push_back(harms);
|
|
|
|
for(int i = 1; i <= k; i++)
|
|
{
|
|
harms->add_harm(new spec_harm(this, at(j)->freq() + freq*i, color, weight));
|
|
harms->add_harm(new spec_harm(this, at(j)->freq() - freq*i, color, weight));
|
|
}
|
|
}
|
|
}
|
|
|
|
int spec_harms::get_count(uint from, int fails, int cnt_mods, bool both_sides) const
|
|
{
|
|
int cnt = 0;
|
|
int cnt_fails = 0;
|
|
for(int i = from; i < size(); i++)
|
|
{
|
|
if(at(i)->is_present())
|
|
{
|
|
|
|
int mods = 0;
|
|
|
|
if(i < _modulating_harms.size())
|
|
{
|
|
int cnt_mods_left = _modulating_harms[i]->get_cnt_harms(1, 2);
|
|
int cnt_mods_right = _modulating_harms[i]->get_cnt_harms(0, 2);
|
|
|
|
if(both_sides)
|
|
mods = cnt_mods_left + cnt_mods_right;
|
|
else
|
|
mods = qMax(cnt_mods_left, cnt_mods_right);
|
|
}
|
|
|
|
if(mods >= cnt_mods)
|
|
{
|
|
cnt++;
|
|
cnt_fails = 0;
|
|
}
|
|
else
|
|
{
|
|
cnt_fails++;
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
cnt_fails++;
|
|
}
|
|
|
|
if(cnt_fails > fails)
|
|
break;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void spec_harms::clear()
|
|
{
|
|
for(auto it : *this)
|
|
delete it;
|
|
|
|
QList<spec_harm*>::clear();
|
|
|
|
for(auto it : _modulating_harms)
|
|
delete it;
|
|
|
|
_modulating_harms.clear();
|
|
}
|
|
|
|
void spec_harms::set_tolerance(qreal value)
|
|
{
|
|
if(_tolerance != value)
|
|
{
|
|
_tolerance = value;
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
at(i)->set_tolerance(_tolerance);
|
|
|
|
for(int i = 0; i < _modulating_harms.size(); i++)
|
|
_modulating_harms[i]->set_tolerance(_tolerance);
|
|
|
|
|
|
emit tolerance_changed();
|
|
}
|
|
}
|
|
|
|
void spec_harms::set_name(QString value)
|
|
{
|
|
if(_name != value)
|
|
{
|
|
_name = value;
|
|
emit name_changed();
|
|
}
|
|
}
|
|
|
|
void spec_harms::set_visible(bool value)
|
|
{
|
|
if(_is_visible != value)
|
|
{
|
|
_is_visible = value;
|
|
emit visible_changed();
|
|
}
|
|
}
|
|
|
|
void spec_harms::get_modulating_harms_integral_index(qreal &value)
|
|
{
|
|
auto it = std::find(begin(), end(), sender());
|
|
if(it == end())
|
|
return;
|
|
|
|
int idx = std::distance(begin(), it);
|
|
if(idx >= _modulating_harms.size())
|
|
return;
|
|
|
|
value += _modulating_harms[idx]->integral_index();
|
|
|
|
}
|
|
}
|
|
}
|