File: Limiter.h

package info (click to toggle)
lsp-plugins 1.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 91,856 kB
  • sloc: cpp: 427,831; xml: 57,779; makefile: 9,961; php: 1,005; sh: 18
file content (374 lines) | stat: -rw-r--r-- 14,090 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/*
 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
 *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
 *
 * This file is part of lsp-dsp-units
 * Created on: 25 нояб. 2016 г.
 *
 * lsp-dsp-units is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * lsp-dsp-units is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with lsp-dsp-units. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef CORE_DYNAMICS_LIMITER_H_
#define CORE_DYNAMICS_LIMITER_H_

#include <lsp-plug.in/dsp-units/version.h>
#include <lsp-plug.in/dsp-units/iface/IStateDumper.h>
#include <lsp-plug.in/dsp-units/util/Delay.h>

#define LIMITER_PATCHES_MAX         256
#define LIMITER_PEAKS_MAX           32
#define LIMITER_LOG_PATCHES_MAX     128

namespace lsp
{
    namespace dspu
    {
        enum limiter_mode_t
        {
            LM_HERM_THIN,
            LM_HERM_WIDE,
            LM_HERM_TAIL,
            LM_HERM_DUCK,

            LM_EXP_THIN,
            LM_EXP_WIDE,
            LM_EXP_TAIL,
            LM_EXP_DUCK,

            LM_LINE_THIN,
            LM_LINE_WIDE,
            LM_LINE_TAIL,
            LM_LINE_DUCK
        };

        class LSP_DSP_UNITS_PUBLIC Limiter
        {
            private:
                Limiter & operator = (const Limiter &);
                Limiter(const Limiter &);

            protected:
                typedef void (*apply_patch_t)(void *patch, float *dst, float amp);

                enum update_t
                {
                    UP_SR       = 1 << 0,
                    UP_LK       = 1 << 1,
                    UP_MODE     = 1 << 2,
                    UP_OTHER    = 1 << 3,
                    UP_THRESH   = 1 << 4,
                    UP_ALR      = 1 << 5,

                    UP_ALL      = UP_SR | UP_LK | UP_MODE | UP_OTHER | UP_THRESH | UP_ALR
                };

                typedef struct alr_t
                {
                    float       fKS;            // Knee start
                    float       fKE;            // Knee end
                    float       fGain;          // Maximum output gain
                    float       fTauAttack;     // Attiack time constant
                    float       fTauRelease;    // Release time constant
                    float       vHermite[3];    // Hermite approximation
                    float       fAttack;        // Attack
                    float       fRelease;       // Release
                    float       fEnvelope;      // Envelope
                    bool        bEnable;        // Enable ALR
                } alr_t;

                typedef struct sat_t
                {
                    int32_t     nAttack;        // Attack
                    int32_t     nPlane;         // Plane
                    int32_t     nRelease;       // Release
                    int32_t     nMiddle;        // Middle

                    float       vAttack[4];     // Hermite interpolation of attack
                    float       vRelease[4];    // Hermite interpolation of release
                } sat_t;

                typedef struct exp_t
                {
                    int32_t     nAttack;        // Attack
                    int32_t     nPlane;         // Plane
                    int32_t     nRelease;       // Release
                    int32_t     nMiddle;        // Middle

                    float       vAttack[4];     // Exponent interpolation of attack
                    float       vRelease[4];    // Exponent interpolation of release
                } exp_t;

                typedef struct line_t
                {
                    int32_t     nAttack;        // Attack
                    int32_t     nPlane;         // Plane
                    int32_t     nRelease;       // Release
                    int32_t     nMiddle;        // Middle

                    float       vAttack[2];     // Line interpolation of attack
                    float       vRelease[2];    // Line interpolation of release
                } line_t;

            protected:
                float       fThreshold;
                float       fReqThreshold;
                float       fLookahead;
                float       fMaxLookahead;
                float       fAttack;
                float       fRelease;
                float       fKnee;
                size_t      nMaxLookahead;
                size_t      nLookahead;
                size_t      nHead;
                size_t      nMaxSampleRate;
                size_t      nSampleRate;
                size_t      nUpdate;
                size_t      nMode;
                alr_t       sALR;

                // Pre-calculated parameters
                float      *vGainBuf;
                float      *vTmpBuf;                // Temporary buffer to store the actual sidechain value
                uint8_t    *vData;

                Delay       sDelay;
                union
                {
                    sat_t       sSat;               // Hermite mode
                    exp_t       sExp;               // Exponent mode
                    line_t      sLine;              // Line mode
                };

            protected:
                inline float    sat(ssize_t n);
                inline float    exp(ssize_t n);
                inline float    line(ssize_t n);
                static void     apply_sat_patch(sat_t *sat, float *dst, float amp);
                static void     apply_exp_patch(exp_t *exp, float *dst, float amp);
                static void     apply_line_patch(line_t *line, float *dst, float amp);

                static void     reset_sat(sat_t *sat);
                static void     reset_exp(exp_t *exp);
                static void     reset_line(line_t *line);

                void            init_sat(sat_t *sat);
                void            init_exp(exp_t *exp);
                void            init_line(line_t *line);

                void            process_alr(float *gbuf, const float *sc, size_t samples);

                static void     dump(IStateDumper *v, const char *name, const sat_t *sat);
                static void     dump(IStateDumper *v, const char *name, const exp_t *exp);
                static void     dump(IStateDumper *v, const char *name, const line_t *line);

            public:
                explicit Limiter();
                ~Limiter();

                /**
                 * Construct the object
                 */
                void construct();

                /** Destroy all data allocated by processor
                 *
                 */
                void destroy();

            public:
                /** Initialize limiter
                 *
                 * @param max_sr maximum sample rate that can be passed to limiter
                 * @param max_lookahead maximum look-ahead time that can be passed to limiter [ms]
                 * @return true on success
                 */
                bool init(size_t max_sr, float max_lookahead);

                /** Check if limiter is modifier
                 *
                 * @return true if limiter settings need to be updated
                 */
                inline bool modified() const                            { return nUpdate != 0;          }

                /** Update settings for limiter
                 *
                 */
                void update_settings();

                /**
                 * Get limiter mode
                 * @return limiter mode
                 */
                inline limiter_mode_t get_mode() const                  { return limiter_mode_t(nMode); }

                /** Set limiter working mode
                 *
                 * @param mode limiter working mode
                 */
                inline void set_mode(limiter_mode_t mode)
                {
                    if (mode == nMode)
                        return;
                    nMode = mode;
                    nUpdate |= UP_MODE;
                }

                /** Change current sample rate of processor
                 *
                 * @param sr sample rate to set
                 */
                inline void set_sample_rate(size_t sr)
                {
                    if (sr == nSampleRate)
                        return;
                    nSampleRate     = sr;
                    nUpdate        |= UP_SR;
                }

                /** Get threshold
                 *
                 * @return threshold
                 */
                inline float        get_threshold() const               { return fReqThreshold;     }

                /** Set limiter threshold
                 *
                 * @param thresh limiter threshold
                 * @param immediate immediately set threshold, no need to perform automated gain lowering
                 */
                float               set_threshold(float thresh, bool immediate);

                /**
                 * Get attack time
                 * @return attack time
                 */
                inline float        get_attack() const                  { return fAttack;           }

                /** Set attack time
                 *
                 * @param attack attack time
                 */
                float               set_attack(float attack);

                /**
                 * Get release time
                 * @return attack time
                 */
                inline float        get_release() const                 { return fRelease;          }

                /** Set release time
                 *
                 * @param release release time
                 */
                float               set_release(float release);

                /**
                 * Get lookahead time
                 * @return lookahead time
                 */
                inline float        get_lookahead() const               { return fLookahead;        }

                /** Set look-ahead time
                 *
                 * @param lk_ahead look-ahead time
                 */
                float               set_lookahead(float lk_ahead);

                /**
                 * Get maximum possible latency according to the configuration
                 * @return maximum possible latency
                 */
                inline size_t       max_latency() const                 { return nMaxLookahead;     }

                /**
                 * Get knee of the limiter
                 * @return knee of the limiter
                 */
                inline float        get_knee() const                    { return fKnee;             }

                /** Set knee, the value not greater than 1.0
                 * If value is 1.0, there is no knee at all
                 * Other values indicate gain offset below the threshold.
                 * The same offset above threshold will be automatically calculated.
                 *
                 * @param knee knee, 1.0 means no knee
                 */
                float               set_knee(float knee);

                /** Get latency of limiter
                 *
                 * @return limiter's latency
                 */
                inline size_t       get_latency() const                 { return nLookahead;        }

                /**
                 * Get automatic level regulation attack
                 * @return automatic level regulation attack
                 */
                inline float        get_alr_attack() const              { return sALR.fAttack;      }

                /**
                 * Set automatic level regulation attack
                 * @param attack attack value
                 * @return previous value
                 */
                float               set_alr_attack(float attack);

                /**
                 * Get automatic level regulation release
                 * @return automatic level regulation attack
                 */
                inline float        get_alr_release() const             { return sALR.fRelease;     }

                /**
                 * Set automatic level regulation release
                 * @param attack attack value
                 * @return previous value
                 */
                float               set_alr_release(float attack);

                /**
                 * Check that automatic level regulation is turned on
                 * @return true if automatic level regulation is turned on
                 */
                inline bool         get_alr() const                     { return sALR.bEnable;      }

                /** Enable automatic level regulation
                 *
                 * @param enable enable flag
                 * @return previous value
                 */
                bool                set_alr(bool enable);

                /** Process data by limiter
                 *
                 * @param dst destination buffer with applied delay
                 * @param gain output gain for VCA
                 * @param src input signal buffer
                 * @param sc sidechain input signal
                 * @param samples number of samples to process
                 */
                void                process(float *dst, float *gain, const float *src, const float *sc, size_t samples);
    
                /**
                 * Dump internal state
                 * @param v state dumper
                 */
                void                dump(IStateDumper *v) const;
        };
    }

} /* namespace lsp */

#endif /* CORE_DYNAMICS_LIMITER_H_ */