#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>(*this)); } QVariant spec_harms::get_modulating() const { return QVariant::fromValue(_modulating_harms); } void spec_harms::get_harms(std::back_insert_iterator> 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::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(); } } }