test_sdk/script/gtl_scr_spec_harms.cpp

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();
}
}
}