#include "gtl_math_cross_spec.h" namespace gtl { namespace math { cross_spec::cross_spec(gtl::analog_data *ref, gtl::analog_data *data) : _is_acq(true), _av(1), _av_cnt(0), _av_filled(false), _threshold(50), _ref(nullptr), _data(nullptr) { _device = static_cast(data->root()); if(_device) _device->lock_ai(); _ref = new gtl::math::fft(ref); _data = new gtl::math::fft(data); connect(_device, >l::device::recieved_data, this, >l::math::cross_spec::device_recieved_data); connect(_data, >l::math::fft::initialized, this, &cross_spec::init); connect(_data, >l::math::fft::frequency_changed, this, &cross_spec::frequency_changed); connect(_data, >l::math::fft::resolution_changed, this, &cross_spec::resolution_changed); connect(_data, >l::math::fft::window_changed, this, &cross_spec::window_changed); connect(_data, >l::math::fft::lines_changed, this, &cross_spec::lines_changed); connect(_data, >l::math::fft::overlap_changed, this, &cross_spec::overlap_changed); init(); if(_device) _device->unlock_ai(); } cross_spec::~cross_spec() { emit deleting(); cleanup(); if(_ref) delete _ref; if(_data) delete _data; } void cross_spec::set_ref(analog_data *ref) { if(_device) _device->lock_ai(); if(_ref) delete _ref; _ref = new gtl::math::fft(ref); _ref->set_frequency(_data->frequency()); _ref->set_resolution(_data->resolution()); _ref->set_overlap(_data->overlap()); _ref->set_window(_data->window()); init(); if(_device) _device->unlock_ai(); } void cross_spec::set_data(analog_data *data) { _device = static_cast(data->root()); if(_device) _device->lock_ai(); disconnect(_device, >l::device::recieved_data, this, >l::math::cross_spec::device_recieved_data); disconnect(_data, >l::math::fft::initialized, this, &cross_spec::init); disconnect(_data, >l::math::fft::frequency_changed, this, &cross_spec::frequency_changed); disconnect(_data, >l::math::fft::resolution_changed, this, &cross_spec::resolution_changed); disconnect(_data, >l::math::fft::window_changed, this, &cross_spec::window_changed); disconnect(_data, >l::math::fft::lines_changed, this, &cross_spec::lines_changed); disconnect(_data, >l::math::fft::overlap_changed, this, &cross_spec::overlap_changed); if(_data) delete _data; _data = new gtl::math::fft(data); _data->set_frequency(_ref->frequency()); _data->set_resolution(_ref->resolution()); _data->set_overlap(_ref->overlap()); _data->set_window(_ref->window()); connect(_device, >l::device::recieved_data, this, >l::math::cross_spec::device_recieved_data); connect(_data, >l::math::fft::initialized, this, >l::math::cross_spec::init); connect(_data, >l::math::fft::frequency_changed, this, >l::math::cross_spec::frequency_changed); connect(_data, >l::math::fft::resolution_changed, this, >l::math::cross_spec::resolution_changed); connect(_data, >l::math::fft::window_changed, this, >l::math::cross_spec::window_changed); connect(_data, >l::math::fft::lines_changed, this, >l::math::cross_spec::lines_changed); connect(_data, >l::math::fft::overlap_changed, this, >l::math::cross_spec::overlap_changed); init(); if(_device) _device->unlock_ai(); } qreal cross_spec::frequency() const { return _data->frequency(); } void cross_spec::set_frequency(qreal value) { _ref->set_frequency(value); _data->set_frequency(value); init(); } qreal cross_spec::resolution() const { return _data->resolution(); } void cross_spec::set_resolution(qreal value) { _ref->set_resolution(value); _data->set_resolution(value); init(); } cross_spec::windows cross_spec::window() const { return (cross_spec::windows) _data->window(); } void cross_spec::set_window(windows value) { _ref->set_window((fft::windows) value); _data->set_window((fft::windows) value); } int cross_spec::lines() const { return _data->lines(); } void cross_spec::set_lines(int value) { _ref->set_lines(value); _data->set_lines(value); init(); } uint cross_spec::average() const { return _av; } void cross_spec::set_average(int value) { if( value != _av && value > 0) { _av = value; init(); emit average_changed(); } } qreal cross_spec::overlap() const { return _data->overlap(); } void cross_spec::set_overlap(int value) { _ref->set_overlap(value); _data->set_overlap(value); } // units cross_spec::unit() const // { // return _un; // } // void cross_spec::set_unit(units value) // { // if( value != _un ) // { // _un = value; // emit unit_changed(); // } // } analog_data *cross_spec::ad() const { return _data->ad(); } qreal cross_spec::acq_time() const { int nl = _data->lines(); qreal f = _data->frequency(); qreal ol = _data->overlap(); return (nl + 1)/f * ((_av - 1)* (1.0 - ol/100.0) + 1); } void cross_spec::calculate() { for(int i = 0; i < _size_fft_out; i++) *(_calculated_it + i) = abs(_ref->at(i)*std::conj(_data->at(i)))/_size_fft_calc/_size_fft_calc; } void cross_spec::before_updating() { } void cross_spec::after_updating() { } void cross_spec::device_recieved_data() { if(_ref->samples() != _data->samples()) return; if(_device) _device->lock_ai(); before_updating(); // Вычисление , усреднение int avdiv = _av_filled ? _av : _av_cnt + 1; if( _av > 1 ) _calculated_it = _buffer_out[_av_cnt]->begin(); else _calculated_it = begin(); calculate(); if( _av > 1 ) { for(int i = 0; i < _size_fft_out; i++) { qreal value = 0; for(int j = 0; j < avdiv; j++) value += _buffer_out[j]->at(i)/avdiv; at(i) = value; } } _av_cnt++; _ac = 100. * ( (qreal) _av_cnt )/_av; emit acquired(_ac); if(_av_cnt == _av) { _av_cnt = 0; _av_filled = true; } after_updating(); if(_device) _device->unlock_ai(); emit changed(); } void cross_spec::cleanup() { if(_device) _device->lock_ai(); for(std::vector* ptr:_buffer_out) { if( ptr ) { ptr->clear(); ptr->shrink_to_fit(); delete ptr; } } _buffer_out.clear(); _buffer_out.shrink_to_fit(); clear(); shrink_to_fit(); if(_device) _device->unlock_ai(); } void cross_spec::init() { if(_device) _device->lock_ai(); cleanup(); _size_fft_out = std::min(_data->size_fft_out(), _ref->size_fft_out()); _size_fft_calc = std::min(_data->size_fft_calc(), _ref->size_fft_calc()); _av_cnt = 0; _av_filled = false; for(int i = 0; i < _av; i++) _buffer_out.push_back(new std::vector(_size_fft_out)); _calculated_it = _buffer_out[0]->begin(); resize(_size_fft_out); if(_device) _device->unlock_ai(); emit initialized(); emit acq_time_changed(); } void cross_spec::stop_acq() { _is_acq = false; } } // namespace math } // namespace gtl