1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 30 янв. 2018 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <core/debug.h>
23 #include <core/colors.h>
24 #include <core/util/Color.h>
25 #include <plugins/mb_compressor.h>
26 
27 #define MBC_BUFFER_SIZE         0x1000
28 #define TRACE_PORT(p)           lsp_trace("  port id=%s", (p)->metadata()->id);
29 
30 namespace lsp
31 {
32     //-------------------------------------------------------------------------
33     // Multiband compressor base class
mb_compressor_base(const plugin_metadata_t & metadata,bool sc,size_t mode)34     mb_compressor_base::mb_compressor_base(const plugin_metadata_t &metadata, bool sc, size_t mode): plugin_t(metadata)
35     {
36         nMode           = mode;
37         bSidechain      = sc;
38         bEnvUpdate      = true;
39         bModern         = true;
40         nEnvBoost       = mb_compressor_base_metadata::FB_DEFAULT;
41         vChannels       = NULL;
42         fInGain         = GAIN_AMP_0_DB;
43         fDryGain        = GAIN_AMP_M_INF_DB;
44         fWetGain        = GAIN_AMP_0_DB;
45         fZoom           = GAIN_AMP_0_DB;
46         pData           = NULL;
47         vTr             = NULL;
48         vPFc            = NULL;
49         vRFc            = NULL;
50         vFreqs          = NULL;
51         vCurve          = NULL;
52         vIndexes        = NULL;
53         pIDisplay       = NULL;
54         vSc[0]          = NULL;
55         vSc[1]          = NULL;
56         vAnalyze[0]     = NULL;
57         vAnalyze[1]     = NULL;
58         vAnalyze[2]     = NULL;
59         vAnalyze[3]     = NULL;
60         vBuffer         = NULL;
61         vEnv            = NULL;
62 
63         pBypass         = NULL;
64         pMode           = NULL;
65         pInGain         = NULL;
66         pDryGain        = NULL;
67         pWetGain        = NULL;
68         pOutGain        = NULL;
69         pReactivity     = NULL;
70         pShiftGain      = NULL;
71         pZoom           = NULL;
72         pEnvBoost       = NULL;
73     }
74 
~mb_compressor_base()75     mb_compressor_base::~mb_compressor_base()
76     {
77     }
78 
compare_bands_for_sort(const comp_band_t * b1,const comp_band_t * b2)79     bool mb_compressor_base::compare_bands_for_sort(const comp_band_t *b1, const comp_band_t *b2)
80     {
81         if (b1->fFreqStart != b2->fFreqStart)
82             return (b1->fFreqStart > b2->fFreqStart);
83         return b1 < b2;
84     }
85 
decode_mode(int mode)86     compressor_mode_t mb_compressor_base::decode_mode(int mode)
87     {
88         switch (mode)
89         {
90             case mb_compressor_base_metadata::CM_DOWNWARD: return CM_DOWNWARD;
91             case mb_compressor_base_metadata::CM_UPWARD: return CM_UPWARD;
92             case mb_compressor_base_metadata::CM_BOOSTING: return CM_BOOSTING;
93             default: return CM_DOWNWARD;
94         }
95     }
96 
init(IWrapper * wrapper)97     void mb_compressor_base::init(IWrapper *wrapper)
98     {
99         // Initialize plugin
100         plugin_t::init(wrapper);
101 
102         // Determine number of channels
103         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
104 
105         // Allocate channels
106         vChannels       = new channel_t[channels];
107         if (vChannels == NULL)
108             return;
109 
110         // Initialize analyzer
111         size_t an_cid       = 0;
112         if (!sAnalyzer.init(2*channels, mb_compressor_base_metadata::FFT_RANK,
113                             MAX_SAMPLE_RATE, mb_compressor_base_metadata::REFRESH_RATE))
114             return;
115 
116         sAnalyzer.set_rank(mb_compressor_base_metadata::FFT_RANK);
117         sAnalyzer.set_activity(false);
118         sAnalyzer.set_envelope(envelope::WHITE_NOISE);
119         sAnalyzer.set_window(mb_compressor_base_metadata::FFT_WINDOW);
120         sAnalyzer.set_rate(mb_compressor_base_metadata::REFRESH_RATE);
121 
122         size_t filter_mesh_size = ALIGN_SIZE(mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(float), DEFAULT_ALIGN);
123 
124         // Allocate float buffer data
125         size_t to_alloc =
126                 // Global buffers
127                 2 * filter_mesh_size + // vTr (both complex and real)
128                 2 * filter_mesh_size + // vFc (both complex and real)
129                 2 * filter_mesh_size + // vSig (both complex and real)
130                 mb_compressor_base_metadata::CURVE_MESH_SIZE * sizeof(float) + // Curve
131                 mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(float) + // vFreqs array
132                 mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(uint32_t) + // vIndexes array
133                 MBC_BUFFER_SIZE * sizeof(float) + // Global vBuffer for band signal processing
134                 MBC_BUFFER_SIZE * sizeof(float) + // Global vEnv for band signal processing
135                 // Channel buffers
136                 (
137                     MBC_BUFFER_SIZE * sizeof(float) + // Global vSc[] for each channel
138                     2 * filter_mesh_size + // vTr of each channel
139                     filter_mesh_size + // vTrMem of each channel
140                     MBC_BUFFER_SIZE * sizeof(float) + // vInBuffer for each channel
141                     MBC_BUFFER_SIZE * sizeof(float) + // vBuffer for each channel
142                     MBC_BUFFER_SIZE * sizeof(float) + // vScBuffer for each channel
143                     ((bSidechain) ? MBC_BUFFER_SIZE * sizeof(float) : 0) + // vExtScBuffer for each channel
144                     MBC_BUFFER_SIZE * sizeof(float) * 2 + // vInAnalyze + vOutAnalyze for each channel
145                     // Band buffers
146                     (
147                         MBC_BUFFER_SIZE * sizeof(float) + // vVCA of each band
148                         mb_compressor_base_metadata::FFT_MESH_POINTS * 2 * sizeof(float) // vTr transfer function for each band
149                     ) * mb_compressor_base_metadata::BANDS_MAX
150                 ) * channels;
151 
152         uint8_t *ptr    = alloc_aligned<uint8_t>(pData, to_alloc);
153         if (ptr == NULL)
154             return;
155         lsp_guard_assert(uint8_t *save   = ptr);
156 
157         // Remember the pointer to frequencies buffer
158         vTr             = reinterpret_cast<float *>(ptr);
159         ptr            += filter_mesh_size * 2;
160         vPFc             = reinterpret_cast<float *>(ptr);
161         ptr            += filter_mesh_size * 2;
162         vRFc            = reinterpret_cast<float *>(ptr);
163         ptr            += filter_mesh_size * 2;
164         vFreqs          = reinterpret_cast<float *>(ptr);
165         ptr            += mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(float);
166         vCurve          = reinterpret_cast<float *>(ptr);
167         ptr            += mb_compressor_base_metadata::CURVE_MESH_SIZE * sizeof(float);
168         vIndexes        = reinterpret_cast<uint32_t *>(ptr);
169         ptr            += mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(uint32_t);
170         vSc[0]          = reinterpret_cast<float *>(ptr);
171         ptr            += MBC_BUFFER_SIZE * sizeof(float);
172         if (channels > 1)
173         {
174             vSc[1]          = reinterpret_cast<float *>(ptr);
175             ptr            += MBC_BUFFER_SIZE * sizeof(float);
176         }
177         else
178             vSc[1]          = NULL;
179         vBuffer         = reinterpret_cast<float *>(ptr);
180         ptr            += MBC_BUFFER_SIZE * sizeof(float);
181         vEnv            = reinterpret_cast<float *>(ptr);
182         ptr            += MBC_BUFFER_SIZE * sizeof(float);
183 
184         // Initialize filters according to number of bands
185         if (sFilters.init(mb_compressor_base_metadata::BANDS_MAX * channels) != STATUS_OK)
186             return;
187         size_t filter_cid = 0;
188 
189         // Initialize channels
190         for (size_t i=0; i<channels; ++i)
191         {
192             channel_t *c    = &vChannels[i];
193 
194             if (!c->sEnvBoost[0].init(NULL))
195                 return;
196             if (bSidechain)
197             {
198                 if (!c->sEnvBoost[1].init(NULL))
199                     return;
200             }
201 
202             c->nPlanSize    = 0;
203             c->vIn          = NULL;
204             c->vOut         = NULL;
205             c->vScIn        = NULL;
206 
207             c->vInBuffer    = reinterpret_cast<float *>(ptr);
208             ptr            += MBC_BUFFER_SIZE * sizeof(float);
209             c->vBuffer      = reinterpret_cast<float *>(ptr);
210             ptr            += MBC_BUFFER_SIZE * sizeof(float);
211             c->vScBuffer    = reinterpret_cast<float *>(ptr);
212             ptr            += MBC_BUFFER_SIZE * sizeof(float);
213             c->vExtScBuffer = NULL;
214             if (bSidechain)
215             {
216                 c->vExtScBuffer = reinterpret_cast<float *>(ptr);
217                 ptr            += MBC_BUFFER_SIZE * sizeof(float);
218             }
219             c->vTr          = reinterpret_cast<float *>(ptr);
220             ptr            += 2 * filter_mesh_size;
221             c->vTrMem       = reinterpret_cast<float *>(ptr);
222             ptr            += filter_mesh_size;
223             c->vInAnalyze   = reinterpret_cast<float *>(ptr);
224             ptr            += MBC_BUFFER_SIZE * sizeof(float);
225             c->vOutAnalyze  = reinterpret_cast<float *>(ptr);
226             ptr            += MBC_BUFFER_SIZE * sizeof(float);
227 
228             c->nAnInChannel = an_cid++;
229             c->nAnOutChannel= an_cid++;
230             vAnalyze[c->nAnInChannel]   = c->vInAnalyze;
231             vAnalyze[c->nAnOutChannel]  = c->vOutAnalyze;
232 
233             c->bInFft       = false;
234             c->bOutFft      = false;
235 
236             c->pIn          = NULL;
237             c->pOut         = NULL;
238             c->pScIn        = NULL;
239             c->pFftIn       = NULL;
240             c->pFftInSw     = NULL;
241             c->pFftOut      = NULL;
242             c->pFftOutSw    = NULL;
243 
244             c->pAmpGraph    = NULL;
245             c->pInLvl       = NULL;
246             c->pOutLvl      = NULL;
247 
248             // Initialize bands
249             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
250             {
251                 comp_band_t *b  = &c->vBands[j];
252 
253                 if (!b->sSC.init(channels, mb_compressor_base_metadata::REACTIVITY_MAX))
254                     return;
255                 if (!b->sPassFilter.init(NULL))
256                     return;
257                 if (!b->sRejFilter.init(NULL))
258                     return;
259                 if (!b->sAllFilter.init(NULL))
260                     return;
261 
262                 // Initialize sidechain equalizers
263                 b->sEQ[0].init(2, 6);
264                 b->sEQ[0].set_mode(EQM_IIR);
265                 if (channels > 1)
266                 {
267                     b->sEQ[1].init(2, 6);
268                     b->sEQ[1].set_mode(EQM_IIR);
269                 }
270 
271                 b->vVCA         = reinterpret_cast<float *>(ptr);
272                 ptr            += MBC_BUFFER_SIZE * sizeof(float);
273                 b->vTr          = reinterpret_cast<float *>(ptr);
274                 ptr            += mb_compressor_base_metadata::FFT_MESH_POINTS * sizeof(float) * 2;
275 
276                 b->fScPreamp    = GAIN_AMP_0_DB;
277 
278                 b->fFreqStart   = 0.0f;
279                 b->fFreqEnd     = 0.0f;
280 
281                 b->fFreqHCF     = 0.0f;
282                 b->fFreqLCF     = 0.0f;
283                 b->fMakeup      = GAIN_AMP_0_DB;
284                 b->fGainLevel   = GAIN_AMP_0_DB;
285                 b->bEnabled     = j < mb_compressor_base_metadata::BANDS_DFL;
286                 b->bCustHCF     = false;
287                 b->bCustLCF     = false;
288                 b->bMute        = false;
289                 b->bSolo        = false;
290                 b->bExtSc       = false;
291                 b->nSync        = S_ALL;
292                 b->nFilterID    = filter_cid++;
293 
294                 b->pExtSc       = NULL;
295                 b->pScSource    = NULL;
296                 b->pScMode      = NULL;
297                 b->pScLook      = NULL;
298                 b->pScReact     = NULL;
299                 b->pScPreamp    = NULL;
300                 b->pScLpfOn     = NULL;
301                 b->pScHpfOn     = NULL;
302                 b->pScLcfFreq   = NULL;
303                 b->pScHcfFreq   = NULL;
304                 b->pScFreqChart = NULL;
305 
306                 b->pMode        = NULL;
307                 b->pEnable      = NULL;
308                 b->pSolo        = NULL;
309                 b->pMute        = NULL;
310                 b->pAttLevel    = NULL;
311                 b->pAttTime     = NULL;
312                 b->pRelLevel    = NULL;
313                 b->pRelTime     = NULL;
314                 b->pRatio       = NULL;
315                 b->pKnee        = NULL;
316                 b->pBThresh     = NULL;
317                 b->pBoost       = NULL;
318                 b->pMakeup      = NULL;
319                 b->pFreqEnd     = NULL;
320                 b->pCurveGraph  = NULL;
321                 b->pRelLevelOut = NULL;
322                 b->pEnvLvl      = NULL;
323                 b->pCurveLvl    = NULL;
324                 b->pMeterGain   = NULL;
325             }
326 
327             // Initialize split
328             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX-1; ++j)
329             {
330                 split_t *s      = &c->vSplit[j];
331 
332                 s->bEnabled     = false;
333                 s->fFreq        = 0.0f;
334 
335                 s->pEnabled     = NULL;
336                 s->pFreq        = NULL;
337             }
338         }
339 
340         lsp_assert(ptr <= &save[to_alloc]);
341 
342         // Bind ports
343         size_t port_id              = 0;
344 
345         // Input ports
346         lsp_trace("Binding input ports");
347         for (size_t i=0; i<channels; ++i)
348         {
349             TRACE_PORT(vPorts[port_id]);
350             vChannels[i].pIn        =   vPorts[port_id++];
351         }
352 
353         // Input ports
354         lsp_trace("Binding output ports");
355         for (size_t i=0; i<channels; ++i)
356         {
357             TRACE_PORT(vPorts[port_id]);
358             vChannels[i].pOut       =   vPorts[port_id++];
359         }
360 
361         // Input ports
362         if (bSidechain)
363         {
364             lsp_trace("Binding sidechain ports");
365             for (size_t i=0; i<channels; ++i)
366             {
367                 TRACE_PORT(vPorts[port_id]);
368                 vChannels[i].pScIn      =   vPorts[port_id++];
369             }
370         }
371 
372         // Common ports
373         lsp_trace("Binding common ports");
374         TRACE_PORT(vPorts[port_id]);
375         pBypass                 = vPorts[port_id++];
376         TRACE_PORT(vPorts[port_id]);
377         pMode                   = vPorts[port_id++];
378         TRACE_PORT(vPorts[port_id]);
379         pInGain                 = vPorts[port_id++];
380         TRACE_PORT(vPorts[port_id]);
381         pOutGain                = vPorts[port_id++];
382         TRACE_PORT(vPorts[port_id]);
383         pDryGain                = vPorts[port_id++];
384         TRACE_PORT(vPorts[port_id]);
385         pWetGain                = vPorts[port_id++];
386         TRACE_PORT(vPorts[port_id]);
387         pReactivity             = vPorts[port_id++];
388         TRACE_PORT(vPorts[port_id]);
389         pShiftGain              = vPorts[port_id++];
390         TRACE_PORT(vPorts[port_id]);
391         pZoom                   = vPorts[port_id++];
392         TRACE_PORT(vPorts[port_id]);
393         pEnvBoost               = vPorts[port_id++];
394         TRACE_PORT(vPorts[port_id]);
395         port_id++;         // Skip band selector
396 
397         lsp_trace("Binding channel ports");
398         for (size_t i=0; i<channels; ++i)
399         {
400             channel_t *c    = &vChannels[i];
401 
402             if ((i > 0) && (nMode == MBCM_STEREO))
403             {
404                 channel_t *sc           = &vChannels[0];
405                 c->pAmpGraph            = sc->pAmpGraph;
406             }
407             else
408             {
409                 TRACE_PORT(vPorts[port_id]);
410                 port_id++;         // Skip filter switch
411                 TRACE_PORT(vPorts[port_id]);
412                 c->pAmpGraph            = vPorts[port_id++];
413             }
414         }
415 
416         lsp_trace("Binding meters");
417         for (size_t i=0; i<channels; ++i)
418         {
419             channel_t *c    = &vChannels[i];
420 
421             TRACE_PORT(vPorts[port_id]);
422             c->pFftInSw             = vPorts[port_id++];
423             TRACE_PORT(vPorts[port_id]);
424             c->pFftOutSw            = vPorts[port_id++];
425             TRACE_PORT(vPorts[port_id]);
426             c->pFftIn               = vPorts[port_id++];
427             TRACE_PORT(vPorts[port_id]);
428             c->pFftOut              = vPorts[port_id++];
429             TRACE_PORT(vPorts[port_id]);
430             c->pInLvl               = vPorts[port_id++];
431             TRACE_PORT(vPorts[port_id]);
432             c->pOutLvl              = vPorts[port_id++];
433         }
434 
435         // Split frequencies
436         lsp_trace("Binding split frequencies");
437         for (size_t i=0; i<channels; ++i)
438         {
439             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX-1; ++j)
440             {
441                 split_t *s      = &vChannels[i].vSplit[j];
442 
443                 if ((i > 0) && (nMode == MBCM_STEREO))
444                 {
445                     split_t *sc     = &vChannels[0].vSplit[j];
446                     s->pEnabled     = sc->pEnabled;
447                     s->pFreq        = sc->pFreq;
448                 }
449                 else
450                 {
451                     TRACE_PORT(vPorts[port_id]);
452                     s->pEnabled     = vPorts[port_id++];
453                     TRACE_PORT(vPorts[port_id]);
454                     s->pFreq        = vPorts[port_id++];
455                 }
456             }
457         }
458 
459         // Compressor bands
460         lsp_trace("Binding compressor bands");
461         for (size_t i=0; i<channels; ++i)
462         {
463             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
464             {
465                 comp_band_t *b  = &vChannels[i].vBands[j];
466 
467                 if ((i > 0) && (nMode == MBCM_STEREO))
468                 {
469                     comp_band_t *sb     = &vChannels[0].vBands[j];
470 
471                     b->pExtSc       = sb->pExtSc;
472                     b->pScSource    = sb->pScSource;
473                     b->pScMode      = sb->pScMode;
474                     b->pScLook      = sb->pScLook;
475                     b->pScReact     = sb->pScReact;
476                     b->pScPreamp    = sb->pScPreamp;
477                     b->pScLpfOn     = sb->pScLpfOn;
478                     b->pScHpfOn     = sb->pScHpfOn;
479                     b->pScLcfFreq   = sb->pScLcfFreq;
480                     b->pScHcfFreq   = sb->pScHcfFreq;
481                     b->pScFreqChart = sb->pScFreqChart;
482 
483                     b->pMode        = sb->pMode;
484                     b->pEnable      = sb->pEnable;
485                     b->pSolo        = sb->pSolo;
486                     b->pMute        = sb->pMute;
487                     b->pAttLevel    = sb->pAttLevel;
488                     b->pAttTime     = sb->pAttTime;
489                     b->pRelLevel    = sb->pRelLevel;
490                     b->pRelTime     = sb->pRelTime;
491                     b->pRatio       = sb->pRatio;
492                     b->pKnee        = sb->pKnee;
493                     b->pBThresh     = sb->pBThresh;
494                     b->pBoost       = sb->pBoost;
495                     b->pMakeup      = sb->pMakeup;
496 
497                     b->pFreqEnd     = sb->pFreqEnd;
498                     b->pCurveGraph  = sb->pCurveGraph;
499                     b->pRelLevelOut = sb->pRelLevelOut;
500                     b->pEnvLvl      = sb->pEnvLvl;
501                     b->pCurveLvl    = sb->pCurveLvl;
502                     b->pMeterGain   = sb->pMeterGain;
503                 }
504                 else
505                 {
506                     if (bSidechain)
507                     {
508                         TRACE_PORT(vPorts[port_id]);
509                         b->pExtSc       = vPorts[port_id++];
510                     }
511                     if (nMode != MBCM_MONO)
512                     {
513                         TRACE_PORT(vPorts[port_id]);
514                         b->pScSource    = vPorts[port_id++];
515                     }
516                     TRACE_PORT(vPorts[port_id]);
517                     b->pScMode      = vPorts[port_id++];
518                     TRACE_PORT(vPorts[port_id]);
519                     b->pScLook      = vPorts[port_id++];
520                     TRACE_PORT(vPorts[port_id]);
521                     b->pScReact     = vPorts[port_id++];
522                     TRACE_PORT(vPorts[port_id]);
523                     b->pScPreamp    = vPorts[port_id++];
524                     TRACE_PORT(vPorts[port_id]);
525                     b->pScLpfOn     = vPorts[port_id++];
526                     TRACE_PORT(vPorts[port_id]);
527                     b->pScHpfOn     = vPorts[port_id++];
528                     TRACE_PORT(vPorts[port_id]);
529                     b->pScLcfFreq   = vPorts[port_id++];
530                     TRACE_PORT(vPorts[port_id]);
531                     b->pScHcfFreq   = vPorts[port_id++];
532                     TRACE_PORT(vPorts[port_id]);
533                     b->pScFreqChart = vPorts[port_id++];
534 
535                     TRACE_PORT(vPorts[port_id]);
536                     b->pMode        = vPorts[port_id++];
537                     TRACE_PORT(vPorts[port_id]);
538                     b->pEnable      = vPorts[port_id++];
539                     TRACE_PORT(vPorts[port_id]);
540                     b->pSolo        = vPorts[port_id++];
541                     TRACE_PORT(vPorts[port_id]);
542                     b->pMute        = vPorts[port_id++];
543                     TRACE_PORT(vPorts[port_id]);
544                     b->pAttLevel    = vPorts[port_id++];
545                     TRACE_PORT(vPorts[port_id]);
546                     b->pAttTime     = vPorts[port_id++];
547                     TRACE_PORT(vPorts[port_id]);
548                     b->pRelLevel    = vPorts[port_id++];
549                     TRACE_PORT(vPorts[port_id]);
550                     b->pRelTime     = vPorts[port_id++];
551                     TRACE_PORT(vPorts[port_id]);
552                     b->pRatio       = vPorts[port_id++];
553                     TRACE_PORT(vPorts[port_id]);
554                     b->pKnee        = vPorts[port_id++];
555                     TRACE_PORT(vPorts[port_id]);
556                     b->pBThresh     = vPorts[port_id++];
557                     TRACE_PORT(vPorts[port_id]);
558                     b->pBoost       = vPorts[port_id++];
559                     TRACE_PORT(vPorts[port_id]);
560                     b->pMakeup      = vPorts[port_id++];
561 
562                     // Skip hue
563                     TRACE_PORT(vPorts[port_id]);
564                     port_id ++;
565 
566                     TRACE_PORT(vPorts[port_id]);
567                     b->pFreqEnd     = vPorts[port_id++];
568                     TRACE_PORT(vPorts[port_id]);
569                     b->pCurveGraph  = vPorts[port_id++];
570                     TRACE_PORT(vPorts[port_id]);
571                     b->pRelLevelOut = vPorts[port_id++];
572                     TRACE_PORT(vPorts[port_id]);
573                     b->pEnvLvl      = vPorts[port_id++];
574                     TRACE_PORT(vPorts[port_id]);
575                     b->pCurveLvl    = vPorts[port_id++];
576                     TRACE_PORT(vPorts[port_id]);
577                     b->pMeterGain   = vPorts[port_id++];
578                 }
579             }
580         }
581 
582         // Initialize curve (logarithmic) in range of -72 .. +24 db
583         float delta = (mb_compressor_base_metadata::CURVE_DB_MAX - mb_compressor_base_metadata::CURVE_DB_MIN) / (mb_compressor_base_metadata::CURVE_MESH_SIZE-1);
584         for (size_t i=0; i<mb_compressor_base_metadata::CURVE_MESH_SIZE; ++i)
585             vCurve[i]   = db_to_gain(mb_compressor_base_metadata::CURVE_DB_MIN + delta * i);
586     }
587 
destroy()588     void mb_compressor_base::destroy()
589     {
590         // Determine number of channels
591         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
592 
593         // Destroy channels
594         if (vChannels != NULL)
595         {
596             for (size_t i=0; i<channels; ++i)
597             {
598                 channel_t *c    = &vChannels[i];
599 
600                 c->sEnvBoost[0].destroy();
601                 c->sEnvBoost[1].destroy();
602                 c->sDelay.destroy();
603 
604                 c->vBuffer      = NULL;
605 
606                 for (size_t i=0; i<mb_compressor_base_metadata::BANDS_MAX; ++i)
607                 {
608                     comp_band_t *b  = &c->vBands[i];
609 
610                     b->sEQ[0].destroy();
611                     b->sEQ[1].destroy();
612                     b->sSC.destroy();
613                     b->sDelay.destroy();
614 
615                     b->sPassFilter.destroy();
616                     b->sRejFilter.destroy();
617                     b->sAllFilter.destroy();
618                 }
619             }
620 
621             delete [] vChannels;
622             vChannels       = NULL;
623         }
624 
625         // Destroy dynamic filters
626         sFilters.destroy();
627 
628         // Destroy data
629         if (pData != NULL)
630             free_aligned(pData);
631 
632         if (pIDisplay != NULL)
633         {
634             pIDisplay->detroy();
635             pIDisplay   = NULL;
636         }
637 
638         // Destroy analyzer
639         sAnalyzer.destroy();
640 
641         // Destroy plugin
642         plugin_t::destroy();
643     }
644 
update_settings()645     void mb_compressor_base::update_settings()
646     {
647         filter_params_t fp;
648 
649         // Determine number of channels
650         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
651         int active_channels = 0;
652         size_t env_boost    = pEnvBoost->getValue();
653 
654         // Determine work mode: classic or modern
655         bool modern         = pMode->getValue() >= 0.5f;
656         if (modern != bModern)
657         {
658             bModern             = modern;
659             for (size_t i=0; i<channels; ++i)
660                 vChannels[i].nPlanSize      = 0;
661         }
662 
663         // Store gain
664         float out_gain      = pOutGain->getValue();
665         fInGain             = pInGain->getValue();
666         fDryGain            = out_gain * pDryGain->getValue();
667         fWetGain            = out_gain * pWetGain->getValue();
668         fZoom               = pZoom->getValue();
669 
670         // Configure channels
671         for (size_t i=0; i<channels; ++i)
672         {
673             channel_t *c    = &vChannels[i];
674 
675             // Update bypass settings
676             c->sBypass.set_bypass(pBypass->getValue());
677 
678             // Update frequency split bands
679             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX-1; ++j)
680             {
681                 split_t *s      = &c->vSplit[j];
682 
683                 bool enabled    = s->bEnabled;
684                 s->bEnabled     = s->pEnabled->getValue() >= 0.5f;
685                 if (enabled != s->bEnabled)
686                     c->nPlanSize    = 0;
687 
688                 float v         = s->fFreq;
689                 s->fFreq        = s->pFreq->getValue();
690                 if (v != s->fFreq)
691                     c->nPlanSize    = 0;
692             }
693 
694             // Update analyzer settings
695             c->bInFft       = c->pFftInSw->getValue() >= 0.5f;
696             c->bOutFft      = c->pFftOutSw->getValue() >= 0.5f;
697 
698             sAnalyzer.enable_channel(c->nAnInChannel, c->bInFft);
699             sAnalyzer.enable_channel(c->nAnOutChannel, c->pFftOutSw->getValue()  >= 0.5f);
700 
701             if (sAnalyzer.channel_active(c->nAnInChannel))
702                 active_channels ++;
703             if (sAnalyzer.channel_active(c->nAnOutChannel))
704                 active_channels ++;
705 
706             // Update envelope boost filters
707             if ((env_boost != nEnvBoost) || (bEnvUpdate))
708             {
709                 fp.fFreq        = mb_compressor_base_metadata::FREQ_BOOST_MIN;
710                 fp.fFreq2       = 0.0f;
711                 fp.fGain        = 1.0f;
712                 fp.fQuality     = 0.0f;
713 
714                 switch (env_boost)
715                 {
716                     case mb_compressor_base_metadata::FB_BT_3DB:
717                         fp.nType        = FLT_BT_RLC_ENVELOPE;
718                         fp.nSlope       = 1;
719                         break;
720                     case mb_compressor_base_metadata::FB_MT_3DB:
721                         fp.nType        = FLT_MT_RLC_ENVELOPE;
722                         fp.nSlope       = 1;
723                         break;
724                     case mb_compressor_base_metadata::FB_BT_6DB:
725                         fp.nType        = FLT_BT_RLC_ENVELOPE;
726                         fp.nSlope       = 2;
727                         break;
728                     case mb_compressor_base_metadata::FB_MT_6DB:
729                         fp.nType        = FLT_MT_RLC_ENVELOPE;
730                         fp.nSlope       = 2;
731                         break;
732                     case mb_compressor_base_metadata::FB_OFF:
733                     default:
734                         fp.nType        = FLT_NONE;
735                         fp.nSlope       = 1;
736                         break;
737                 }
738 
739                 c->sEnvBoost[0].update(fSampleRate, &fp);
740                 if (bSidechain)
741                     c->sEnvBoost[1].update(fSampleRate, &fp);
742             }
743         }
744 
745         // Update analyzer parameters
746         sAnalyzer.set_reactivity(pReactivity->getValue());
747         if (pShiftGain != NULL)
748             sAnalyzer.set_shift(pShiftGain->getValue() * 100.0f);
749         sAnalyzer.set_activity(active_channels > 0);
750 
751         // Update analyzer
752         if (sAnalyzer.needs_reconfiguration())
753         {
754             sAnalyzer.reconfigure();
755             sAnalyzer.get_frequencies(vFreqs, vIndexes, SPEC_FREQ_MIN, SPEC_FREQ_MAX, mb_compressor_base_metadata::MESH_POINTS);
756         }
757 
758         size_t latency = 0;
759         bool solo_on = false;
760 
761         // Configure channels
762         for (size_t i=0; i<channels; ++i)
763         {
764             channel_t *c    = &vChannels[i];
765 
766             // Update compressor bands
767             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
768             {
769                 comp_band_t *b  = &c->vBands[j];
770 
771                 float attack    = b->pAttLevel->getValue();
772                 float release   = b->pRelLevel->getValue() * attack;
773                 float makeup    = b->pMakeup->getValue();
774                 compressor_mode_t mode = decode_mode(b->pMode->getValue());
775                 bool enabled    = b->pEnable->getValue() >= 0.5f;
776                 if (enabled && (j > 0))
777                     enabled         = c->vSplit[j-1].bEnabled;
778                 bool cust_lcf   = b->pScLpfOn->getValue() >= 0.5f;
779                 bool cust_hcf   = b->pScHpfOn->getValue() >= 0.5f;
780                 float sc_gain   = b->pScPreamp->getValue();
781                 bool mute       = (b->pMute->getValue() >= 0.5f);
782                 bool solo       = (enabled) && (b->pSolo->getValue() >= 0.5f);
783 
784                 b->pRelLevelOut->setValue(release);
785 
786                 b->bExtSc       = (b->pExtSc != NULL) ? b->pExtSc->getValue() >= 0.5f : false;
787 
788                 b->sSC.set_mode(b->pScMode->getValue());
789                 b->sSC.set_reactivity(b->pScReact->getValue());
790                 b->sSC.set_stereo_mode((nMode == MBCM_MS) ? SCSM_MIDSIDE : SCSM_STEREO);
791                 b->sSC.set_source((b->pScSource != NULL) ? b->pScSource->getValue() : SCS_MIDDLE);
792 
793                 if (sc_gain != b->fScPreamp)
794                 {
795                     b->fScPreamp    = sc_gain;
796                     b->nSync       |= S_EQ_CURVE;
797                 }
798 
799                 b->sComp.set_mode(mode);
800                 b->sComp.set_threshold(attack, release);
801                 b->sComp.set_timings(b->pAttTime->getValue(), b->pRelTime->getValue());
802                 b->sComp.set_ratio(b->pRatio->getValue());
803                 b->sComp.set_knee(b->pKnee->getValue());
804                 b->sComp.set_boost_threshold((mode != CM_BOOSTING) ? b->pBThresh->getValue() : b->pBoost->getValue());
805 
806                 if (b->sComp.modified())
807                 {
808                     b->sComp.update_settings();
809                     b->nSync       |= S_COMP_CURVE;
810                 }
811                 if (b->fMakeup != makeup)
812                 {
813                     b->fMakeup      = makeup;
814                     b->nSync       |= S_COMP_CURVE;
815                 }
816                 if (b->bEnabled != enabled)
817                 {
818                     b->bEnabled     = enabled;
819                     b->nSync       |= S_COMP_CURVE;
820                     if (!enabled)
821                         b->sDelay.clear(); // Clear delay buffer from artifacts
822                 }
823                 if (b->bSolo != solo)
824                 {
825                     b->bSolo        = solo;
826                     b->nSync       |= S_COMP_CURVE;
827                 }
828                 if (b->bMute != mute)
829                 {
830                     b->bMute        = mute;
831                     b->nSync       |= S_COMP_CURVE;
832                 }
833                 if (b->bCustLCF != cust_lcf)
834                 {
835                     b->bCustLCF     = cust_lcf;
836                     b->nSync       |= S_COMP_CURVE;
837                     c->nPlanSize    = 0;
838                 }
839                 if (b->bCustHCF != cust_hcf)
840                 {
841                     b->bCustHCF     = cust_hcf;
842                     b->nSync       |= S_COMP_CURVE;
843                     c->nPlanSize    = 0;
844                 }
845                 if (cust_lcf)
846                 {
847                     float lcf       = b->pScLcfFreq->getValue();
848                     if (lcf != b->fFreqLCF)
849                     {
850                         b->fFreqLCF     = lcf;
851                         c->nPlanSize    = 0;
852                     }
853                 }
854                 if (cust_hcf)
855                 {
856                     float hcf       = b->pScHcfFreq->getValue();
857                     if (hcf != b->fFreqHCF)
858                     {
859                         b->fFreqHCF     = hcf;
860                         c->nPlanSize    = 0;
861                     }
862                 }
863 
864                 if (b->bSolo)
865                     solo_on         = true;
866 
867                 // Estimate lookahead buffer size
868                 b->nLookahead   = millis_to_samples(fSampleRate, b->pScLook->getValue());
869             }
870         }
871 
872         for (size_t i=0; i<channels; ++i)
873         {
874             channel_t *c    = &vChannels[i];
875 
876             // Check muting option
877             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
878             {
879                 comp_band_t *b      = &c->vBands[j];
880                 if ((!b->bMute) && (solo_on))
881                     b->bMute    = !b->bSolo;
882             }
883 
884             // Rebuild compression plan
885             if (c->nPlanSize <= 0)
886             {
887                 c->nPlanSize                = 0;
888                 c->vBands[0].fFreqStart     = 0;
889                 c->vPlan[c->nPlanSize++]    = &c->vBands[0];
890 
891                 for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX-1; ++j)
892                 {
893                     comp_band_t *b      = &c->vBands[j+1];
894                     b->fFreqStart       = c->vSplit[j].fFreq;
895 
896                     if (c->vSplit[j].bEnabled)
897                         c->vPlan[c->nPlanSize++]    = b;
898                 }
899 
900                 // Do simple sort of PLAN items by frequency
901                 if (c->nPlanSize > 1)
902                 {
903                     // Sort in ascending order
904                     for (size_t si=0; si < c->nPlanSize-1; ++si)
905                         for (size_t sj=si+1; sj < c->nPlanSize; ++sj)
906                             if (compare_bands_for_sort(c->vPlan[si], c->vPlan[sj]))
907                             {
908                                 comp_band_t *tmp = c->vPlan[si];
909                                 c->vPlan[si]    = c->vPlan[sj];
910                                 c->vPlan[sj]    = tmp;
911                             }
912 
913                     for (size_t j=1; j<c->nPlanSize; ++j)
914                         c->vPlan[j-1]->fFreqEnd     = c->vPlan[j]->fFreqStart;
915                 }
916                 c->vPlan[c->nPlanSize-1]->fFreqEnd       = (fSampleRate >> 1);
917 
918                 // Configure equalizers
919                 lsp_trace("Reordered bands according to frequency grow");
920                 for (size_t j=0; j<c->nPlanSize; ++j)
921                 {
922                     comp_band_t *b  = c->vPlan[j];
923                     b->pFreqEnd->setValue(b->fFreqEnd);
924                     b->nSync       |= S_EQ_CURVE;
925 
926 //                    lsp_trace("plan[%d] start=%f, end=%f, fft=%s",
927 //                            int(j), b->fFreqStart, b->fFreqEnd,
928 //                            (b->bFFT) ? "true" : "false");
929 
930                     lsp_trace("plan[%d] start=%f, end=%f", int(j), b->fFreqStart, b->fFreqEnd);
931 
932                     // Configure equalizer for the sidechain
933                     for (size_t k=0; k<channels; ++k)
934                     {
935                         // Configure lo-pass filter
936                         fp.nType        = ((j != (c->nPlanSize-1)) || (b->bCustHCF)) ? FLT_BT_LRX_LOPASS : FLT_NONE;
937                         fp.fFreq        = (b->bCustHCF) ? b->pScHcfFreq->getValue() : b->pFreqEnd->getValue();
938                         fp.fFreq2       = fp.fFreq;
939                         fp.fQuality     = 0.0f;
940                         fp.fGain        = 1.0f;
941                         fp.fQuality     = 0.0f;
942                         fp.nSlope       = 2; // TODO
943 
944                         b->sEQ[k].set_params(0, &fp);
945 
946                         // Configure hi-pass filter
947                         fp.nType        = ((j != 0) || (b->bCustLCF)) ? FLT_BT_LRX_HIPASS : FLT_NONE;
948                         fp.fFreq        = (b->bCustLCF) ? b->pScLcfFreq->getValue() : b->fFreqStart;
949                         fp.fFreq2       = fp.fFreq;
950                         fp.fQuality     = 0.0f;
951                         fp.fGain        = 1.0f;
952                         fp.fQuality     = 0.0f;
953                         fp.nSlope       = 2; // TODO
954 
955                         b->sEQ[k].set_params(1, &fp);
956                     }
957 
958                     // Update transfer function for equalizer
959                     b->sEQ[0].freq_chart(size_t(0), b->vTr, vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
960                     b->sEQ[0].freq_chart(size_t(1), vTr, vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
961                     dsp::pcomplex_mul2(b->vTr, vTr, mb_compressor_base_metadata::FFT_MESH_POINTS);
962                     dsp::pcomplex_mod(b->vTr, b->vTr, mb_compressor_base_metadata::FFT_MESH_POINTS);
963 
964                     // Update filter parameters, depending on operating mode
965                     if (bModern)
966                     {
967                         // Configure filter for band
968                         if (j <= 0)
969                         {
970                             fp.nType        = (c->nPlanSize > 1) ? FLT_BT_LRX_LOSHELF : FLT_BT_AMPLIFIER;
971                             fp.fFreq        = b->fFreqEnd;
972                             fp.fFreq2       = b->fFreqEnd;
973                         }
974                         else if (j >= (c->nPlanSize - 1))
975                         {
976                             fp.nType        = FLT_BT_LRX_HISHELF;
977                             fp.fFreq        = b->fFreqStart;
978                             fp.fFreq2       = b->fFreqStart;
979                         }
980                         else
981                         {
982                             fp.nType        = FLT_BT_LRX_LADDERPASS;
983                             fp.fFreq        = b->fFreqStart;
984                             fp.fFreq2       = b->fFreqEnd;
985                         }
986 
987                         fp.fGain        = 1.0f;
988                         fp.nSlope       = 2; // TODO
989                         fp.fQuality     = 0.0;
990 
991                         lsp_trace("Filter type=%d, from=%f, to=%f", int(fp.nType), fp.fFreq, fp.fFreq2);
992 
993                         sFilters.set_params(b->nFilterID, &fp);
994                     }
995                     else
996                     {
997                         fp.fGain        = 1.0f;
998                         fp.nSlope       = 2; // TODO
999                         fp.fQuality     = 0.0;
1000                         fp.fFreq    	= b->fFreqEnd;
1001                         fp.fFreq2   	= b->fFreqEnd;
1002 
1003                         // We're going from low frequencies to high frequencies
1004                         if (j >= (c->nPlanSize - 1))
1005                         {
1006                             fp.nType    = FLT_NONE;
1007                             b->sPassFilter.update(fSampleRate, &fp);
1008                             b->sRejFilter.update(fSampleRate, &fp);
1009                             b->sAllFilter.update(fSampleRate, &fp);
1010                         }
1011                         else
1012                         {
1013                             fp.nType    = FLT_BT_LRX_LOPASS;
1014                             b->sPassFilter.update(fSampleRate, &fp);
1015                             fp.nType    = FLT_BT_LRX_HIPASS;
1016                             b->sRejFilter.update(fSampleRate, &fp);
1017                             fp.nType    = (j == 0) ? FLT_NONE : FLT_BT_LRX_ALLPASS;
1018                             b->sAllFilter.update(fSampleRate, &fp);
1019                         }
1020                     }
1021                 }
1022             } // nPlanSize
1023 
1024             // Enable/disable dynamic filters
1025             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
1026             {
1027                 comp_band_t *b  = &c->vBands[j];
1028                 sFilters.set_filter_active(b->nFilterID, b->bEnabled);
1029             }
1030 
1031             // Calculate latency
1032             for (size_t j=0; j<c->nPlanSize; ++j)
1033             {
1034                 comp_band_t *b  = c->vPlan[j];
1035                 latency         = lsp_max(latency, b->nLookahead);
1036             }
1037         }
1038 
1039         // Update latency
1040         set_latency(latency);
1041         for (size_t i=0; i<channels; ++i)
1042         {
1043             channel_t *c    = &vChannels[i];
1044 
1045             // Update latency
1046             for (size_t j=0; j<c->nPlanSize; ++j)
1047             {
1048                 comp_band_t *b  = c->vPlan[j];
1049                 b->sDelay.set_delay(latency - b->nLookahead);
1050             }
1051             c->sDelay.set_delay(latency);
1052         }
1053 
1054         // Debug:
1055 #ifdef LSP_TRACE
1056         for (size_t i=0; i<channels; ++i)
1057         {
1058             channel_t *c    = &vChannels[i];
1059 
1060             for (size_t j=0; j<c->nPlanSize; ++j)
1061             {
1062                 comp_band_t *b  = c->vPlan[j];
1063                 filter_params_t fp;
1064                 sFilters.get_params(b->nFilterID, &fp);
1065 
1066                 lsp_trace("plan[%d, %d] start=%f, end=%f, filter={id=%d, type=%d, slope=%d}, solo=%s, mute=%s",
1067                         int(i), int(j),
1068                         b->fFreqStart, b->fFreqEnd,
1069                         int(b->nFilterID), int(fp.nType), int(fp.nSlope),
1070                         (b->bSolo) ? "true" : "false",
1071                         (b->bMute) ? "true" : "false"
1072                     );
1073             }
1074         }
1075 #endif /* LSP_TRACE */
1076 
1077         nEnvBoost       = env_boost;
1078         bEnvUpdate      = false;
1079     }
1080 
update_sample_rate(long sr)1081     void mb_compressor_base::update_sample_rate(long sr)
1082     {
1083         // Determine number of channels
1084         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
1085         size_t max_delay    = millis_to_samples(sr, mb_compressor_base_metadata::LOOKAHEAD_MAX);
1086 
1087         // Update analyzer's sample rate
1088         sAnalyzer.set_sample_rate(sr);
1089         sFilters.set_sample_rate(sr);
1090         bEnvUpdate          = true;
1091 
1092         // Update channels
1093         for (size_t i=0; i<channels; ++i)
1094         {
1095             channel_t *c = &vChannels[i];
1096             c->sBypass.init(sr);
1097             c->sDelay.init(max_delay);
1098 
1099             // Update bands
1100             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
1101             {
1102                 comp_band_t *b  = &c->vBands[j];
1103 
1104                 b->sSC.set_sample_rate(sr);
1105                 b->sComp.set_sample_rate(sr);
1106                 b->sDelay.init(max_delay);
1107 
1108                 b->sPassFilter.set_sample_rate(sr);
1109                 b->sRejFilter.set_sample_rate(sr);
1110                 b->sAllFilter.set_sample_rate(sr);
1111 
1112                 b->sEQ[0].set_sample_rate(sr);
1113                 if (channels > 1)
1114                     b->sEQ[1].set_sample_rate(sr);
1115             }
1116 
1117             c->nPlanSize        = 0; // Force to rebuild plan
1118         }
1119     }
1120 
ui_activated()1121     void mb_compressor_base::ui_activated()
1122     {
1123         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
1124 
1125         for (size_t i=0; i<channels; ++i)
1126         {
1127             channel_t *c        = &vChannels[i];
1128 
1129             for (size_t j=0; j<c->nPlanSize; ++j)
1130             {
1131                 comp_band_t *b      = c->vPlan[j];
1132                 b->nSync            = S_ALL;
1133             }
1134         }
1135     }
1136 
1137     /*
1138          The overall schema of signal processing in 'classic' mode for 4 bands:
1139 
1140 
1141         s   ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐  s'
1142        ──┬─►│LPF 1│────►│VCA 1│────►│APF 2│────►│  +  │────►│APF 3│────►│  +  │────►│  +  │────►
1143          │  └─────┘     └─────┘     └─────┘     └─────┘     └─────┘     └─────┘     └─────┘
1144          │                                         ▲                       ▲           ▲
1145          │                                         │                       │           │
1146          │  ┌─────┐                 ┌─────┐     ┌─────┐     ┌─────┐     ┌─────┐        │
1147          └─►│HPF 1│──────────────┬─►│LPF 2│────►│VCA 2│  ┌─►│LPF 3│────►│VCA 3│        │
1148             └─────┘              │  └─────┘     └─────┘  │  └─────┘     └─────┘        │
1149                                  │                       │                             │
1150                                  │                       │                             │
1151                                  │  ┌─────┐              │  ┌─────┐     ┌─────┐        │
1152                                  └─►│HPF 2│──────────────┴─►│HPF 3│────►│VCA 4│────────┘
1153                                     └─────┘                 └─────┘     └─────┘
1154      */
1155 
process(size_t samples)1156     void mb_compressor_base::process(size_t samples)
1157     {
1158         size_t channels     = (nMode == MBCM_MONO) ? 1 : 2;
1159 
1160         // Bind input signal
1161         for (size_t i=0; i<channels; ++i)
1162         {
1163             channel_t *c        = &vChannels[i];
1164 
1165             c->vIn              = c->pIn->getBuffer<float>();
1166             c->vOut             = c->pOut->getBuffer<float>();
1167             c->vScIn            = (c->pScIn != NULL) ? c->pScIn->getBuffer<float>() : NULL;
1168         }
1169 
1170         // Do processing
1171         while (samples > 0)
1172         {
1173             // Determine buffer size for processing
1174             size_t to_process   = (samples > MBC_BUFFER_SIZE) ? MBC_BUFFER_SIZE : samples;
1175 
1176             // Measure input signal level
1177             for (size_t i=0; i<channels; ++i)
1178             {
1179                 channel_t *c        = &vChannels[i];
1180                 float level         = dsp::abs_max(c->vIn, to_process) * fInGain;
1181                 c->pInLvl->setValue(level);
1182             }
1183 
1184             // Pre-process channel data
1185             if (nMode == MBCM_MS)
1186             {
1187                 dsp::lr_to_ms(vChannels[0].vBuffer, vChannels[1].vBuffer, vChannels[0].vIn, vChannels[1].vIn, to_process);
1188                 dsp::mul_k2(vChannels[0].vBuffer, fInGain, to_process);
1189                 dsp::mul_k2(vChannels[1].vBuffer, fInGain, to_process);
1190             }
1191             else if (nMode == MBCM_MONO)
1192                 dsp::mul_k3(vChannels[0].vBuffer, vChannels[0].vIn, fInGain, to_process);
1193             else
1194             {
1195                 dsp::mul_k3(vChannels[0].vBuffer, vChannels[0].vIn, fInGain, to_process);
1196                 dsp::mul_k3(vChannels[1].vBuffer, vChannels[1].vIn, fInGain, to_process);
1197             }
1198             if (bSidechain)
1199             {
1200                 if (nMode == MBCM_MS)
1201                 {
1202                     dsp::lr_to_ms(vChannels[0].vExtScBuffer, vChannels[1].vExtScBuffer, vChannels[0].vScIn, vChannels[1].vScIn, to_process);
1203                     dsp::mul_k2(vChannels[0].vExtScBuffer, fInGain, to_process);
1204                     dsp::mul_k2(vChannels[1].vExtScBuffer, fInGain, to_process);
1205                 }
1206                 else if (nMode == MBCM_MONO)
1207                     dsp::mul_k3(vChannels[0].vExtScBuffer, vChannels[0].vScIn, fInGain, to_process);
1208                 else
1209                 {
1210                     dsp::mul_k3(vChannels[0].vExtScBuffer, vChannels[0].vScIn, fInGain, to_process);
1211                     dsp::mul_k3(vChannels[1].vExtScBuffer, vChannels[1].vScIn, fInGain, to_process);
1212                 }
1213             }
1214 
1215 
1216             // Do frequency boost and input channel analysis
1217             for (size_t i=0; i<channels; ++i)
1218             {
1219                 channel_t *c        = &vChannels[i];
1220                 c->sEnvBoost[0].process(c->vScBuffer, c->vBuffer, to_process);
1221                 if (bSidechain)
1222                     c->sEnvBoost[1].process(c->vExtScBuffer, c->vExtScBuffer, to_process);
1223 
1224                 dsp::copy(c->vInAnalyze, c->vBuffer, to_process);
1225             }
1226 
1227             // MAIN PLUGIN STUFF
1228             for (size_t i=0; i<channels; ++i)
1229             {
1230                 channel_t *c        = &vChannels[i];
1231 
1232                 for (size_t j=0; j<c->nPlanSize; ++j)
1233                 {
1234                     comp_band_t *b      = c->vPlan[j];
1235 
1236                     // Prepare sidechain signal with band equalizers
1237                     b->sEQ[0].process(vSc[0], (b->bExtSc) ? vChannels[0].vExtScBuffer : vChannels[0].vScBuffer, to_process);
1238                     if (channels > 1)
1239                         b->sEQ[1].process(vSc[1], (b->bExtSc) ? vChannels[1].vExtScBuffer : vChannels[1].vScBuffer, to_process);
1240 
1241                     // Preprocess VCA signal
1242                     b->sSC.process(vBuffer, const_cast<const float **>(vSc), to_process); // Band now contains processed by sidechain signal
1243                     b->sDelay.process(vBuffer, vBuffer, b->fScPreamp, to_process); // Apply sidechain preamp and lookahead delay
1244 
1245                     if (b->bEnabled)
1246                     {
1247                         b->sComp.process(b->vVCA, vEnv, vBuffer, to_process); // Output
1248                         dsp::mul_k2(b->vVCA, b->fMakeup, to_process); // Apply makeup gain
1249 
1250                         // Output curve level
1251                         float lvl = dsp::abs_max(vEnv, to_process);
1252                         b->pEnvLvl->setValue(lvl);
1253                         b->pMeterGain->setValue(b->sComp.reduction(lvl));
1254                         lvl = b->sComp.curve(lvl) * b->fMakeup;
1255                         b->pCurveLvl->setValue(lvl);
1256 
1257                         // Remember last envelope level and buffer level
1258                         b->fGainLevel   = b->vVCA[to_process-1];
1259 
1260                         // Check muting option
1261                         if (b->bMute)
1262                             dsp::fill(b->vVCA, GAIN_AMP_M_36_DB, to_process);
1263                     }
1264                     else
1265                     {
1266                         dsp::fill(b->vVCA, (b->bMute) ? GAIN_AMP_M_36_DB : GAIN_AMP_0_DB, to_process);
1267                         b->fGainLevel   = GAIN_AMP_0_DB;
1268                     }
1269                 }
1270 
1271                 // Output curve parameters for disabled compressors
1272                 for (size_t i=0; i<mb_compressor_base_metadata::BANDS_MAX; ++i)
1273                 {
1274                     comp_band_t *b      = &c->vBands[i];
1275                     if (b->bEnabled)
1276                         continue;
1277 
1278                     b->pEnvLvl->setValue(0.0f);
1279                     b->pCurveLvl->setValue(0.0f);
1280                     b->pMeterGain->setValue(GAIN_AMP_0_DB);
1281                 }
1282             }
1283 
1284             // Here, we apply VCA to input signal dependent on the input
1285             if (bModern) // 'Modern' mode
1286             {
1287                 // Apply VCA control
1288                 for (size_t i=0; i<channels; ++i)
1289                 {
1290                     channel_t *c        = &vChannels[i];
1291                     c->sDelay.process(c->vInBuffer, c->vBuffer, to_process); // Apply delay to compensate lookahead feature
1292                     dsp::copy(vBuffer, c->vInBuffer, to_process);
1293 
1294                     for (size_t j=0; j<c->nPlanSize; ++j)
1295                     {
1296                         comp_band_t *b      = c->vPlan[j];
1297                         sFilters.process(b->nFilterID, c->vBuffer, c->vBuffer, b->vVCA, to_process);
1298                     }
1299                 }
1300             }
1301             else // 'Classic' mode
1302             {
1303                 // Apply VCA control
1304                 for (size_t i=0; i<channels; ++i)
1305                 {
1306                     channel_t *c        = &vChannels[i];
1307 
1308                     // Originally, there is no signal
1309                     c->sDelay.process(c->vInBuffer, c->vBuffer, to_process); // Apply delay to compensate lookahead feature, store into vBuffer
1310                     dsp::copy(vBuffer, c->vInBuffer, to_process);
1311                     dsp::fill_zero(c->vBuffer, to_process);                 // Clear the channel buffer
1312 
1313                     for (size_t j=0; j<c->nPlanSize; ++j)
1314                     {
1315                         comp_band_t *b      = c->vPlan[j];
1316 
1317                         b->sAllFilter.process(c->vBuffer, c->vBuffer, to_process); // Process the signal with all-pass
1318                         b->sPassFilter.process(vEnv, vBuffer, to_process); // Filter frequencies from input
1319                         dsp::mul2(vEnv, b->vVCA, to_process); // Apply VCA gain
1320                         dsp::add2(c->vBuffer, vEnv, to_process); // Add signal to the channel buffer
1321                         b->sRejFilter.process(vBuffer, vBuffer, to_process); // Filter frequencies from input
1322                     }
1323                 }
1324             }
1325 
1326             // MAIN PLUGIN STUFF END
1327 
1328             // Do output channel analysis
1329             for (size_t i=0; i<channels; ++i)
1330             {
1331                 channel_t *c        = &vChannels[i];
1332                 dsp::copy(c->vOutAnalyze, c->vBuffer, to_process);
1333             }
1334 
1335             sAnalyzer.process(vAnalyze, to_process);
1336 
1337             // Post-process data (if needed)
1338             if (nMode == MBCM_MS)
1339             {
1340                 dsp::ms_to_lr(vChannels[0].vBuffer, vChannels[1].vBuffer, vChannels[0].vBuffer, vChannels[1].vBuffer, to_process);
1341                 dsp::ms_to_lr(vChannels[0].vInBuffer, vChannels[1].vInBuffer, vChannels[0].vInBuffer, vChannels[1].vInBuffer, to_process);
1342             }
1343 
1344             // Final metering
1345             for (size_t i=0; i<channels; ++i)
1346             {
1347                 channel_t *c        = &vChannels[i];
1348 
1349                 // Apply dry/wet gain and bypass
1350                 dsp::mix2(c->vBuffer, c->vInBuffer, fWetGain, fDryGain, to_process);
1351                 float level         = dsp::abs_max(c->vBuffer, to_process);
1352                 c->pOutLvl->setValue(level);
1353                 c->sBypass.process(c->vOut, c->vInBuffer, c->vBuffer, to_process);
1354 
1355                 // Update pointers
1356                 c->vIn             += to_process;
1357                 c->vOut            += to_process;
1358                 if (c->vScIn != NULL)
1359                     c->vScIn           += to_process;
1360             }
1361             samples    -= to_process;
1362         } // while (samples > 0)
1363 
1364         // Output FFT curves for each channel
1365         for (size_t i=0; i<channels; ++i)
1366         {
1367             channel_t *c     = &vChannels[i];
1368 
1369             // Calculate transfer function for the compressor
1370             if (bModern)
1371             {
1372                 dsp::pcomplex_fill_ri(c->vTr, 1.0f, 0.0f, mb_compressor_base_metadata::FFT_MESH_POINTS);
1373 
1374                 // Calculate transfer function
1375                 for (size_t j=0; j<c->nPlanSize; ++j)
1376                 {
1377                     comp_band_t *b      = c->vPlan[j];
1378                     sFilters.freq_chart(b->nFilterID, vTr, vFreqs, b->fGainLevel, mb_compressor_base_metadata::FFT_MESH_POINTS);
1379                     dsp::pcomplex_mul2(c->vTr, vTr, mb_compressor_base_metadata::FFT_MESH_POINTS);
1380                 }
1381             }
1382             else
1383             {
1384                 dsp::pcomplex_fill_ri(vTr, 1.0f, 0.0f, mb_compressor_base_metadata::FFT_MESH_POINTS);   // vBuffer
1385                 dsp::fill_zero(c->vTr, mb_compressor_base_metadata::FFT_MESH_POINTS*2);                 // c->vBuffer
1386 
1387                 // Calculate transfer function
1388                 for (size_t j=0; j<c->nPlanSize; ++j)
1389                 {
1390                     comp_band_t *b      = c->vPlan[j];
1391 
1392                     // Apply all-pass characteristics
1393                     b->sAllFilter.freq_chart(vPFc, vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1394                     dsp::pcomplex_mul2(c->vTr, vPFc, mb_compressor_base_metadata::FFT_MESH_POINTS);
1395 
1396                     // Apply lo-pass filter characteristics
1397                     b->sPassFilter.freq_chart(vPFc, vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1398                     dsp::pcomplex_mul2(vPFc, vTr, mb_compressor_base_metadata::FFT_MESH_POINTS);
1399                     dsp::fmadd_k3(c->vTr, vPFc, b->fGainLevel, mb_compressor_base_metadata::FFT_MESH_POINTS*2);
1400 
1401                     // Apply hi-pass filter characteristics
1402                     b->sRejFilter.freq_chart(vRFc, vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1403                     dsp::pcomplex_mul2(vTr, vRFc, mb_compressor_base_metadata::FFT_MESH_POINTS);
1404                 }
1405             }
1406             dsp::pcomplex_mod(c->vTrMem, c->vTr, mb_compressor_base_metadata::FFT_MESH_POINTS);
1407 
1408             // Output FFT curve, compression curve and FFT spectrogram for each band
1409             for (size_t j=0; j<mb_compressor_base_metadata::BANDS_MAX; ++j)
1410             {
1411                 comp_band_t *b      = &c->vBands[j];
1412 
1413                 // FFT spectrogram
1414                 mesh_t *mesh        = NULL;
1415 
1416                 // FFT curve
1417                 if (b->nSync & S_EQ_CURVE)
1418                 {
1419                     mesh                = (b->pScFreqChart != NULL) ? b->pScFreqChart->getBuffer<mesh_t>() : NULL;
1420                     if ((mesh != NULL) && (mesh->isEmpty()))
1421                     {
1422                         // Add extra points
1423                         mesh->pvData[0][0] = SPEC_FREQ_MIN*0.5f;
1424                         mesh->pvData[0][mb_compressor_base_metadata::MESH_POINTS+1] = SPEC_FREQ_MAX * 2.0f;
1425                         mesh->pvData[1][0] = 0.0f;
1426                         mesh->pvData[1][mb_compressor_base_metadata::MESH_POINTS+1] = 0.0f;
1427 
1428                         // Fill mesh
1429                         dsp::copy(&mesh->pvData[0][1], vFreqs, mb_compressor_base_metadata::MESH_POINTS);
1430                         dsp::mul_k3(&mesh->pvData[1][1], b->vTr, b->fScPreamp, mb_compressor_base_metadata::MESH_POINTS);
1431                         mesh->data(2, mb_compressor_base_metadata::FILTER_MESH_POINTS);
1432 
1433                         // Mark mesh as synchronized
1434                         b->nSync           &= ~S_EQ_CURVE;
1435                     }
1436                 }
1437 
1438                 // Compression curve
1439                 if (b->nSync & S_COMP_CURVE)
1440                 {
1441                     mesh                = (b->pCurveGraph != NULL) ? b->pCurveGraph->getBuffer<mesh_t>() : NULL;
1442                     if ((mesh != NULL) && (mesh->isEmpty()))
1443                     {
1444                         if (b->bEnabled)
1445                         {
1446                             // Copy frequency points
1447                             dsp::copy(mesh->pvData[0], vCurve, mb_compressor_base_metadata::CURVE_MESH_SIZE);
1448                             b->sComp.curve(mesh->pvData[1], vCurve, mb_compressor_base_metadata::CURVE_MESH_SIZE);
1449                             if (b->fMakeup != GAIN_AMP_0_DB)
1450                                 dsp::mul_k2(mesh->pvData[1], b->fMakeup, compressor_base_metadata::CURVE_MESH_SIZE);
1451 
1452                             // Mark mesh containing data
1453                             mesh->data(2, mb_compressor_base_metadata::CURVE_MESH_SIZE);
1454                         }
1455                         else
1456                             mesh->data(2, 0);
1457 
1458                         // Mark mesh as synchronized
1459                         b->nSync           &= ~S_COMP_CURVE;
1460                     }
1461                 }
1462             }
1463 
1464             // Output FFT curve for input
1465             mesh_t *mesh            = (c->pFftIn != NULL) ? c->pFftIn->getBuffer<mesh_t>() : NULL;
1466             if ((mesh != NULL) && (mesh->isEmpty()))
1467             {
1468                 if (c->bInFft)
1469                 {
1470                     // Copy frequency points
1471                     dsp::copy(mesh->pvData[0], vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1472                     sAnalyzer.get_spectrum(c->nAnInChannel, mesh->pvData[1], vIndexes, mb_compressor_base_metadata::FFT_MESH_POINTS);
1473 
1474                     // Mark mesh containing data
1475                     mesh->data(2, mb_compressor_base_metadata::FFT_MESH_POINTS);
1476                 }
1477                 else
1478                     mesh->data(2, 0);
1479             }
1480 
1481             // Output FFT curve for output
1482             mesh            = (c->pFftOut != NULL) ? c->pFftOut->getBuffer<mesh_t>() : NULL;
1483             if ((mesh != NULL) && (mesh->isEmpty()))
1484             {
1485                 if (sAnalyzer.channel_active(c->nAnOutChannel))
1486                 {
1487                     // Copy frequency points
1488                     dsp::copy(mesh->pvData[0], vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1489                     sAnalyzer.get_spectrum(c->nAnOutChannel, mesh->pvData[1], vIndexes, mb_compressor_base_metadata::FFT_MESH_POINTS);
1490 
1491                     // Mark mesh containing data
1492                     mesh->data(2, mb_compressor_base_metadata::FFT_MESH_POINTS);
1493                 }
1494                 else
1495                     mesh->data(2, 0);
1496             }
1497 
1498             // Output Channel curve
1499             mesh            = (c->pAmpGraph != NULL) ? c->pAmpGraph->getBuffer<mesh_t>() : NULL;
1500             if ((mesh != NULL) && (mesh->isEmpty()))
1501             {
1502                 // Calculate amplitude (modulo)
1503                 dsp::copy(mesh->pvData[0], vFreqs, mb_compressor_base_metadata::FFT_MESH_POINTS);
1504                 dsp::copy(mesh->pvData[1], c->vTrMem, mb_compressor_base_metadata::FFT_MESH_POINTS);
1505                 mesh->data(2, mb_compressor_base_metadata::FFT_MESH_POINTS);
1506             }
1507         } // for channel
1508 
1509         // Request for redraw
1510         if (pWrapper != NULL)
1511             pWrapper->query_display_draw();
1512     }
1513 
inline_display(ICanvas * cv,size_t width,size_t height)1514     bool mb_compressor_base::inline_display(ICanvas *cv, size_t width, size_t height)
1515     {
1516         // Check proportions
1517         if (height > (R_GOLDEN_RATIO * width))
1518             height  = R_GOLDEN_RATIO * width;
1519 
1520         // Init canvas
1521         if (!cv->init(width, height))
1522             return false;
1523         width   = cv->width();
1524         height  = cv->height();
1525 
1526         // Clear background
1527         bool bypassing = vChannels[0].sBypass.bypassing();
1528         cv->set_color_rgb((bypassing) ? CV_DISABLED : CV_BACKGROUND);
1529         cv->paint();
1530 
1531         // Draw axis
1532         cv->set_line_width(1.0);
1533 
1534         // "-72 db / (:zoom ** 3)" max="24 db * :zoom"
1535 
1536         float miny  = logf(GAIN_AMP_M_72_DB / dsp::ipowf(fZoom, 3));
1537         float maxy  = logf(GAIN_AMP_P_24_DB * fZoom);
1538 
1539         float zx    = 1.0f/SPEC_FREQ_MIN;
1540         float zy    = dsp::ipowf(fZoom, 3)/GAIN_AMP_M_72_DB;
1541         float dx    = width/(logf(SPEC_FREQ_MAX)-logf(SPEC_FREQ_MIN));
1542         float dy    = height/(miny-maxy);
1543 
1544         // Draw vertical lines
1545         cv->set_color_rgb(CV_YELLOW, 0.5f);
1546         for (float i=100.0f; i<SPEC_FREQ_MAX; i *= 10.0f)
1547         {
1548             float ax = dx*(logf(i*zx));
1549             cv->line(ax, 0, ax, height);
1550         }
1551 
1552         // Draw horizontal lines
1553         cv->set_color_rgb(CV_WHITE, 0.5f);
1554         for (float i=GAIN_AMP_M_72_DB; i<GAIN_AMP_P_24_DB; i *= GAIN_AMP_P_12_DB)
1555         {
1556             float ay = height + dy*(logf(i*zy));
1557             cv->line(0, ay, width, ay);
1558         }
1559 
1560         // Allocate buffer: f, x, y, tr
1561         pIDisplay           = float_buffer_t::reuse(pIDisplay, 4, width+2);
1562         float_buffer_t *b   = pIDisplay;
1563         if (b == NULL)
1564             return false;
1565 
1566         // Initialize mesh
1567         b->v[0][0]          = SPEC_FREQ_MIN*0.5f;
1568         b->v[0][width+1]    = SPEC_FREQ_MAX*2.0f;
1569         b->v[3][0]          = 1.0f;
1570         b->v[3][width+1]    = 1.0f;
1571 
1572         size_t channels = ((nMode == MBCM_MONO) || (nMode == MBCM_STEREO)) ? 1 : 2;
1573         static uint32_t c_colors[] = {
1574                 CV_MIDDLE_CHANNEL, CV_MIDDLE_CHANNEL,
1575                 CV_MIDDLE_CHANNEL, CV_MIDDLE_CHANNEL,
1576                 CV_LEFT_CHANNEL, CV_RIGHT_CHANNEL,
1577                 CV_MIDDLE_CHANNEL, CV_SIDE_CHANNEL
1578                };
1579 
1580         bool aa = cv->set_anti_aliasing(true);
1581         cv->set_line_width(2);
1582 
1583         for (size_t i=0; i<channels; ++i)
1584         {
1585             channel_t *c    = &vChannels[i];
1586 
1587             for (size_t j=0; j<width; ++j)
1588             {
1589                 size_t k        = (j*mb_compressor_base_metadata::MESH_POINTS)/width;
1590                 b->v[0][j+1]    = vFreqs[k];
1591                 b->v[3][j+1]    = c->vTrMem[k];
1592             }
1593 
1594             dsp::fill(b->v[1], 0.0f, width+2);
1595             dsp::fill(b->v[2], height, width+2);
1596             dsp::axis_apply_log1(b->v[1], b->v[0], zx, dx, width+2);
1597             dsp::axis_apply_log1(b->v[2], b->v[3], zy, dy, width+2);
1598 
1599             // Draw mesh
1600             uint32_t color = (bypassing || !(active())) ? CV_SILVER : c_colors[nMode*2 + i];
1601             Color stroke(color), fill(color, 0.5f);
1602             cv->draw_poly(b->v[1], b->v[2], width+2, stroke, fill);
1603         }
1604         cv->set_anti_aliasing(aa);
1605 
1606         return true;
1607     }
1608 
1609     //-------------------------------------------------------------------------
1610     // Compressor derivatives
mb_compressor_mono()1611     mb_compressor_mono::mb_compressor_mono() : mb_compressor_base(metadata, false, MBCM_MONO)
1612     {
1613     }
1614 
mb_compressor_stereo()1615     mb_compressor_stereo::mb_compressor_stereo() : mb_compressor_base(metadata, false, MBCM_STEREO)
1616     {
1617     }
1618 
mb_compressor_lr()1619     mb_compressor_lr::mb_compressor_lr() : mb_compressor_base(metadata, false, MBCM_LR)
1620     {
1621     }
1622 
mb_compressor_ms()1623     mb_compressor_ms::mb_compressor_ms() : mb_compressor_base(metadata, false, MBCM_MS)
1624     {
1625     }
1626 
sc_mb_compressor_mono()1627     sc_mb_compressor_mono::sc_mb_compressor_mono() : mb_compressor_base(metadata, true, MBCM_MONO)
1628     {
1629     }
1630 
sc_mb_compressor_stereo()1631     sc_mb_compressor_stereo::sc_mb_compressor_stereo() : mb_compressor_base(metadata, true, MBCM_STEREO)
1632     {
1633     }
1634 
sc_mb_compressor_lr()1635     sc_mb_compressor_lr::sc_mb_compressor_lr() : mb_compressor_base(metadata, true, MBCM_LR)
1636     {
1637     }
1638 
sc_mb_compressor_ms()1639     sc_mb_compressor_ms::sc_mb_compressor_ms() : mb_compressor_base(metadata, true, MBCM_MS)
1640     {
1641     }
1642 }
1643 
1644 
1645