libardour support for timespan realtime export
[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
29 #include "pbd/malign.h"
30
31 #include "ardour/buffer_set.h"
32 #include "ardour/chan_mapping.h"
33 #include "ardour/libardour_visibility.h"
34 #include "ardour/types.h"
35
36 namespace ARDOUR { namespace DSP {
37
38         /** C/C++ Shared Memory
39          *
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.
43          *
44          * Access to this memory area is always 4 byte aligned. The data
45          * is interpreted either as float or as int.
46          *
47          * This memory area can also be shared between different instances
48          * or the same lua plugin (DSP, GUI).
49          *
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
53          * destroyed.
54          */
55         class DspShm {
56                 public:
57                         DspShm (size_t s = 0)
58                                 : _data (0)
59                                 , _size (0)
60                         {
61                                 assert (sizeof(float) == sizeof (int32_t));
62                                 assert (sizeof(float) == sizeof (int));
63                                 allocate (s);
64                         }
65
66                         ~DspShm () {
67                                 cache_aligned_free (_data);
68                         }
69
70                         /** [re] allocate memory in host's memory space
71                          *
72                          * @param s size, total number of float or integer elements to store.
73                          */
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; }
79                         }
80
81                         /** clear memory (set to zero) */
82                         void clear () {
83                                 memset (_data, 0, sizeof(float) * _size);
84                         }
85
86                         /** access memory as float array
87                          *
88                          * @param off offset in shared memory region
89                          * @returns float[]
90                          */
91                         float* to_float (size_t off) {
92                                 if (off >= _size) { return 0; }
93                                 return &(((float*)_data)[off]);
94                         }
95
96                         /** access memory as integer array
97                          *
98                          * @param off offset in shared memory region
99                          * @returns int_32_t[]
100                          */
101                         int32_t* to_int (size_t off) {
102                                 if (off >= _size) { return 0; }
103                                 return &(((int32_t*)_data)[off]);
104                         }
105
106                         /** atomically set integer at offset
107                          *
108                          * This involves a memory barrier. This call
109                          * is intended for buffers which are
110                          * shared with another instance.
111                          *
112                          * @param off offset in shared memory region
113                          * @param val value to set
114                          */
115                         void atomic_set_int (size_t off, int32_t val) {
116                                 g_atomic_int_set (&(((int32_t*)_data)[off]), val);
117                         }
118
119                         /** atomically read integer at offset
120                          *
121                          * This involves a memory barrier. This call
122                          * is intended for buffers which are
123                          * shared with another instance.
124                          *
125                          * @param off offset in shared memory region
126                          * @returns value at offset
127                          */
128                         int32_t atomic_get_int (size_t off) {
129                                 return g_atomic_int_get (&(((int32_t*)_data)[off]));
130                         }
131
132                 private:
133                         void* _data;
134                         size_t _size;
135         };
136
137         /** lua wrapper to memset() */
138         void memset (float *data, const float val, const uint32_t n_samples);
139         /** matrix multiply
140          * multiply every sample of `data' with the corresponding sample at `mult'.
141          *
142          * @param data multiplicand
143          * @param mult multiplicand
144          * @param n_samples number of samples in data and mmult
145          */
146         void mmult (float *data, float *mult, const uint32_t n_samples);
147         /** calculate peaks
148          *
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
153          */
154         void peaks (float *data, float &min, float &max, uint32_t n_samples);
155
156         /** non-linear power-scale meter deflection
157          *
158          * @param power signal power (dB)
159          * @returns deflected value
160          */
161         float log_meter (float power);
162         /** non-linear power-scale meter deflection
163          *
164          * @param coeff signal value
165          * @returns deflected value
166          */
167         float log_meter_coeff (float coeff);
168
169         void process_map (BufferSet* bufs,
170                           const ChanMapping& in,
171                           const ChanMapping& out,
172                           pframes_t nframes, framecnt_t offset,
173                           const DataType&);
174
175         /** 1st order Low Pass filter */
176         class LIBARDOUR_API LowPass {
177                 public:
178                         /** instantiate a LPF
179                          *
180                          * @param samplerate samplerate
181                          * @param freq cut-off frequency
182                          */
183                         LowPass (double samplerate, float freq);
184                         /** process audio data
185                          *
186                          * @param data pointer to audio-data
187                          * @param n_samples number of samples to process
188                          */
189                         void proc (float *data, const uint32_t n_samples);
190                         /** filter control data
191                          *
192                          * This is useful for parameter smoothing.
193                          *
194                          * @param data pointer to control-data array
195                          * @param val target value
196                          * @param array length
197                          */
198                         void ctrl (float *data, const float val, const uint32_t n_samples);
199                         /** update filter cut-off frequency
200                          *
201                          * @param freq cut-off frequency
202                          */
203                         void set_cutoff (float freq);
204                         /** reset filter state */
205                         void reset () { _z =  0.f; }
206                 private:
207                         float _rate;
208                         float _z;
209                         float _a;
210         };
211
212         /** Biquad Filter */
213         class LIBARDOUR_API Biquad {
214                 public:
215                         enum Type {
216                                 LowPass,
217                                 HighPass,
218                                 BandPassSkirt,
219                                 BandPass0dB,
220                                 Notch,
221                                 AllPass,
222                                 Peaking,
223                                 LowShelf,
224                                 HighShelf
225                         };
226
227                         /** Instantiate Biquad Filter
228                          *
229                          * @param samplerate Samplerate
230                          */
231                         Biquad (double samplerate);
232                         Biquad (const Biquad &other);
233
234                         /** process audio data
235                          *
236                          * @param data pointer to audio-data
237                          * @param n_samples number of samples to process
238                          */
239                         void run (float *data, const uint32_t n_samples);
240                         /** setup filter, compute coefficients
241                          *
242                          * @param t filter type (LowPass, HighPass, etc)
243                          * @param freq filter frequency
244                          * @param Q filter quality
245                          * @param gain filter gain
246                          */
247                         void compute (Type t, double freq, double Q, double gain);
248
249                         /** setup filter, set coefficients directly */
250                         void configure (double a1, double a2, double b0, double b1, double b2);
251
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)
255                          */
256                         float dB_at_freq (float freq) const;
257
258                         /** reset filter state */
259                         void reset () { _z1 = _z2 = 0.0; }
260                 private:
261                         double _rate;
262                         float  _z1, _z2;
263                         double _a1, _a2;
264                         double _b0, _b1, _b2;
265         };
266
267         class LIBARDOUR_API FFTSpectrum {
268                 public:
269                         FFTSpectrum (uint32_t window_size, double rate);
270                         ~FFTSpectrum ();
271
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
274                          *
275                          * @param data raw audio data
276                          * @param n_samples number of samples to write to analysis buffer
277                          * @param offset destination offset
278                          */
279                         void set_data_hann (float const * const data, const uint32_t n_samples, const uint32_t offset = 0);
280
281                         /** process current data in buffer */
282                         void execute ();
283
284                         /** query
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)
288                          */
289                         float power_at_bin (const uint32_t bin, const float norm = 1.f) const;
290
291                         float freq_at_bin (const uint32_t bin) const {
292                                 return bin * _fft_freq_per_bin;
293                         }
294
295                 private:
296                         static Glib::Threads::Mutex fft_planner_lock;
297                         float* hann_window;
298
299                         void init (uint32_t window_size, double rate);
300                         void reset ();
301
302                         uint32_t _fft_window_size;
303                         uint32_t _fft_data_size;
304                         double   _fft_freq_per_bin;
305
306                         float* _fft_data_in;
307                         float* _fft_data_out;
308                         float* _fft_power;
309
310                         fftwf_plan _fftplan;
311         };
312
313 } } /* namespace */
314 #endif