diff options
author | Robin Gareus <robin@gareus.org> | 2016-07-02 23:35:00 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-07-02 23:36:34 +0200 |
commit | f169ff3db3943b9992042e71048cade2ca1fe39d (patch) | |
tree | 47d8f30c2c88668b48215a115ca03260d9d8c1c7 /libs/ardour/dsp_filter.cc | |
parent | 8b142a2fd6214c51ca1d1ccdcf043c6445141e24 (diff) |
extend lua API:
* add a basic FFT spectrum analyzer
* prepare Cairo::ImageSurface
* HSL colorspace conversion
Diffstat (limited to 'libs/ardour/dsp_filter.cc')
-rw-r--r-- | libs/ardour/dsp_filter.cc | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/libs/ardour/dsp_filter.cc b/libs/ardour/dsp_filter.cc index 9d6e2cf710..3b93c9c6f3 100644 --- a/libs/ardour/dsp_filter.cc +++ b/libs/ardour/dsp_filter.cc @@ -155,6 +155,16 @@ Biquad::run (float *data, const uint32_t n_samples) } void +Biquad::configure (double a1, double a2, double b0, double b1, double b2) +{ + _a1 = a1; + _a2 = a2; + _b0 = b0; + _b1 = b1; + _b2 = b2; +} + +void Biquad::compute (Type type, double freq, double Q, double gain) { if (Q <= .001) { Q = 0.001; } @@ -289,3 +299,98 @@ Biquad::dB_at_freq (float freq) const if (!isfinite_local (rv)) { rv = 0; } return std::min (120.f, std::max(-120.f, rv)); } + + +Glib::Threads::Mutex FFTSpectrum::fft_planner_lock; + +FFTSpectrum::FFTSpectrum (uint32_t window_size, double rate) + : hann_window (0) +{ + init (window_size, rate); +} + +FFTSpectrum::~FFTSpectrum () +{ + { + Glib::Threads::Mutex::Lock lk (fft_planner_lock); + fftwf_destroy_plan (_fftplan); + } + fftwf_free (_fft_data_in); + fftwf_free (_fft_data_out); + free (_fft_power); + free (hann_window); +} + +void +FFTSpectrum::init (uint32_t window_size, double rate) +{ + Glib::Threads::Mutex::Lock lk (fft_planner_lock); + + _fft_window_size = window_size; + _fft_data_size = window_size / 2; + _fft_freq_per_bin = rate / _fft_data_size / 2.f; + + _fft_data_in = (float *) fftwf_malloc (sizeof(float) * _fft_window_size); + _fft_data_out = (float *) fftwf_malloc (sizeof(float) * _fft_window_size); + _fft_power = (float *) malloc (sizeof(float) * _fft_data_size); + + reset (); + + _fftplan = fftwf_plan_r2r_1d (_fft_window_size, _fft_data_in, _fft_data_out, FFTW_R2HC, FFTW_MEASURE); + + 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.5f - (0.5f * (float) cos (2.0f * M_PI * (float)i / (float)(window_size))); + sum += hann_window[i]; + } + const double isum = 2.0 / sum; + for (uint32_t i = 0; i < window_size; ++i) { + hann_window[i] *= isum; + } +} + +void +FFTSpectrum::reset () +{ + for (uint32_t i = 0; i < _fft_data_size; ++i) { + _fft_power[i] = 0; + } + for (uint32_t i = 0; i < _fft_window_size; ++i) { + _fft_data_out[i] = 0; + } +} + +void +FFTSpectrum::set_data_hann (float const * const data, uint32_t n_samples, uint32_t offset) +{ + assert(n_samples + offset <= _fft_window_size); + for (uint32_t i = 0; i < n_samples; ++i) { + _fft_data_in[i + offset] = data[i] * hann_window[i + offset]; + } +} + +void +FFTSpectrum::execute () +{ + fftwf_execute (_fftplan); + + _fft_power[0] = _fft_data_out[0] * _fft_data_out[0]; + +#define FRe (_fft_data_out[i]) +#define FIm (_fft_data_out[_fft_window_size - i]) + for (uint32_t i = 1; i < _fft_data_size - 1; ++i) { + _fft_power[i] = (FRe * FRe) + (FIm * FIm); + //_fft_phase[i] = atan2f (FIm, FRe); + } +#undef FRe +#undef FIm +} + +float +FFTSpectrum::power_at_bin (const uint32_t b, const float norm) const { + assert (b >= 0 && b < _fft_data_size); + const float a = _fft_power[b] * norm; + return a > 1e-12 ? 10.0 * fast_log10 (a) : -INFINITY; +} |