add some more documentation
[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 "ardour/libardour_visibility.h"
27
28 namespace ARDOUR { namespace DSP {
29
30         /** C Shared Memory
31          *
32          * A convenience class representing a C array or float[] or int32_t[]
33          * data values. This is useful for lua scripts to perform DSP operations
34          * directly using C, C++.
35          * Access to this memory area is always 4 byte aligned: float, int.
36          *
37          * This memory area can also be shared between different instances.
38          *
39          * Since memory allocation is not realtime safe it should be
40          * allocated during dsp_init() or dsp_configure().
41          *
42          * The memory is free()ed automatically when the lua instance is
43          * destroyed.
44          */
45         class DspShm {
46                 public:
47                         DspShm ()
48                                 : _data (0)
49                                 , _size (0)
50                         {
51                                 assert (sizeof(float) == sizeof (int32_t));
52                                 assert (sizeof(float) == sizeof (int));
53                         }
54
55                         ~DspShm () {
56                                 free (_data);
57                         }
58
59                         /** [re] allocate memory in host's memory space
60                          *
61                          * @param s size, total number of float or integer elements to store.
62                          */
63                         void allocate (size_t s) {
64                                 _data = realloc (_data, sizeof(float) * s);
65                                 if (_data) { _size = s; }
66                         }
67
68                         /** clear memory (set to zero) */
69                         void clear () {
70                                 memset (_data, 0, sizeof(float) * _size);
71                         }
72
73                         /** access memory as float array
74                          *
75                          * @param off offset in shared memory region
76                          * @returns float[]
77                          */
78                         float* to_float (size_t off) {
79                                 if (off >= _size) { return 0; }
80                                 return &(((float*)_data)[off]);
81                         }
82
83                         /** access memory as integer array
84                          *
85                          * @param off offset in shared memory region
86                          * @returns int_32_t[]
87                          */
88                         int32_t* to_int (size_t off) {
89                                 if (off >= _size) { return 0; }
90                                 return &(((int32_t*)_data)[off]);
91                         }
92
93                         /** atomically set integer at offset
94                          *
95                          * This involves a memory barrier. This call
96                          * is intended for buffers which are
97                          * shared with another instance.
98                          *
99                          * @param off offset in shared memory region
100                          * @param val value to set
101                          */
102                         void atomic_set_int (size_t off, int32_t val) {
103                                 g_atomic_int_set (&(((int32_t*)_data)[off]), val);
104                         }
105
106                         /** atomically read 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                          * @returns value at offset
114                          */
115                         int32_t atomic_get_int (size_t off) {
116                                 return g_atomic_int_get (&(((int32_t*)_data)[off]));
117                         }
118
119                 private:
120                         void* _data;
121                         size_t _size;
122         };
123
124         /** lua wrapper to memset() */
125         void memset (float *data, const float val, const uint32_t n_samples);
126         /** matrix multiply
127          * multiply every sample of `data' with the corresponding sample at `mult'.
128          *
129          * @param data multiplicand
130          * @param mult multiplicand
131          * @param n_samples number of samples in data and mmult
132          */
133         void mmult (float *data, float *mult, const uint32_t n_samples);
134         /** calculate peaks
135          *
136          * @param data data to analyze
137          * @param min result, minimum value found in range
138          * @param max result, max value found in range
139          * @param n_samples number of samples to analyze
140          */
141         void peaks (float *data, float &min, float &max, uint32_t n_samples);
142
143         /** non-linear power-scale meter deflection
144          *
145          * @param power signal power (dB)
146          * @returns deflected value
147          */
148         float log_meter (float power);
149         /** non-linear power-scale meter deflection
150          *
151          * @param coeff signal value
152          * @returns deflected value
153          */
154         float log_meter_coeff (float coeff);
155
156         /** 1st order Low Pass filter */
157         class LIBARDOUR_API LowPass {
158                 public:
159                         /** instantiate a LPF
160                          *
161                          * @param samplerate samplerate
162                          * @param freq cut-off frequency
163                          */
164                         LowPass (double samplerate, float freq);
165                         /** process audio data
166                          *
167                          * @param data pointer to audio-data
168                          * @param n_samples number of samples to process
169                          */
170                         void proc (float *data, const uint32_t n_samples);
171                         /** filter control data
172                          *
173                          * This is useful for parameter smoothing.
174                          *
175                          * @param data pointer to control-data array
176                          * @param val target value
177                          * @param array length
178                          */
179                         void ctrl (float *data, const float val, const uint32_t n_samples);
180                         /** update filter cut-off frequency
181                          *
182                          * @param freq cut-off frequency
183                          */
184                         void set_cutoff (float freq);
185                         /** reset filter state */
186                         void reset () { _z =  0.f; }
187                 private:
188                         float _rate;
189                         float _z;
190                         float _a;
191         };
192
193         /** Biquad Filter */
194         class LIBARDOUR_API BiQuad {
195                 public:
196                         enum Type {
197                                 LowPass,
198                                 HighPass,
199                                 BandPassSkirt,
200                                 BandPass0dB,
201                                 Notch,
202                                 AllPass,
203                                 Peaking,
204                                 LowShelf,
205                                 HighShelf
206                         };
207
208                         /** Instantiate Biquad Filter
209                          *
210                          * @param samplerate Samplerate
211                          */
212                         BiQuad (double samplerate);
213                         BiQuad (const BiQuad &other);
214
215                         /** process audio data
216                          *
217                          * @param data pointer to audio-data
218                          * @param n_samples number of samples to process
219                          */
220                         void run (float *data, const uint32_t n_samples);
221                         /** setup filter, compute coefficients
222                          *
223                          * @param t filter type
224                          * @param freq filter frequency
225                          * @param Q filter quality
226                          * @param gain filter gain
227                          */
228                         void compute (Type t, double freq, double Q, double gain);
229                         /** reset filter state */
230                         void reset () { _z1 = _z2 = 0.0; }
231                 private:
232                         double _rate;
233                         float  _z1, _z2;
234                         double _a1, _a2;
235                         double _b0, _b1, _b2;
236         };
237
238 } } /* namespace */
239 #endif