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