add support for reverb & chorus in a-fluidsynth
[ardour.git] / gtk2_ardour / fft.cc
index eda1a96e3f6c601b6cad76fdd5d80cc15d2db969..a4e34bf2aafedbb56116c372772ef017c2320506 100644 (file)
 #include <string.h>
 #include <math.h>
 
+using namespace GTKArdour;
+
 FFT::FFT(uint32_t windowSize)
        : _window_size(windowSize),
          _data_size(_window_size/2),
-       _iterations(0)
+       _iterations(0),
+       _hann_window(0)
 {
        _fftInput  = (float *) fftwf_malloc(sizeof(float) * _window_size);
 
@@ -45,17 +48,24 @@ FFT::reset()
 {
        memset(_power_at_bin, 0, sizeof(float) * _data_size);
        memset(_phase_at_bin, 0, sizeof(float) * _data_size);
-       
+
        _iterations = 0;
 }
 
 void
-FFT::analyze(ARDOUR::Sample *input)
+FFT::analyze(ARDOUR::Sample *input, WindowingType windowing_type)
 {
        _iterations++;
 
        memcpy(_fftInput, input, sizeof(float) * _window_size);
 
+       if (windowing_type == HANN) {
+               float *window = get_hann_window();
+               for (uint32_t i = 0; i < _window_size; i++) {
+                       _fftInput[i] *= window[i];
+               }
+       }
+
        fftwf_execute(_plan);
 
        _power_at_bin[0] += _fftOutput[0] * _fftOutput[0];
@@ -66,11 +76,11 @@ FFT::analyze(ARDOUR::Sample *input)
 
 #define Re (_fftOutput[i])
 #define Im (_fftOutput[_window_size-i])
-               for (uint32_t i=1; i < _data_size - 1; i++) { 
+               for (uint32_t i=1; i < _data_size - 1; i++) {
 
                power = (Re * Re) + (Im * Im);
                phase = atanf(Im / Re);
-       
+
                if (Re < 0.0 && Im > 0.0) {
                        phase += M_PI;
                } else if (Re < 0.0 && Im < 0.0) {
@@ -88,7 +98,7 @@ void
 FFT::calculate()
 {
        if (_iterations > 1) {
-               for (uint32_t i=0; i < _data_size - 1; i++) { 
+               for (uint32_t i=0; i < _data_size - 1; i++) {
                        _power_at_bin[i] /= (float)_iterations;
                        _phase_at_bin[i] /= (float)_iterations;
                }
@@ -96,9 +106,37 @@ FFT::calculate()
        }
 }
 
+float *
+FFT::get_hann_window()
+{
+       if (_hann_window)
+               return _hann_window;
+
+
+        _hann_window = (float *) malloc(sizeof(float) * _window_size);
+
+       double sum = 0.0;
+
+        for (uint32_t i=0; i < _window_size; i++) {
+                _hann_window[i]=0.81f * ( 0.5f - (0.5f * (float) cos(2.0f * M_PI * (float)i / (float)(_window_size))));
+                sum += _hann_window[i];
+        }
+
+        double isum = 1.0 / sum;
+
+        for (uint32_t i=0; i < _window_size; i++) {
+                _hann_window[i] *= isum;
+        }
+
+       return _hann_window;
+}
+
 
 FFT::~FFT()
 {
+       if (_hann_window) {
+               free(_hann_window);
+       }
        fftwf_destroy_plan(_plan);
        free(_power_at_bin);
        free(_phase_at_bin);