X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Ffft_result.cc;h=b4a82c25869e20443d6b285f7fbde1fee2481772;hb=415721fa5b48f3c3dc164ac60095c095c4e48ad0;hp=37c045b7b052a1b38bd299263060de4a575d0f5c;hpb=bb9cc45cd22af67ac275a5e73accbe14fee664d8;p=ardour.git diff --git a/gtk2_ardour/fft_result.cc b/gtk2_ardour/fft_result.cc index 37c045b7b0..b4a82c2586 100644 --- a/gtk2_ardour/fft_result.cc +++ b/gtk2_ardour/fft_result.cc @@ -1,31 +1,29 @@ /* - Copyright (C) 2006 Paul Davis - Written by Sampo Savolainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include + * Copyright (C) 2006, 2016 Paul Davis + * Written by Sampo Savolainen & Robin Gareus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "fft_result.h" +#include "fft_graph.h" #include #include #include #include - -#include +#include using namespace std; @@ -35,18 +33,24 @@ FFTResult::FFTResult(FFTGraph *graph, Gdk::Color color, string trackname) _windowSize = _graph->windowSize(); _dataSize = _windowSize / 2; - _averages = 0; - - _data_avg = (float *) malloc(sizeof(float) * _dataSize); - memset(_data_avg,0,sizeof(float) * _dataSize); - - _data_min = (float *) malloc(sizeof(float) * _dataSize); - _data_max = (float *) malloc(sizeof(float) * _dataSize); - - for (int i = 0; i < _dataSize; i++) { - _data_min[i] = FLT_MAX; - _data_max[i] = FLT_MIN; + _min_flat = _max_flat = 0.0; + _min_prop = _max_prop = 0.0; + + _data_flat_avg = (float *) malloc (sizeof(float) * _dataSize); + _data_flat_min = (float *) malloc (sizeof(float) * _dataSize); + _data_flat_max = (float *) malloc (sizeof(float) * _dataSize); + _data_prop_avg = (float *) malloc (sizeof(float) * _dataSize); + _data_prop_min = (float *) malloc (sizeof(float) * _dataSize); + _data_prop_max = (float *) malloc (sizeof(float) * _dataSize); + + for (unsigned int i = 0; i < _dataSize; i++) { + _data_flat_min[i] = FLT_MAX; + _data_flat_max[i] = FLT_MIN; + _data_flat_avg[i] = 0; + _data_prop_min[i] = FLT_MAX; + _data_prop_max[i] = FLT_MIN; + _data_prop_avg[i] = 0; } _color = color; @@ -56,34 +60,31 @@ FFTResult::FFTResult(FFTGraph *graph, Gdk::Color color, string trackname) void FFTResult::analyzeWindow(float *window) { - float *_hanning = _graph->_hanning; + float const * const _hanning = _graph->_hanning; float *_in = _graph->_in; float *_out = _graph->_out; - int i; // Copy the data and apply the hanning window - for (i = 0; i < _windowSize; i++) { - _in[i] = window[ i ] * _hanning[ i ]; + for (unsigned int i = 0; i < _windowSize; ++i) { + _in[i] = window[i] * _hanning[i]; } fftwf_execute(_graph->_plan); + // calculate signal power per bin float b = _out[0] * _out[0]; - _data_avg[0] += b; - if (b < _data_min[0]) _data_min[0] = b; - if (b > _data_max[0]) _data_max[0] = b; - - for (i=1; i < _dataSize - 1; i++) { // TODO: check with Jesse whether this is really correct - b = (_out[i] * _out[i]); - - _data_avg[i] += b; // + (_out[_windowSize-i] * _out[_windowSize-i]);, TODO: thanks to Stefan Kost + _data_flat_avg[0] += b; + if (b < _data_flat_min[0]) _data_flat_min[0] = b; + if (b > _data_flat_max[0]) _data_flat_max[0] = b; - if (_data_min[i] > b) _data_min[i] = b; - if (_data_max[i] < b ) _data_max[i] = b; + for (unsigned int i = 1; i < _dataSize - 1; ++i) { + b = (_out[i] * _out[i]) + (_out[_windowSize - i] * _out[_windowSize - i]); + _data_flat_avg[i] += b; + if (_data_flat_min[i] > b) _data_flat_min[i] = b; + if (_data_flat_max[i] < b ) _data_flat_max[i] = b; } - _averages++; } @@ -91,32 +92,43 @@ void FFTResult::finalize() { if (_averages == 0) { - _minimum = 0.0; - _maximum = 0.0; + _min_flat = _max_flat = 0.0; + _min_prop = _max_prop = 0.0; return; } // Average & scale - for (int i = 0; i < _dataSize; i++) { - _data_avg[i] /= _averages; - _data_avg[i] = 10.0f * log10f(_data_avg[i]); - - _data_min[i] = 10.0f * log10f(_data_min[i]); - if (_data_min[i] < -10000.0f) { - _data_min[i] = -10000.0f; - } - _data_max[i] = 10.0f * log10f(_data_max[i]); + for (unsigned int i = 0; i < _dataSize - 1; ++i) { + _data_flat_avg[i] /= _averages; + // proportional, pink spectrum @ -18dB + _data_prop_avg[i] = _data_flat_avg [i] * i / 63.096f; + _data_prop_min[i] = _data_flat_min [i] * i / 63.096f; + _data_prop_max[i] = _data_flat_max [i] * i / 63.096f; + } + + _data_prop_avg[0] = _data_flat_avg [0] / 63.096f; + _data_prop_min[0] = _data_flat_min [0] / 63.096f; + _data_prop_max[0] = _data_flat_max [0] / 63.096f; + + // calculate power + for (unsigned int i = 0; i < _dataSize - 1; ++i) { + _data_flat_min[i] = power_to_db (_data_flat_min[i]); + _data_flat_max[i] = power_to_db (_data_flat_max[i]); + _data_flat_avg[i] = power_to_db (_data_flat_avg[i]); + _data_prop_min[i] = power_to_db (_data_prop_min[i]); + _data_prop_max[i] = power_to_db (_data_prop_max[i]); + _data_prop_avg[i] = power_to_db (_data_prop_avg[i]); } // find min & max - _minimum = _maximum = _data_avg[0]; - - for (int i = 1; i < _dataSize; i++) { - if (_data_avg[i] < _minimum && !isinf(_data_avg[i])) { - _minimum = _data_avg[i]; - } else if (_data_avg[i] > _maximum && !isinf(_data_avg[i])) { - _maximum = _data_avg[i]; - } + _min_flat = _max_flat = _data_flat_avg[0]; + _min_prop = _max_prop = _data_prop_avg[0]; + + for (unsigned int i = 1; i < _dataSize - 1; ++i) { + _min_flat = std::min (_min_flat, _data_flat_avg[i]); + _max_flat = std::max (_max_flat, _data_flat_avg[i]); + _min_prop = std::min (_min_prop, _data_prop_avg[i]); + _max_prop = std::max (_max_prop, _data_prop_avg[i]); } _averages = 0; @@ -124,36 +136,10 @@ FFTResult::finalize() FFTResult::~FFTResult() { - free(_data_avg); - free(_data_min); - free(_data_max); + free(_data_flat_avg); + free(_data_flat_min); + free(_data_flat_max); + free(_data_prop_avg); + free(_data_prop_min); + free(_data_prop_max); } - - -float -FFTResult::avgAt(int x) -{ - if (x < 0 || x>= _dataSize) - return 0.0f; - - return _data_avg[x]; -} - -float -FFTResult::minAt(int x) -{ - if (x < 0 || x>= _dataSize) - return 0.0f; - - return _data_min[x]; -} - -float -FFTResult::maxAt(int x) -{ - if (x < 0 || x>= _dataSize) - return 0.0f; - - return _data_max[x]; -} -