2 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #ifndef _dsp_filter_h_
20 #define _dsp_filter_h_
29 #include "pbd/malign.h"
31 #include "ardour/buffer_set.h"
32 #include "ardour/chan_mapping.h"
33 #include "ardour/libardour_visibility.h"
34 #include "ardour/types.h"
36 namespace ARDOUR { namespace DSP {
38 /** C/C++ Shared Memory
40 * A convenience class representing a C array of float[] or int32_t[]
41 * data values. This is useful for lua scripts to perform DSP operations
42 * directly using C/C++ with CPU Hardware acceleration.
44 * Access to this memory area is always 4 byte aligned. The data
45 * is interpreted either as float or as int.
47 * This memory area can also be shared between different instances
48 * or the same lua plugin (DSP, GUI).
50 * Since memory allocation is not realtime safe it should be
51 * allocated during dsp_init() or dsp_configure().
52 * The memory is free()ed automatically when the lua instance is
61 assert (sizeof(float) == sizeof (int32_t));
62 assert (sizeof(float) == sizeof (int));
67 cache_aligned_free (_data);
70 /** [re] allocate memory in host's memory space
72 * @param s size, total number of float or integer elements to store.
74 void allocate (size_t s) {
75 if (s == _size) { return; }
76 cache_aligned_free (_data);
77 cache_aligned_malloc ((void**) &_data, sizeof (float) * s);
78 if (_data) { _size = s; }
81 /** clear memory (set to zero) */
83 memset (_data, 0, sizeof(float) * _size);
86 /** access memory as float array
88 * @param off offset in shared memory region
91 float* to_float (size_t off) {
92 if (off >= _size) { return 0; }
93 return &(((float*)_data)[off]);
96 /** access memory as integer array
98 * @param off offset in shared memory region
101 int32_t* to_int (size_t off) {
102 if (off >= _size) { return 0; }
103 return &(((int32_t*)_data)[off]);
106 /** atomically set integer at offset
108 * This involves a memory barrier. This call
109 * is intended for buffers which are
110 * shared with another instance.
112 * @param off offset in shared memory region
113 * @param val value to set
115 void atomic_set_int (size_t off, int32_t val) {
116 g_atomic_int_set (&(((int32_t*)_data)[off]), val);
119 /** atomically read integer at offset
121 * This involves a memory barrier. This call
122 * is intended for buffers which are
123 * shared with another instance.
125 * @param off offset in shared memory region
126 * @returns value at offset
128 int32_t atomic_get_int (size_t off) {
129 return g_atomic_int_get (&(((int32_t*)_data)[off]));
137 /** lua wrapper to memset() */
138 void memset (float *data, const float val, const uint32_t n_samples);
140 * multiply every sample of `data' with the corresponding sample at `mult'.
142 * @param data multiplicand
143 * @param mult multiplicand
144 * @param n_samples number of samples in data and mmult
146 void mmult (float *data, float *mult, const uint32_t n_samples);
149 * @param data data to analyze
150 * @param min result, minimum value found in range
151 * @param max result, max value found in range
152 * @param n_samples number of samples to analyze
154 void peaks (const float *data, float &min, float &max, uint32_t n_samples);
156 /** non-linear power-scale meter deflection
158 * @param power signal power (dB)
159 * @returns deflected value
161 float log_meter (float power);
162 /** non-linear power-scale meter deflection
164 * @param coeff signal value
165 * @returns deflected value
167 float log_meter_coeff (float coeff);
169 void process_map (BufferSet* bufs,
170 const ChanMapping& in,
171 const ChanMapping& out,
172 pframes_t nframes, samplecnt_t offset,
175 /** 1st order Low Pass filter */
176 class LIBARDOUR_API LowPass {
178 /** instantiate a LPF
180 * @param samplerate samplerate
181 * @param freq cut-off frequency
183 LowPass (double samplerate, float freq);
184 /** process audio data
186 * @param data pointer to audio-data
187 * @param n_samples number of samples to process
189 void proc (float *data, const uint32_t n_samples);
190 /** filter control data
192 * This is useful for parameter smoothing.
194 * @param data pointer to control-data array
195 * @param val target value
196 * @param array length
198 void ctrl (float *data, const float val, const uint32_t n_samples);
199 /** update filter cut-off frequency
201 * @param freq cut-off frequency
203 void set_cutoff (float freq);
204 /** reset filter state */
205 void reset () { _z = 0.f; }
213 class LIBARDOUR_API Biquad {
227 /** Instantiate Biquad Filter
229 * @param samplerate Samplerate
231 Biquad (double samplerate);
232 Biquad (const Biquad &other);
234 /** process audio data
236 * @param data pointer to audio-data
237 * @param n_samples number of samples to process
239 void run (float *data, const uint32_t n_samples);
240 /** setup filter, compute coefficients
242 * @param t filter type (LowPass, HighPass, etc)
243 * @param freq filter frequency
244 * @param Q filter quality
245 * @param gain filter gain
247 void compute (Type t, double freq, double Q, double gain);
249 /** setup filter, set coefficients directly */
250 void configure (double a1, double a2, double b0, double b1, double b2);
252 /** filter transfer function (filter response for spectrum visualization)
253 * @param freq frequency
254 * @return gain at given frequency in dB (clamped to -120..+120)
256 float dB_at_freq (float freq) const;
258 /** reset filter state */
259 void reset () { _z1 = _z2 = 0.0; }
264 double _b0, _b1, _b2;
267 class LIBARDOUR_API FFTSpectrum {
269 FFTSpectrum (uint32_t window_size, double rate);
272 /** set data to be analyzed and pre-process with hanning window
273 * n_samples + offset must not be larger than the configured window_size
275 * @param data raw audio data
276 * @param n_samples number of samples to write to analysis buffer
277 * @param offset destination offset
279 void set_data_hann (float const * const data, const uint32_t n_samples, const uint32_t offset = 0);
281 /** process current data in buffer */
285 * @param bin the frequency bin 0 .. window_size / 2
286 * @param norm gain factor (set equal to @bin for 1/f normalization)
287 * @return signal power at given bin (in dBFS)
289 float power_at_bin (const uint32_t bin, const float norm = 1.f) const;
291 float freq_at_bin (const uint32_t bin) const {
292 return bin * _fft_freq_per_bin;
296 static Glib::Threads::Mutex fft_planner_lock;
299 void init (uint32_t window_size, double rate);
302 uint32_t _fft_window_size;
303 uint32_t _fft_data_size;
304 double _fft_freq_per_bin;
307 float* _fft_data_out;