1f13cceb611b2e9a7468ccde4f4a58db6f6c5249
[ardour.git] / libs / ardour / ardour / dsp_filter.h
1 /*
2  * Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
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.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 #ifndef _dsp_filter_h_
19 #define _dsp_filter_h_
20
21 #include <stdint.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <glib.h>
25 #include <glibmm.h>
26 #include <fftw3.h>
27
28 #include "pbd/malign.h"
29
30 #include "ardour/buffer_set.h"
31 #include "ardour/chan_mapping.h"
32 #include "ardour/libardour_visibility.h"
33 #include "ardour/types.h"
34
35 namespace ARDOUR { namespace DSP {
36
37         /** C/C++ Shared Memory
38          *
39          * A convenience class representing a C array of float[] or int32_t[]
40          * data values. This is useful for lua scripts to perform DSP operations
41          * directly using C/C++ with CPU Hardware acceleration.
42          *
43          * Access to this memory area is always 4 byte aligned. The data
44          * is interpreted either as float or as int.
45          *
46          * This memory area can also be shared between different instances
47          * or the same lua plugin (DSP, GUI).
48          *
49          * Since memory allocation is not realtime safe it should be
50          * allocated during dsp_init() or dsp_configure().
51          * The memory is free()ed automatically when the lua instance is
52          * destroyed.
53          */
54         class DspShm {
55                 public:
56                         DspShm (size_t s = 0)
57                                 : _data (0)
58                                 , _size (0)
59                         {
60                                 assert (sizeof(float) == sizeof (int32_t));
61                                 assert (sizeof(float) == sizeof (int));
62                                 allocate (s);
63                         }
64
65                         ~DspShm () {
66                                 cache_aligned_free (_data);
67                         }
68
69                         /** [re] allocate memory in host's memory space
70                          *
71                          * @param s size, total number of float or integer elements to store.
72                          */
73                         void allocate (size_t s) {
74                                 if (s == _size) { return; }
75                                 cache_aligned_free (_data);
76                                 cache_aligned_malloc ((void**) &_data, sizeof (float) * s);
77                                 if (_data) { _size = s; }
78                         }
79
80                         /** clear memory (set to zero) */
81                         void clear () {
82                                 memset (_data, 0, sizeof(float) * _size);
83                         }
84
85                         /** access memory as float array
86                          *
87                          * @param off offset in shared memory region
88                          * @returns float[]
89                          */
90                         float* to_float (size_t off) {
91                                 if (off >= _size) { return 0; }
92                                 return &(((float*)_data)[off]);
93                         }
94
95                         /** access memory as integer array
96                          *
97                          * @param off offset in shared memory region
98                          * @returns int_32_t[]
99                          */
100                         int32_t* to_int (size_t off) {
101                                 if (off >= _size) { return 0; }
102                                 return &(((int32_t*)_data)[off]);
103                         }
104
105                         /** atomically set integer at offset
106                          *
107                          * This involves a memory barrier. This call
108                          * is intended for buffers which are
109                          * shared with another instance.
110                          *
111                          * @param off offset in shared memory region
112                          * @param val value to set
113                          */
114                         void atomic_set_int (size_t off, int32_t val) {
115                                 g_atomic_int_set (&(((int32_t*)_data)[off]), val);
116                         }
117
118                         /** atomically read integer at offset
119                          *
120                          * This involves a memory barrier. This call
121                          * is intended for buffers which are
122                          * shared with another instance.
123                          *
124                          * @param off offset in shared memory region
125                          * @returns value at offset
126                          */
127                         int32_t atomic_get_int (size_t off) {
128                                 return g_atomic_int_get (&(((int32_t*)_data)[off]));
129                         }
130
131                 private:
132                         void* _data;
133                         size_t _size;
134         };
135
136         /** lua wrapper to memset() */
137         void memset (float *data, const float val, const uint32_t n_samples);
138         /** matrix multiply
139          * multiply every sample of `data' with the corresponding sample at `mult'.
140          *
141          * @param data multiplicand
142          * @param mult multiplicand
143          * @param n_samples number of samples in data and mmult
144          */
145         void mmult (float *data, float *mult, const uint32_t n_samples);
146         /** calculate peaks
147          *
148          * @param data data to analyze
149          * @param min result, minimum value found in range
150          * @param max result, max value found in range
151          * @param n_samples number of samples to analyze
152          */
153         void peaks (const float *data, float &min, float &max, uint32_t n_samples);
154
155         /** non-linear power-scale meter deflection
156          *
157          * @param power signal power (dB)
158          * @returns deflected value
159          */
160         float log_meter (float power);
161         /** non-linear power-scale meter deflection
162          *
163          * @param coeff signal value
164          * @returns deflected value
165          */
166         float log_meter_coeff (float coeff);
167
168         void process_map (BufferSet* bufs,
169                           const ChanMapping& in,
170                           const ChanMapping& out,
171                           pframes_t nframes, samplecnt_t offset,
172                           const DataType&);
173
174         /** 1st order Low Pass filter */
175         class LIBARDOUR_API LowPass {
176                 public:
177                         /** instantiate a LPF
178                          *
179                          * @param samplerate samplerate
180                          * @param freq cut-off frequency
181                          */
182                         LowPass (double samplerate, float freq);
183                         /** process audio data
184                          *
185                          * @param data pointer to audio-data
186                          * @param n_samples number of samples to process
187                          */
188                         void proc (float *data, const uint32_t n_samples);
189                         /** filter control data
190                          *
191                          * This is useful for parameter smoothing.
192                          *
193                          * @param data pointer to control-data array
194                          * @param val target value
195                          * @param array length
196                          */
197                         void ctrl (float *data, const float val, const uint32_t n_samples);
198                         /** update filter cut-off frequency
199                          *
200                          * @param freq cut-off frequency
201                          */
202                         void set_cutoff (float freq);
203                         /** reset filter state */
204                         void reset () { _z =  0.f; }
205                 private:
206                         float _rate;
207                         float _z;
208                         float _a;
209         };
210
211         /** Biquad Filter */
212         class LIBARDOUR_API Biquad {
213                 public:
214                         enum Type {
215                                 LowPass,
216                                 HighPass,
217                                 BandPassSkirt,
218                                 BandPass0dB,
219                                 Notch,
220                                 AllPass,
221                                 Peaking,
222                                 LowShelf,
223                                 HighShelf
224                         };
225
226                         /** Instantiate Biquad Filter
227                          *
228                          * @param samplerate Samplerate
229                          */
230                         Biquad (double samplerate);
231                         Biquad (const Biquad &other);
232
233                         /** process audio data
234                          *
235                          * @param data pointer to audio-data
236                          * @param n_samples number of samples to process
237                          */
238                         void run (float *data, const uint32_t n_samples);
239                         /** setup filter, compute coefficients
240                          *
241                          * @param t filter type (LowPass, HighPass, etc)
242                          * @param freq filter frequency
243                          * @param Q filter quality
244                          * @param gain filter gain
245                          */
246                         void compute (Type t, double freq, double Q, double gain);
247
248                         /** setup filter, set coefficients directly */
249                         void configure (double a1, double a2, double b0, double b1, double b2);
250
251                         /** filter transfer function (filter response for spectrum visualization)
252                          * @param freq frequency
253                          * @return gain at given frequency in dB (clamped to -120..+120)
254                          */
255                         float dB_at_freq (float freq) const;
256
257                         /** reset filter state */
258                         void reset () { _z1 = _z2 = 0.0; }
259                 private:
260                         double _rate;
261                         float  _z1, _z2;
262                         double _a1, _a2;
263                         double _b0, _b1, _b2;
264         };
265
266         class LIBARDOUR_API FFTSpectrum {
267                 public:
268                         FFTSpectrum (uint32_t window_size, double rate);
269                         ~FFTSpectrum ();
270
271                         /** set data to be analyzed and pre-process with hanning window
272                          * n_samples + offset must not be larger than the configured window_size
273                          *
274                          * @param data raw audio data
275                          * @param n_samples number of samples to write to analysis buffer
276                          * @param offset destination offset
277                          */
278                         void set_data_hann (float const * const data, const uint32_t n_samples, const uint32_t offset = 0);
279
280                         /** process current data in buffer */
281                         void execute ();
282
283                         /** query
284                          * @param bin the frequency bin 0 .. window_size / 2
285                          * @param norm gain factor (set equal to @bin for 1/f normalization)
286                          * @return signal power at given bin (in dBFS)
287                          */
288                         float power_at_bin (const uint32_t bin, const float norm = 1.f) const;
289
290                         float freq_at_bin (const uint32_t bin) const {
291                                 return bin * _fft_freq_per_bin;
292                         }
293
294                 private:
295                         static Glib::Threads::Mutex fft_planner_lock;
296                         float* hann_window;
297
298                         void init (uint32_t window_size, double rate);
299                         void reset ();
300
301                         uint32_t _fft_window_size;
302                         uint32_t _fft_data_size;
303                         double   _fft_freq_per_bin;
304
305                         float* _fft_data_in;
306                         float* _fft_data_out;
307                         float* _fft_power;
308
309                         fftwf_plan _fftplan;
310         };
311
312         class LIBARDOUR_API Generator {
313                 public:
314                         Generator ();
315
316                         enum Type {
317                                 UniformWhiteNoise,
318                                 GaussianWhiteNoise,
319                                 PinkNoise,
320                         };
321
322                         void run (float *data, const uint32_t n_samples);
323                         void set_type (Type t);
324
325                 private:
326                         uint32_t randi ();
327                         float    randf () { return (randi () / 1073741824.f) - 1.f; }
328                         float    grandf ();
329
330                         Type     _type;
331                         uint32_t _rseed;
332                         /* pink-noise */
333                         float _b0, _b1, _b2, _b3, _b4, _b5, _b6;
334                         /* gaussian white */
335                         bool _pass;
336                         float _rn;
337
338         };
339
340 } } /* namespace */
341 #endif