File: Crossover.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 (359 lines) | stat: -rw-r--r-- 15,700 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
/*
 * 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: 03 авг. 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 LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_
#define LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_

#include <lsp-plug.in/dsp-units/version.h>
#include <lsp-plug.in/dsp-units/iface/IStateDumper.h>
#include <lsp-plug.in/dsp-units/filters/Filter.h>
#include <lsp-plug.in/dsp-units/filters/Equalizer.h>

namespace lsp
{
    /*
         The overall schema of signal processing by the crossover for 4 bands
         (filters are following in order of the increasing frequency):

        INPUT = Input signal passed to the process() method
        LPF   = Low-pass filter
        HPF   = High-pass filter
        APF   = All-pass filter
        OUT   = Output signal for the particular band passed to the crossover_func_t callback function

       ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐
       │INPUT│──┬─►│LPF 0│────►│APF 1│────►│APF 2│────►│OUT 0│
       └─────┘  │  └─────┘     └─────┘     └─────┘     └─────┘
                │  ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐
                └─►│HPF 0│──┬─►│LPF 1│────►│APF 2│────►│OUT 1│
                   └─────┘  │  └─────┘     └─────┘     └─────┘
                            │  ┌─────┐     ┌─────┐     ┌─────┐
                            └─►│HPF 1│──┬─►│LPF 2│────►│OUT 2│
                               └─────┘  │  └─────┘     └─────┘
                                        │  ┌─────┐     ┌─────┐
                                        └─►│HPF 2│────►│OUT 3│
                                           └─────┘     └─────┘
     */

    namespace dspu
    {
        /**
         * Crossover callback function for processing band signal
         *
         * @param object the object that handles callback
         * @param subject the subject that is used to handle callback
         * @param band number of the band
         * @param data the output band signal produced by crossover,
         *        is valid only until the function returns
         * @param first index of the first sample in input buffer
         * @param count number of processed samples in the data buffer
         */
        typedef void (* crossover_func_t)(void *object, void *subject, size_t band, const float *data, size_t first, size_t count);

        /**
         * Crossover filter type
         */
        enum crossover_mode_t
        {
            CROSS_MODE_BT,     //!< CROSS_MODE_BT bilinear transform
            CROSS_MODE_MT      //!< CROSS_MODE_MT matched transform
        };

        /** Crossover, splits signal into bands, calls processing handler (if present)
         * and mixes processed bands back after adjusting the post-processing amplification gain
         *
         */
        class LSP_DSP_UNITS_PUBLIC Crossover
        {
            private:
                Crossover & operator = (const Crossover &);
                Crossover(const Crossover &);

            protected:
                enum xover_type_t
                {
                    FILTER_LPF,                         // Low-pass filter
                    FILTER_HPF,                         // High-pass filter
                    FILTER_APF                          // All-pass filter
                };

                typedef struct split_t
                {
                    Equalizer           sLPF;           // Lo-pass filter
                    Filter              sHPF;           // Hi-pass filter with all-pass filters

                    size_t              nBandId;        // Number of split point
                    size_t              nSlope;         // Filter slope (0 = off)
                    float               fFreq;          // Frequency
                    crossover_mode_t    nMode;          // Filter type
                } split_t;

                typedef struct band_t
                {
                    float               fGain;          // Output gain of the band
                    float               fStart;         // Start frequency of the band
                    float               fEnd;           // End frequency of the band
                    bool                bEnabled;       // Enabled flag
                    split_t            *pStart;         // Pointer to starting split point
                    split_t            *pEnd;           // Pointer to ending split point

                    crossover_func_t    pFunc;          // Function
                    void               *pObject;        // Bound object
                    void               *pSubject;       // Bound subject
                    size_t              nId;            // Number of the band
                } band_t;

                enum reconfigure_t
                {
                    R_GAIN          = 1 << 0,           // We can reconfigure band gain in softer mode
                    R_SPLIT         = 1 << 1,           // Need to reconfigure filter order

                    R_ALL           = R_GAIN | R_SPLIT
                } reconfigure_t;

            protected:
                size_t          nReconfigure;   // Change flag
                size_t          nSplits;        // Number of splits
                size_t          nBufSize;       // Buffer size
                size_t          nSampleRate;    // Sample rate

                band_t         *vBands;         // List of bands
                split_t        *vSplit;         // List of split points
                split_t       **vPlan;          // Split plan
                size_t          nPlanSize;      // Size of plan

                float          *vLpfBuf;        // Buffer for LPF
                float          *vHpfBuf;        // Buffer for HPF
                uint8_t        *pData;          // Unaligned data

            protected:
                inline filter_type_t    select_filter(xover_type_t type, crossover_mode_t mode);

            public:
                explicit Crossover();
                ~Crossover();

                /** Construct crossover
                 *
                 */
                void            construct();

                /** Destroy crossover
                 *
                 */
                void            destroy();

                /** Initialize crossover
                 *
                 * @param bands number of bands
                 * @param buf_size maximum signal processing buffer size
                 * @return status of operation
                 */
                bool            init(size_t bands, size_t buf_size);

            public:
                /**
                 * Get number of bands
                 * @return number of bands
                 */
                inline size_t   num_bands() const                       { return nSplits+1;     }

                /**
                 * Get number of split points
                 * @return number of split points
                 */
                inline size_t   num_splits() const                      { return nSplits;       }

                /**
                 * Get maximum buffer size for one iteration, if the provided
                 * buffer is greater than max_buffer_size, the signal will be processed
                 * in more than one iteration.
                 *
                 * @return maximum buffer size
                 */
                inline size_t   max_buffer_size() const                 { return nBufSize;      }

                /** Set slope of crossover
                 *
                 * @param sp split point number
                 * @param slope slope of crossover filters
                 */
                void            set_slope(size_t sp, size_t slope);

                /**
                 * Get slope of the split point
                 * @param sp split point number
                 * @return slope of the split point, 0 means split point is off,
                 *         negative value means invalid index
                 */
                ssize_t         get_slope(size_t sp) const;

                /** Set frequency of split point
                 *
                 * @param sp split point number
                 * @param freq split frequency of the split point
                 */
                void            set_frequency(size_t sp, float freq);

                /**
                 * Get split frequency of the split point
                 * @param sp split point number
                 * @return split frequency of the split point, negative value
                 *         means invalid index
                 */
                float           get_frequency(size_t sp) const;

                /**
                 * Set filter mode for the split point
                 * @param sp split point
                 * @param mode mode for the split point
                 */
                void            set_mode(size_t sp, crossover_mode_t mode);

                /**
                 * Get filter mode of the split point
                 * @param sp split point
                 * @param mode mode for the split point or negative value on invalid index
                 */
                ssize_t         get_mode(size_t sp) const;

                /**
                 * Set gain of the specific output band
                 * @param band band number
                 * @param gain gain of the band
                 */
                void            set_gain(size_t band, float gain);

                /**
                 * Get gain of the specific output band
                 * @param band band number
                 * @return gain of the band, negative value on invalid index
                 */
                float           get_gain(size_t band) const;

                /**
                 * Get start frequency of the band, may call reconfigure()
                 * @param band band number
                 * @return start frequency of the band or negative value on invalid index
                 */
                float           get_band_start(size_t band);

                /**
                 * Get end frequency of the band, may call reconfigure()
                 * @param band band number
                 * @return end frequency of the band or negative value on invalid index
                 */
                float           get_band_end(size_t band);

                /**
                 * Check that the band is active (always true for band 0), may call reconfigure()
                 * @param band band number
                 * @return true if band is active
                 */
                bool            band_active(size_t band);

                /**
                 * Set band signal handler
                 * @param band band number
                 * @param func handler function
                 * @param object object to pass to function
                 * @param subject subject to pass to function
                 * @return false if invalid band number has been specified
                 */
                bool            set_handler(size_t band, crossover_func_t func, void *object, void *subject);

                /**
                 * Unset band signal handler
                 * @param band band number
                 * @return false if invalid band number has been specified
                 */
                bool            unset_handler(size_t band);

                /** Set sample rate, needs reconfiguration
                 *
                 * @param sr sample rate to set
                 */
                void            set_sample_rate(size_t sr);

                /**
                 * Get sample rate of the crossover
                 * @return sample rate
                 */
                inline size_t   get_sample_rate()                   { return nSampleRate;           }

                /** Get frequency chart of the crossover band. This method returns frequency chart
                 * without applied all-pass filters
                 *
                 * @param band number of the band
                 * @param re real part of the frequency chart
                 * @param im imaginary part of the frequency chart
                 * @param f frequencies to calculate value
                 * @param count number of points for the chart
                 * @return false if invalid band index is specified
                 */
                bool            freq_chart(size_t band,  float *re, float *im, const float *f, size_t count);

                /** Get frequency chart of the crossover. This method returns frequency chart
                 * without applied all-pass filters
                 *
                 * @param band number of the band
                 * @param c transfer function (packed complex numbers)
                 * @param f frequencies to calculate value
                 * @param count number of points for the chart
                 * @return false if invalid band index is specified
                 */
                bool            freq_chart(size_t band, float *c, const float *f, size_t count);

                /**
                 * Check that we need to call reconfigure()
                 * @return true if we need to call reconfigure()
                 */
                inline bool     needs_reconfiguration() const       { return nReconfigure != 0;     }

                /** Reconfigure crossover after parameter update
                 *
                 */
                void            reconfigure();

                /** Process data and issue callbacks, automatically calls reconfigure()
                 * if the reconfiguration is required
                 *
                 * @param in input buffer to process data
                 * @param samples number of samples to process
                 */
                void            process(const float *in, size_t samples);

                /**
                 * Dump the state
                 * @param dumper dumper
                 */
                void            dump(IStateDumper *v) const;
        };
    }
} /* namespace lsp */

#endif /* LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_ */