#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);
{
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];
#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) {
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;
}
}
}
+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);