test_sdk/math/gtl_math_octv.cpp

340 lines
8.4 KiB
C++
Raw Normal View History

#include "gtl_math_octv.h"
namespace gtl
{
namespace math
{
octv::octv(gtl::analog_data *ad)
: QObject(ad)
, _ad(ad)
, _min(10)
, _max(1024)
, _r(octv::ratios::two)
, _l(octv::looks::amplitude)
, _frac(octv::fractions::one)
, _r_rbw(5)
{
_frequencies = new std::vector<qreal>;
_spec = new gtl::math::spec(gtl::math::spec::types::ausp, _ad);
_spec->set_window(gtl::math::spec::windows::blackman);
_spec->set_unit(gtl::units::unit);
_spec->set_overlap(0);
_spec->set_average(1);
connect(_spec, &gtl::math::spec::changed, this, &octv::spec_changed);
// connect(_spec, &gtl::math::spec::average_changed, this, &octv::average_changed);
// connect(_spec, &gtl::math::spec::overlap_changed, this, &octv::overlap_changed);
// connect(_spec, &gtl::math::spec::unit_changed, this, &octv::unit_changed);
connect(_spec, &gtl::math::spec::acquired, this, &octv::acquired);
init();
}
qreal octv::left(int idx)
{
if(idx < _frequencies->size())
{
return _gfl * _frequencies->at(idx);
}
return 0.;
}
qreal octv::right(int idx)
{
if(idx < _frequencies->size())
{
return _gfh * _frequencies->at(idx);
}
return 0.;
}
qreal octv::minimum() const
{
return _min;
}
void octv::set_minimum(qreal value)
{
if(value != _min && value > 0.1)
{
_min = value;
init();
}
}
qreal octv::maximum() const
{
return _max;
}
void octv::set_maximum(qreal value)
{
if(value > _ad->get_rate())
value = _ad->get_rate();
if(value != _max && value >= 1)
{
_max = value;
init();
}
}
octv::ratios octv::ratio() const
{
return _r;
}
void octv::set_ratio(ratios value)
{
if(value != _r)
{
_r = value;
init();
}
}
octv::looks octv::look() const
{
return _l;
}
void octv::set_look(looks value)
{
if(value != _l)
{
_l = value;
}
}
octv::fractions octv::fraction() const
{
return _frac;
}
void octv::set_fraction(fractions value)
{
if(value != _frac)
{
_frac = value;
init();
}
}
units octv::unit() const
{
return _unit;
}
void octv::set_unit(units value)
{
if( value != _unit )
{
_unit = value;
emit unit_changed();
}
}
// int octv::average() const
// {
// if(_spec)
// {
// return _spec->average();
// }
// return 1;
// }
// void octv::set_average(int value)
// {
// if(_spec)
// {
// _spec->set_average(value);
// }
// }
// qreal octv::overlap() const
// {
// if(_spec)
// {
// return _spec->overlap();
// }
// return 0;
// }
// void octv::set_overlap(int value)
// {
// if(_spec)
// {
// _spec->set_overlap(value);
// }
// }
void octv::init()
{
_frac_num = 1;
if(_frac == gtl::math::octv::fractions::one_third)
_frac_num = 3;
else if(_frac == gtl::math::octv::fractions::one_sixth)
_frac_num = 6;
else if(_frac == gtl::math::octv::fractions::one_twelwe)
_frac_num = 12;
qreal frac_num = (qreal) _frac_num;
_gfl = g_pow((-1.)/(2.*frac_num), true);
_gfh = g_pow(1./(2.*frac_num), true);
/// Calculate frequencies///
qreal tmp_min = g_pow(_min/1000., false);
qreal tmp_max = g_pow(_max/1000., false);
if(_frac_num%2)
{
tmp_min = tmp_min*frac_num + 30.;
tmp_max = tmp_max*frac_num + 30.;
}
else
{
tmp_min = (tmp_min*frac_num*2. + 59.)/2.;
tmp_max = (tmp_max*frac_num*2. + 59.)/2.;
}
int min = std::floor(tmp_min);
int max = std::ceil(tmp_max);
if(min > max)
max = min;
_frequencies->clear();
for(int i = min; i <= max; i++)
{
qreal frequency = _frac_num%2 ? g_pow((i - 30.)/frac_num, true) : g_pow((2.*i - 59.)/(2.*frac_num), true);
frequency *= 1000.;
if(_gfl * frequency < _max && _gfh * frequency > _min)
{
_frequencies->push_back(frequency);
}
}
/////////////////////////////
_spec->set_resolution(left(0)/_r_rbw);
_spec->set_frequency(right(_frequencies->size() - 1));
calculate();
emit initialized();
}
std::pair<int, int> octv::calculate_band_indexes(qreal frequency)
{
qreal res = _spec->resolution();
std::pair<int, int> band;
band.first = (int) (_gfl * frequency / res);
band.second = (int) (_gfh * frequency / res) - 1;
if(band.first > band.second)
band.second = band.first;
return band;
}
qreal octv::calculate_octave(std::vector<qreal>::iterator begin, std::vector<qreal>::iterator end)
{
qreal result = 0;
if(_l == octv::looks::amplitude)
{
result = *std::max_element(begin, end);
}
else if(_l == octv::looks::rms)
{
qreal sum = 0;
for(auto it = begin; it < end; ++it)
{
sum += pow(*it, 2);
}
sum /= std::distance(begin, end);
result = sqrt(sum);
}
if( _unit == gtl::db )
{
result = 20 * log(result/_ad->reference());
}
return result;
}
qreal octv::g_pow(qreal value, bool direction)
{
if(_r == octv::ratios::two)
{
if(direction)
{
return pow(2., value);
}
else
{
return log2(value);
}
}
else if(_r == octv::ratios::ten)
{
if(direction)
{
return pow(10., value * 3./10.);
}
else
{
return log(value) * 10./3.;
}
}
return 0.;
}
void octv::calculate()
{
clear();
std::pair<int, int> band_indexes;
std::pair<qreal, qreal> result;
for(auto it : *_frequencies)
{
result.first = it;
band_indexes = calculate_band_indexes(it);
if(band_indexes.second >= _spec->size())
band_indexes.second = _spec->size() - 1;
result.second = calculate_octave(_spec->begin() + band_indexes.first, _spec->begin() + band_indexes.second);
push_back(result);
}
}
void octv::before_updating()
{
}
void octv::after_updating()
{
}
void octv::spec_changed()
{
_ad->lock_device();
calculate();
_ad->unlock_device();
emit changed();
}
void octv::set_rate(qreal value)
{
_ad->set_rate(value);
init();
}
}
}