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: 16 сент. 2016 г.
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/compressor.h>
26 
27 #define COMP_BUF_SIZE           0x1000
28 #define TRACE_PORT(p)           lsp_trace("  port id=%s", (p)->metadata()->id);
29 
30 namespace lsp
31 {
32     //-------------------------------------------------------------------------
33     // Compressor base class
34 
compressor_base(const plugin_metadata_t & metadata,bool sc,size_t mode)35     compressor_base::compressor_base(const plugin_metadata_t &metadata, bool sc, size_t mode): plugin_t(metadata)
36     {
37         nMode           = mode;
38         bSidechain      = sc;
39         vChannels       = NULL;
40         vCurve          = NULL;
41         vTime           = NULL;
42         bPause          = false;
43         bClear          = false;
44         bMSListen       = false;
45         fInGain         = 1.0f;
46         bUISync         = true;
47 
48         pBypass         = NULL;
49         pInGain         = NULL;
50         pOutGain        = NULL;
51         pPause          = NULL;
52         pClear          = NULL;
53         pMSListen       = NULL;
54 
55         pData           = NULL;
56         pIDisplay       = NULL;
57     }
58 
~compressor_base()59     compressor_base::~compressor_base()
60     {
61     }
62 
init(IWrapper * wrapper)63     void compressor_base::init(IWrapper *wrapper)
64     {
65         plugin_t::init(wrapper);
66         size_t channels = (nMode == CM_MONO) ? 1 : 2;
67 
68         // Allocate channels
69         vChannels       = new channel_t[channels];
70         if (vChannels == NULL)
71             return;
72 
73         // Allocate temporary buffers
74         size_t buf_size         = COMP_BUF_SIZE * sizeof(float);
75         size_t curve_size       = (compressor_base_metadata::CURVE_MESH_SIZE) * sizeof(float);
76         size_t history_size     = (compressor_base_metadata::TIME_MESH_SIZE) * sizeof(float);
77         size_t allocate         = buf_size * channels * 5 + curve_size + history_size + DEFAULT_ALIGN;
78         uint8_t *ptr            = new uint8_t[allocate];
79         if (ptr == NULL)
80             return;
81         pData                   = ptr;
82         ptr                     = ALIGN_PTR(ptr, DEFAULT_ALIGN);
83         vCurve                  = reinterpret_cast<float *>(ptr);
84         ptr                    += curve_size;
85         vTime                   = reinterpret_cast<float *>(ptr);
86         ptr                    += history_size;
87 
88         // Initialize channels
89         for (size_t i=0; i<channels; ++i)
90         {
91             channel_t *c = &vChannels[i];
92 
93             if (!c->sSC.init(channels, compressor_base_metadata::REACTIVITY_MAX))
94                 return;
95             if (!c->sSCEq.init(2, 12))
96                 return;
97             c->sSCEq.set_mode(EQM_IIR);
98             c->sSC.set_pre_equalizer(&c->sSCEq);
99 
100             c->vIn              = reinterpret_cast<float *>(ptr);
101             ptr                += buf_size;
102             c->vOut             = reinterpret_cast<float *>(ptr);
103             ptr                += buf_size;
104             c->vSc              = reinterpret_cast<float *>(ptr);
105             ptr                += buf_size;
106             c->vEnv             = reinterpret_cast<float *>(ptr);
107             ptr                += buf_size;
108             c->vGain            = reinterpret_cast<float *>(ptr);
109             ptr                += buf_size;
110             c->bScListen        = false;
111             c->nSync            = S_ALL;
112             c->nScType          = SCT_FEED_FORWARD;
113             c->fMakeup          = 1.0f;
114             c->fFeedback        = 0.0f;
115             c->fDryGain         = 1.0f;
116             c->fWetGain         = 0.0f;
117             c->fDotIn           = 0.0f;
118             c->fDotOut          = 0.0f;
119 
120             c->pIn              = NULL;
121             c->pOut             = NULL;
122             c->pSC              = NULL;
123 
124             for (size_t j=0; j<G_TOTAL; ++j)
125                 c->pGraph[j]        = NULL;
126 
127             for (size_t j=0; j<M_TOTAL; ++j)
128                 c->pMeter[j]        = NULL;
129 
130             c->pScType          = NULL;
131             c->pScMode          = NULL;
132             c->pScLookahead     = NULL;
133             c->pScListen        = NULL;
134             c->pScSource        = NULL;
135             c->pScReactivity    = NULL;
136             c->pScPreamp        = NULL;
137             c->pScHpfMode       = NULL;
138             c->pScHpfFreq       = NULL;
139             c->pScLpfMode       = NULL;
140             c->pScLpfFreq       = NULL;
141 
142             c->pMode            = NULL;
143             c->pAttackLvl       = NULL;
144             c->pReleaseLvl      = NULL;
145             c->pAttackTime      = NULL;
146             c->pReleaseTime     = NULL;
147             c->pRatio           = NULL;
148             c->pKnee            = NULL;
149             c->pBThresh         = NULL;
150             c->pBoost           = NULL;
151             c->pMakeup          = NULL;
152             c->pDryGain         = NULL;
153             c->pWetGain         = NULL;
154             c->pCurve           = NULL;
155             c->pReleaseOut      = NULL;
156         }
157 
158         lsp_assert(ptr < &pData[allocate]);
159 
160         // Bind ports
161         size_t port_id              = 0;
162 
163         // Input ports
164         lsp_trace("Binding input ports");
165         for (size_t i=0; i<channels; ++i)
166         {
167             TRACE_PORT(vPorts[port_id]);
168             vChannels[i].pIn        =   vPorts[port_id++];
169         }
170 
171         // Input ports
172         lsp_trace("Binding output ports");
173         for (size_t i=0; i<channels; ++i)
174         {
175             TRACE_PORT(vPorts[port_id]);
176             vChannels[i].pOut       =   vPorts[port_id++];
177         }
178 
179         // Input ports
180         if (bSidechain)
181         {
182             lsp_trace("Binding sidechain ports");
183             for (size_t i=0; i<channels; ++i)
184             {
185                 TRACE_PORT(vPorts[port_id]);
186                 vChannels[i].pSC        =   vPorts[port_id++];
187             }
188         }
189 
190         // Common ports
191         lsp_trace("Binding common ports");
192         TRACE_PORT(vPorts[port_id]);
193         pBypass                 =   vPorts[port_id++];
194         TRACE_PORT(vPorts[port_id]);
195         pInGain                 =   vPorts[port_id++];
196         TRACE_PORT(vPorts[port_id]);
197         pOutGain                =   vPorts[port_id++];
198         TRACE_PORT(vPorts[port_id]);
199         pPause                  =   vPorts[port_id++];
200         TRACE_PORT(vPorts[port_id]);
201         pClear                  =   vPorts[port_id++];
202         if (nMode == CM_MS)
203         {
204             TRACE_PORT(vPorts[port_id]);
205             pMSListen               =   vPorts[port_id++];
206         }
207 
208         // Sidechain ports
209         lsp_trace("Binding sidechain ports");
210         for (size_t i=0; i<channels; ++i)
211         {
212             channel_t *c = &vChannels[i];
213 
214             if ((i > 0) && (nMode == CM_STEREO))
215             {
216                 channel_t *sc       = &vChannels[0];
217                 c->pScType          = sc->pScType;
218                 c->pScSource        = sc->pScSource;
219                 c->pScLookahead     = sc->pScLookahead;
220                 c->pScMode          = sc->pScMode;
221                 c->pScListen        = sc->pScListen;
222                 c->pScReactivity    = sc->pScReactivity;
223                 c->pScPreamp        = sc->pScPreamp;
224                 c->pScHpfMode       = sc->pScHpfMode;
225                 c->pScHpfFreq       = sc->pScHpfFreq;
226                 c->pScLpfMode       = sc->pScLpfMode;
227                 c->pScLpfFreq       = sc->pScLpfFreq;
228             }
229             else
230             {
231                 TRACE_PORT(vPorts[port_id]);
232                 c->pScType          =   vPorts[port_id++];
233                 TRACE_PORT(vPorts[port_id]);
234                 c->pScMode          =   vPorts[port_id++];
235                 TRACE_PORT(vPorts[port_id]);
236                 c->pScLookahead     =   vPorts[port_id++];
237                 TRACE_PORT(vPorts[port_id]);
238                 c->pScListen        =   vPorts[port_id++];
239                 if (nMode != CM_MONO)
240                 {
241                     TRACE_PORT(vPorts[port_id]);
242                     c->pScSource        =   vPorts[port_id++];
243                 }
244                 TRACE_PORT(vPorts[port_id]);
245                 c->pScReactivity    =   vPorts[port_id++];
246                 TRACE_PORT(vPorts[port_id]);
247                 c->pScPreamp        =   vPorts[port_id++];
248                 TRACE_PORT(vPorts[port_id]);
249                 c->pScHpfMode       =   vPorts[port_id++];
250                 TRACE_PORT(vPorts[port_id]);
251                 c->pScHpfFreq       =   vPorts[port_id++];
252                 TRACE_PORT(vPorts[port_id]);
253                 c->pScLpfMode       =   vPorts[port_id++];
254                 TRACE_PORT(vPorts[port_id]);
255                 c->pScLpfFreq       =   vPorts[port_id++];
256             }
257         }
258 
259         // Compressor ports
260         lsp_trace("Binding compressor ports");
261         for (size_t i=0; i<channels; ++i)
262         {
263             channel_t *c = &vChannels[i];
264 
265             if ((i > 0) && (nMode == CM_STEREO))
266             {
267                 channel_t *sc       = &vChannels[0];
268 
269                 c->pMode            = sc->pMode;
270                 c->pAttackLvl       = sc->pAttackLvl;
271                 c->pAttackTime      = sc->pAttackTime;
272                 c->pReleaseLvl      = sc->pReleaseLvl;
273                 c->pReleaseTime     = sc->pReleaseTime;
274                 c->pRatio           = sc->pRatio;
275                 c->pKnee            = sc->pKnee;
276                 c->pBThresh         = sc->pBThresh;
277                 c->pBoost           = sc->pBoost;
278                 c->pMakeup          = sc->pMakeup;
279                 c->pDryGain         = sc->pDryGain;
280                 c->pWetGain         = sc->pWetGain;
281             }
282             else
283             {
284                 TRACE_PORT(vPorts[port_id]);
285                 c->pMode            =   vPorts[port_id++];
286                 TRACE_PORT(vPorts[port_id]);
287                 c->pAttackLvl       =   vPorts[port_id++];
288                 TRACE_PORT(vPorts[port_id]);
289                 c->pAttackTime      =   vPorts[port_id++];
290                 TRACE_PORT(vPorts[port_id]);
291                 c->pReleaseLvl      =   vPorts[port_id++];
292                 TRACE_PORT(vPorts[port_id]);
293                 c->pReleaseTime     =   vPorts[port_id++];
294                 TRACE_PORT(vPorts[port_id]);
295                 c->pRatio           =   vPorts[port_id++];
296                 TRACE_PORT(vPorts[port_id]);
297                 c->pKnee            =   vPorts[port_id++];
298                 TRACE_PORT(vPorts[port_id]);
299                 c->pBThresh         =   vPorts[port_id++];
300                 TRACE_PORT(vPorts[port_id]);
301                 c->pBoost           =   vPorts[port_id++];
302                 TRACE_PORT(vPorts[port_id]);
303                 c->pMakeup          =   vPorts[port_id++];
304                 TRACE_PORT(vPorts[port_id]);
305                 c->pDryGain         =   vPorts[port_id++];
306                 TRACE_PORT(vPorts[port_id]);
307                 c->pWetGain         =   vPorts[port_id++];
308                 TRACE_PORT(vPorts[port_id]);
309                 c->pReleaseOut      =   vPorts[port_id++];
310 
311                 // Skip meters visibility controls
312                 TRACE_PORT(vPorts[port_id]);
313                 port_id++;
314                 TRACE_PORT(vPorts[port_id]);
315                 port_id++;
316                 TRACE_PORT(vPorts[port_id]);
317                 port_id++;
318 
319                 TRACE_PORT(vPorts[port_id]);
320                 c->pCurve           =   vPorts[port_id++];
321                 TRACE_PORT(vPorts[port_id]);
322                 c->pGraph[G_SC]     =   vPorts[port_id++];
323                 TRACE_PORT(vPorts[port_id]);
324                 c->pGraph[G_ENV]    =   vPorts[port_id++];
325                 TRACE_PORT(vPorts[port_id]);
326                 c->pGraph[G_GAIN]   =   vPorts[port_id++];
327                 TRACE_PORT(vPorts[port_id]);
328                 c->pMeter[M_SC]     =   vPorts[port_id++];
329                 TRACE_PORT(vPorts[port_id]);
330                 c->pMeter[M_CURVE]  =   vPorts[port_id++];
331                 TRACE_PORT(vPorts[port_id]);
332                 c->pMeter[M_ENV]    =   vPorts[port_id++];
333                 TRACE_PORT(vPorts[port_id]);
334                 c->pMeter[M_GAIN]   =   vPorts[port_id++];
335             }
336         }
337 
338         // Bind history
339         lsp_trace("Binding history ports");
340         for (size_t i=0; i<channels; ++i)
341         {
342             channel_t *c = &vChannels[i];
343 
344             // Skip meters visibility controls
345             TRACE_PORT(vPorts[port_id]);
346             port_id++;
347             TRACE_PORT(vPorts[port_id]);
348             port_id++;
349 
350             // Bind ports
351             TRACE_PORT(vPorts[port_id]);
352             c->pGraph[G_IN]     =   vPorts[port_id++];
353             TRACE_PORT(vPorts[port_id]);
354             c->pGraph[G_OUT]    =   vPorts[port_id++];
355             TRACE_PORT(vPorts[port_id]);
356             c->pMeter[M_IN]     =   vPorts[port_id++];
357             TRACE_PORT(vPorts[port_id]);
358             c->pMeter[M_OUT]    =   vPorts[port_id++];
359         }
360 
361         // Initialize curve (logarithmic) in range of -72 .. +24 db
362         float delta = (compressor_base_metadata::CURVE_DB_MAX - compressor_base_metadata::CURVE_DB_MIN) / (compressor_base_metadata::CURVE_MESH_SIZE-1);
363         for (size_t i=0; i<compressor_base_metadata::CURVE_MESH_SIZE; ++i)
364             vCurve[i]   = db_to_gain(compressor_base_metadata::CURVE_DB_MIN + delta * i);
365 
366         // Initialize time points
367         delta       = compressor_base_metadata::TIME_HISTORY_MAX / (compressor_base_metadata::TIME_MESH_SIZE - 1);
368         for (size_t i=0; i<compressor_base_metadata::TIME_MESH_SIZE; ++i)
369             vTime[i]    = compressor_base_metadata::TIME_HISTORY_MAX - i*delta;
370     }
371 
destroy()372     void compressor_base::destroy()
373     {
374         if (vChannels != NULL)
375         {
376             size_t channels = (nMode == CM_MONO) ? 1 : 2;
377             for (size_t i=0; i<channels; ++i)
378             {
379                 vChannels[i].sSC.destroy();
380                 vChannels[i].sSCEq.destroy();
381                 vChannels[i].sDelay.destroy();
382                 vChannels[i].sCompDelay.destroy();
383                 vChannels[i].sDryDelay.destroy();
384             }
385 
386             delete [] vChannels;
387             vChannels = NULL;
388         }
389 
390         if (pData != NULL)
391         {
392             delete [] pData;
393             pData = NULL;
394         }
395 
396         if (pIDisplay != NULL)
397         {
398             pIDisplay->detroy();
399             pIDisplay   = NULL;
400         }
401     }
402 
update_sample_rate(long sr)403     void compressor_base::update_sample_rate(long sr)
404     {
405         size_t samples_per_dot  = seconds_to_samples(sr, compressor_base_metadata::TIME_HISTORY_MAX / compressor_base_metadata::TIME_MESH_SIZE);
406         size_t channels         = (nMode == CM_MONO) ? 1 : 2;
407         size_t max_delay        = millis_to_samples(fSampleRate, compressor_base_metadata::LOOKAHEAD_MAX);
408 
409         for (size_t i=0; i<channels; ++i)
410         {
411             channel_t *c = &vChannels[i];
412             c->sBypass.init(sr);
413             c->sComp.set_sample_rate(sr);
414             c->sSC.set_sample_rate(sr);
415             c->sSCEq.set_sample_rate(sr);
416             c->sDelay.init(max_delay);
417             c->sCompDelay.init(max_delay);
418             c->sDryDelay.init(max_delay);
419 
420             for (size_t j=0; j<G_TOTAL; ++j)
421                 c->sGraph[j].init(compressor_base_metadata::TIME_MESH_SIZE, samples_per_dot);
422             c->sGraph[G_GAIN].fill(1.0f);
423         }
424     }
425 
decode_mode(int mode)426     compressor_mode_t compressor_base::decode_mode(int mode)
427     {
428         switch (mode)
429         {
430             case compressor_base_metadata::CM_DOWNWARD: return CM_DOWNWARD;
431             case compressor_base_metadata::CM_UPWARD: return CM_UPWARD;
432             case compressor_base_metadata::CM_BOOSTING: return CM_BOOSTING;
433             default: return CM_DOWNWARD;
434         }
435     }
436 
update_settings()437     void compressor_base::update_settings()
438     {
439         filter_params_t fp;
440         size_t channels = (nMode == CM_MONO) ? 1 : 2;
441         bool bypass     = pBypass->getValue() >= 0.5f;
442 
443         // Global parameters
444         bPause          = pPause->getValue() >= 0.5f;
445         bClear          = pClear->getValue() >= 0.5f;
446         bMSListen       = (pMSListen != NULL) ? pMSListen->getValue() >= 0.5f : false;
447         fInGain         = pInGain->getValue();
448         float out_gain  = pOutGain->getValue();
449         size_t latency  = 0;
450 
451         for (size_t i=0; i<channels; ++i)
452         {
453             channel_t *c    = &vChannels[i];
454 
455             // Update bypass settings
456             c->sBypass.set_bypass(bypass);
457 
458             // Update sidechain settings
459             c->nScType      = c->pScType->getValue();
460             c->bScListen    = c->pScListen->getValue() >= 0.5f;
461 
462             c->sSC.set_gain(c->pScPreamp->getValue());
463             c->sSC.set_mode((c->pScMode != NULL) ? c->pScMode->getValue() : SCM_RMS);
464             c->sSC.set_source((c->pScSource != NULL) ? c->pScSource->getValue() : SCS_MIDDLE);
465             c->sSC.set_reactivity(c->pScReactivity->getValue());
466             c->sSC.set_stereo_mode(((nMode == CM_MS) && (c->nScType != SCT_EXTERNAL)) ? SCSM_MIDSIDE : SCSM_STEREO);
467 
468             // Setup hi-pass filter for sidechain
469             size_t hp_slope = c->pScHpfMode->getValue() * 2;
470             fp.nType        = (hp_slope > 0) ? FLT_BT_BWC_HIPASS : FLT_NONE;
471             fp.fFreq        = c->pScHpfFreq->getValue();
472             fp.fFreq2       = fp.fFreq;
473             fp.fGain        = 1.0f;
474             fp.nSlope       = hp_slope;
475             fp.fQuality     = 0.0f;
476             c->sSCEq.set_params(0, &fp);
477 
478             // Setup low-pass filter for sidechain
479             size_t lp_slope = c->pScLpfMode->getValue() * 2;
480             fp.nType        = (lp_slope > 0) ? FLT_BT_BWC_LOPASS : FLT_NONE;
481             fp.fFreq        = c->pScLpfFreq->getValue();
482             fp.fFreq2       = fp.fFreq;
483             fp.fGain        = 1.0f;
484             fp.nSlope       = lp_slope;
485             fp.fQuality     = 0.0f;
486             c->sSCEq.set_params(1, &fp);
487 
488             // Update delay and estimate overall delay
489             size_t delay    = millis_to_samples(fSampleRate, (c->pScLookahead != NULL) ? c->pScLookahead->getValue() : 0);
490             c->sDelay.set_delay(delay);
491             if (delay > latency)
492                 latency         = delay;
493 
494             // Update compressor settings
495             float attack    = c->pAttackLvl->getValue();
496             float release   = c->pReleaseLvl->getValue() * attack;
497             float makeup    = c->pMakeup->getValue();
498             compressor_mode_t mode = decode_mode(c->pMode->getValue());
499 
500             c->sComp.set_threshold(attack, release);
501             c->sComp.set_timings(c->pAttackTime->getValue(), c->pReleaseTime->getValue());
502             c->sComp.set_ratio(c->pRatio->getValue());
503             c->sComp.set_knee(c->pKnee->getValue());
504             c->sComp.set_boost_threshold((mode != CM_BOOSTING) ? c->pBThresh->getValue() : c->pBoost->getValue());
505             c->sComp.set_mode(mode);
506             if (c->pReleaseOut != NULL)
507                 c->pReleaseOut->setValue(release);
508             c->sGraph[G_GAIN].set_method((mode == CM_DOWNWARD) ? MM_MINIMUM : MM_MAXIMUM);
509 
510             // Check modification flag
511             if (c->sComp.modified())
512             {
513                 c->sComp.update_settings();
514                 c->nSync           |= S_CURVE;
515             }
516 
517             // Update gains
518             c->fDryGain         = c->pDryGain->getValue() * out_gain;
519             c->fWetGain         = c->pWetGain->getValue() * out_gain;
520             if (c->fMakeup != makeup)
521             {
522                 c->fMakeup          = makeup;
523                 c->nSync           |= S_CURVE;
524             }
525         }
526 
527         // Tune compensation delays
528         for (size_t i=0; i<channels; ++i)
529         {
530             channel_t *c    = &vChannels[i];
531             c->sCompDelay.set_delay(latency - c->sDelay.get_delay());
532             c->sDryDelay.set_delay(latency);
533         }
534 
535         // Report latency
536         set_latency(latency);
537     }
538 
ui_activated()539     void compressor_base::ui_activated()
540     {
541         size_t channels     = (nMode == CM_MONO) ? 1 : 2;
542         for (size_t i=0; i<channels; ++i)
543             vChannels[i].nSync     = S_CURVE;
544         bUISync             = true;
545     }
546 
process_feedback(channel_t * c,size_t i,size_t channels)547     float compressor_base::process_feedback(channel_t *c, size_t i, size_t channels)
548     {
549         // Read input samples
550         float in[2];
551         if (channels > 1)
552         {
553             in[0] = vChannels[0].fFeedback;
554             in[1] = vChannels[1].fFeedback;
555         }
556         else
557         {
558             in[0] = c->fFeedback;
559             in[1] = 0.0f;
560         }
561 
562         // Process sidechain
563         float scin      = c->sSC.process(in);
564 
565         // Perform compression routine
566         c->vGain[i]     = c->sComp.process(&c->vEnv[i], scin);
567         c->vOut[i]      = c->vGain[i] * c->vIn[i];
568 
569         return scin;
570     }
571 
process_non_feedback(channel_t * c,float ** in,size_t samples)572     void compressor_base::process_non_feedback(channel_t *c, float **in, size_t samples)
573     {
574         c->sSC.process(c->vSc, const_cast<const float **>(in), samples);
575         c->sComp.process(c->vGain, c->vEnv, c->vSc, samples);
576         dsp::mul3(c->vOut, c->vGain, c->vIn, samples); // Adjust gain for input
577     }
578 
process(size_t samples)579     void compressor_base::process(size_t samples)
580     {
581         size_t channels = (nMode == CM_MONO) ? 1 : 2;
582         size_t feedback = 0;
583 
584         float *in_buf[2];   // Input buffer
585         float *out_buf[2];  // Output buffer
586         float *sc_buf[2];   // Sidechain source
587         float *in[2];       // Buffet to pass to sidechain
588 
589         // Prepare audio channels
590         for (size_t i=0; i<channels; ++i)
591         {
592             channel_t *c        = &vChannels[i];
593 
594             // Initialize pointers
595             in_buf[i]           = c->pIn->getBuffer<float>();
596             out_buf[i]          = c->pOut->getBuffer<float>();
597             sc_buf[i]           = (c->pSC != NULL) ? c->pSC->getBuffer<float>() : in_buf[i];
598 
599             // Analyze channel mode
600             if (c->nScType == SCT_FEED_BACK)
601                 feedback |= (1 << i);
602 
603 //            lsp_dumpf("in_buf", "%g", in_buf[i], samples);
604         }
605 
606         // Perform compression
607         size_t left = samples;
608         while (left > 0)
609         {
610             // Detemine number of samples to process
611             size_t to_process = (left > COMP_BUF_SIZE) ? COMP_BUF_SIZE : left;
612 
613             // Prepare audio channels
614             if (nMode == CM_MONO)
615                 dsp::mul_k3(vChannels[0].vIn, in_buf[0], fInGain, to_process);
616             else if (nMode == CM_MS)
617             {
618                 dsp::lr_to_ms(vChannels[0].vIn, vChannels[1].vIn, in_buf[0], in_buf[1], to_process);
619                 dsp::mul_k2(vChannels[0].vIn, fInGain, to_process);
620                 dsp::mul_k2(vChannels[1].vIn, fInGain, to_process);
621             }
622             else
623             {
624                 dsp::mul_k3(vChannels[0].vIn, in_buf[0], fInGain, to_process);
625                 dsp::mul_k3(vChannels[1].vIn, in_buf[1], fInGain, to_process);
626             }
627 
628             // Process meters
629             for (size_t i=0; i<channels; ++i)
630             {
631                 channel_t *c        = &vChannels[i];
632                 // Update input graph
633                 c->sGraph[G_IN].process(c->vIn, to_process);
634                 c->pMeter[M_IN]->setValue(dsp::abs_max(c->vIn, to_process));
635             }
636 
637             // Do compression
638             switch (feedback)
639             {
640                 case 0:
641                 {
642                     if (channels > 1) // Process second channel in stereo pair
643                     {
644                         // First channel
645                         in[0]   = (vChannels[0].nScType == SCT_EXTERNAL) ? sc_buf[0] : vChannels[0].vIn;
646                         in[1]   = (vChannels[0].nScType == SCT_EXTERNAL) ? sc_buf[1] : vChannels[1].vIn;
647                         process_non_feedback(&vChannels[0], in, to_process);
648                         vChannels[0].fFeedback      = vChannels[0].vOut[to_process-1];
649 
650                         // Second channel
651                         in[0]   = (vChannels[1].nScType == SCT_EXTERNAL) ? sc_buf[0] : vChannels[0].vIn;
652                         in[1]   = (vChannels[1].nScType == SCT_EXTERNAL) ? sc_buf[1] : vChannels[1].vIn;
653                         process_non_feedback(&vChannels[1], in, to_process);
654                         vChannels[1].fFeedback      = vChannels[1].vOut[to_process-1];
655                     }
656                     else
657                     {
658                         // Only one channel
659                         in[0]   = (vChannels[0].nScType == SCT_EXTERNAL) ? sc_buf[0] : vChannels[0].vIn;
660                         in[1]   = NULL;
661                         process_non_feedback(&vChannels[0], in, to_process);
662                         vChannels[0].fFeedback      = vChannels[0].vOut[to_process-1];
663                     }
664 
665                     break;
666                 }
667 
668                 case 1:
669                 {
670                     // 0=FB [1=FF/EXT]
671                     if (channels > 1)
672                     {
673                         // Second channel
674                         in[0]   = (vChannels[1].nScType == SCT_EXTERNAL) ? sc_buf[0] : vChannels[0].vIn;
675                         in[1]   = (vChannels[1].nScType == SCT_EXTERNAL) ? sc_buf[1] : vChannels[1].vIn;
676                         process_non_feedback(&vChannels[1], in, to_process);
677 //                        vChannels[1].fFeedback      = vChannels[1].vOut[to_process-1]; // do not update feedback at this time
678 
679                         // Process feedback channel
680                         for (size_t i=0; i<to_process; ++i)
681                         {
682                             vChannels[0].vSc[i]     = process_feedback(&vChannels[0], i, channels);
683                             vChannels[0].fFeedback  = vChannels[0].vOut[i];
684                             vChannels[1].fFeedback  = vChannels[1].vOut[i];
685                         }
686                     }
687                     else
688                     {
689                         // Process feedback channel
690                         for (size_t i=0; i<to_process; ++i)
691                         {
692                             vChannels[0].vSc[i]     = process_feedback(&vChannels[0], i, channels);
693                             vChannels[0].fFeedback  = vChannels[0].vOut[i];
694                         }
695                     }
696 
697                     break;
698                 }
699 
700                 case 2:
701                 {
702                     // 0=FF/EXT 1=FB
703                     // First channel
704                     in[0]   = (vChannels[0].nScType == SCT_EXTERNAL) ? sc_buf[0] : vChannels[0].vIn;
705                     in[1]   = (vChannels[0].nScType == SCT_EXTERNAL) ? sc_buf[1] : vChannels[1].vIn;
706                     process_non_feedback(&vChannels[0], in, to_process);
707 //                    vChannels[0].fFeedback      = vChannels[0].vOut[to_process-1]; // do not update feedback at this time
708 
709                     // Process feedback channel
710                     for (size_t i=0; i<to_process; ++i)
711                     {
712                         vChannels[1].vSc[i]     = process_feedback(&vChannels[1], i, channels);
713                         vChannels[1].fFeedback  = vChannels[1].vOut[i];
714                         vChannels[0].fFeedback  = vChannels[0].vOut[i];
715                     }
716 
717                     break;
718                 }
719 
720                 case 3:
721                 {
722                     // 0=FB, 1=FB
723                     for (size_t i=0; i<to_process; ++i)
724                     {
725                         vChannels[0].vSc[i]     = process_feedback(&vChannels[0], i, channels);
726                         vChannels[1].vSc[i]     = process_feedback(&vChannels[1], i, channels);
727                         vChannels[0].fFeedback  = vChannels[0].vOut[i];
728                         vChannels[1].fFeedback  = vChannels[1].vOut[i];
729                     }
730                     break;
731                 }
732                 default:
733                     break;
734             }
735 
736             // Apply gain to each channel and process meters
737             for (size_t i=0; i<channels; ++i)
738             {
739                 channel_t *c        = &vChannels[i];
740 
741                 // Add delay to original signal and apply gain
742                 c->sDelay.process(c->vOut, c->vIn, c->vGain, to_process);
743 
744                 // Apply latency compensation delay
745                 c->sCompDelay.process(c->vOut, c->vOut, to_process);
746 
747                 // Process graph outputs
748                 if ((i == 0) || (nMode != CM_STEREO))
749                 {
750                     c->sGraph[G_SC].process(c->vSc, to_process);                        // Sidechain signal
751                     c->pMeter[M_SC]->setValue(dsp::abs_max(c->vSc, to_process));
752 
753                     c->sGraph[G_GAIN].process(c->vGain, to_process);                    // Gain reduction signal
754                     c->pMeter[M_GAIN]->setValue(dsp::abs_max(c->vGain, to_process));
755 
756                     c->sGraph[G_ENV].process(c->vEnv, to_process);                      // Envelope signal
757                     c->pMeter[M_ENV]->setValue(dsp::abs_max(c->vEnv, to_process));
758                 }
759             }
760 
761             // Form output signal
762             if (nMode == CM_MS)
763             {
764                 channel_t *cm       = &vChannels[0];
765                 channel_t *cs       = &vChannels[1];
766 
767                 dsp::mix2(cm->vOut, cm->vIn, cm->fMakeup * cm->fWetGain, cm->fDryGain, to_process);
768                 dsp::mix2(cs->vOut, cs->vIn, cs->fMakeup * cs->fWetGain, cs->fDryGain, to_process);
769 
770                 cm->sGraph[G_OUT].process(cm->vOut, to_process);
771                 cm->pMeter[M_OUT]->setValue(dsp::abs_max(cm->vOut, to_process));
772                 cs->sGraph[G_OUT].process(cs->vOut, to_process);
773                 cs->pMeter[M_OUT]->setValue(dsp::abs_max(cs->vOut, to_process));
774 
775                 if (!bMSListen)
776                     dsp::ms_to_lr(cm->vOut, cs->vOut, cm->vOut, cs->vOut, to_process);
777                 if (cm->bScListen)
778                     dsp::copy(cm->vOut, cm->vSc, to_process);
779                 if (cs->bScListen)
780                     dsp::copy(cs->vOut, cs->vSc, to_process);
781             }
782             else
783             {
784                 for (size_t i=0; i<channels; ++i)
785                 {
786                     // Mix dry/wet signal or copy sidechain signal
787                     channel_t *c        = &vChannels[i];
788                     if (c->bScListen)
789                         dsp::copy(c->vOut, c->vSc, to_process);
790                     else
791                         dsp::mix2(c->vOut, c->vIn, c->fMakeup * c->fWetGain, c->fDryGain, to_process);
792 
793                     c->sGraph[G_OUT].process(c->vOut, to_process);                      // Output signal
794                     c->pMeter[M_OUT]->setValue(dsp::abs_max(c->vOut, to_process));
795                 }
796             }
797 
798             // Final metering
799             for (size_t i=0; i<channels; ++i)
800             {
801                 // Apply bypass
802                 channel_t *c        = &vChannels[i];
803                 c->sDryDelay.process(c->vIn, in_buf[i], to_process);                    // Apply latency compensation
804                 c->sBypass.process(out_buf[i], c->vIn, vChannels[i].vOut, to_process);
805 
806 //                dump_buffer("out_buf", out_buf[i], samples);
807 
808                 in_buf[i]          += to_process;
809                 out_buf[i]         += to_process;
810                 sc_buf[i]          += to_process;
811             }
812 
813             left       -= to_process;
814         }
815 
816         if ((!bPause) || (bClear) || (bUISync))
817         {
818             // Process mesh requests
819             for (size_t i=0; i<channels; ++i)
820             {
821                 // Get channel
822                 channel_t *c        = &vChannels[i];
823 
824                 for (size_t j=0; j<G_TOTAL; ++j)
825                 {
826                     // Check that port is bound
827                     if (c->pGraph[j] == NULL)
828                         continue;
829 
830                     // Clear data if requested
831                     if (bClear)
832                         dsp::fill_zero(c->sGraph[j].data(), compressor_base_metadata::TIME_MESH_SIZE);
833 
834                     // Get mesh
835                     mesh_t *mesh    = c->pGraph[j]->getBuffer<mesh_t>();
836                     if ((mesh != NULL) && (mesh->isEmpty()))
837                     {
838                         // Fill mesh with new values
839                         dsp::copy(mesh->pvData[0], vTime, compressor_base_metadata::TIME_MESH_SIZE);
840                         dsp::copy(mesh->pvData[1], c->sGraph[j].data(), compressor_base_metadata::TIME_MESH_SIZE);
841                         mesh->data(2, compressor_base_metadata::TIME_MESH_SIZE);
842                     }
843                 } // for j
844             }
845 
846             bUISync     = false;
847         }
848 
849         // Output compressor curves for each channel
850         for (size_t i=0; i<channels; ++i)
851         {
852             channel_t *c       = &vChannels[i];
853 
854             // Output compression curve
855             if (c->pCurve != NULL)
856             {
857                 mesh_t *mesh            = c->pCurve->getBuffer<mesh_t>();
858                 if ((c->nSync & S_CURVE) && (mesh != NULL) && (mesh->isEmpty()))
859                 {
860                     // Copy frequency points
861                     dsp::copy(mesh->pvData[0], vCurve, compressor_base_metadata::CURVE_MESH_SIZE);
862                     c->sComp.curve(mesh->pvData[1], vCurve, compressor_base_metadata::CURVE_MESH_SIZE);
863                     if (c->fMakeup != 1.0f)
864                         dsp::mul_k2(mesh->pvData[1], c->fMakeup, compressor_base_metadata::CURVE_MESH_SIZE);
865 
866                     // Mark mesh containing data
867                     mesh->data(2, compressor_base_metadata::CURVE_MESH_SIZE);
868                     c->nSync &= ~S_CURVE;
869                 }
870             }
871 
872             // Update meter
873             if ((c->pMeter[M_ENV] != NULL) && (c->pMeter[M_CURVE] != NULL))
874             {
875                 c->fDotIn   = c->pMeter[M_ENV]->getValue();
876                 c->fDotOut  = c->sComp.curve(c->fDotIn) * c->fMakeup;
877                 c->pMeter[M_CURVE]->setValue(c->fDotOut);
878             }
879         }
880 
881         // Request for redraw
882         if (pWrapper != NULL)
883             pWrapper->query_display_draw();
884     }
885 
inline_display(ICanvas * cv,size_t width,size_t height)886     bool compressor_base::inline_display(ICanvas *cv, size_t width, size_t height)
887     {
888         // Check proportions
889         if (height > width)
890             height  = width;
891 
892         // Init canvas
893         if (!cv->init(width, height))
894             return false;
895         width   = cv->width();
896         height  = cv->height();
897 
898         // Clear background
899         bool bypassing = vChannels[0].sBypass.bypassing();
900         cv->set_color_rgb((bypassing) ? CV_DISABLED : CV_BACKGROUND);
901         cv->paint();
902 
903         float zx    = 1.0f/GAIN_AMP_M_72_DB;
904         float zy    = 1.0f/GAIN_AMP_M_72_DB;
905         float dx    = width/(logf(GAIN_AMP_P_24_DB)-logf(GAIN_AMP_M_72_DB));
906         float dy    = height/(logf(GAIN_AMP_M_72_DB)-logf(GAIN_AMP_P_24_DB));
907 
908         // Draw horizontal and vertical lines
909         cv->set_line_width(1.0);
910         cv->set_color_rgb((bypassing) ? CV_SILVER: CV_YELLOW, 0.5f);
911         for (float i=GAIN_AMP_M_72_DB; i<GAIN_AMP_P_24_DB; i *= GAIN_AMP_P_24_DB)
912         {
913             float ax = dx*(logf(i*zx));
914             float ay = height + dy*(logf(i*zy));
915             cv->line(ax, 0, ax, height);
916             cv->line(0, ay, width, ay);
917         }
918 
919         // Draw 1:1 line
920         cv->set_line_width(2.0);
921         cv->set_color_rgb(CV_GRAY);
922         {
923             float ax1 = dx*(logf(GAIN_AMP_M_72_DB*zx));
924             float ax2 = dx*(logf(GAIN_AMP_P_24_DB*zx));
925             float ay1 = height + dy*(logf(GAIN_AMP_M_72_DB*zy));
926             float ay2 = height + dy*(logf(GAIN_AMP_P_24_DB*zy));
927             cv->line(ax1, ay1, ax2, ay2);
928         }
929 
930         // Draw axis
931         cv->set_color_rgb((bypassing) ? CV_SILVER : CV_WHITE);
932         {
933             float ax = dx*(logf(GAIN_AMP_0_DB*zx));
934             float ay = height + dy*(logf(GAIN_AMP_0_DB*zy));
935             cv->line(ax, 0, ax, height);
936             cv->line(0, ay, width, ay);
937         }
938 
939         // Reuse display
940         pIDisplay           = float_buffer_t::reuse(pIDisplay, 4, width);
941         float_buffer_t *b   = pIDisplay;
942         if (b == NULL)
943             return false;
944 
945         size_t channels = ((nMode == CM_MONO) || (nMode == CM_STEREO)) ? 1 : 2;
946         static uint32_t c_colors[] = {
947                 CV_MIDDLE_CHANNEL, CV_MIDDLE_CHANNEL,
948                 CV_MIDDLE_CHANNEL, CV_MIDDLE_CHANNEL,
949                 CV_LEFT_CHANNEL, CV_RIGHT_CHANNEL,
950                 CV_MIDDLE_CHANNEL, CV_SIDE_CHANNEL
951                };
952 
953         bool aa = cv->set_anti_aliasing(true);
954         cv->set_line_width(2);
955 
956         for (size_t i=0; i<channels; ++i)
957         {
958             channel_t *c    = &vChannels[i];
959 
960             for (size_t j=0; j<width; ++j)
961             {
962                 size_t k        = (j*compressor_base_metadata::CURVE_MESH_SIZE)/width;
963                 b->v[0][j]      = vCurve[k];
964             }
965             c->sComp.curve(b->v[1], b->v[0], width);
966             if (c->fMakeup != 1.0f)
967                 dsp::mul_k2(b->v[1], c->fMakeup, width);
968 
969             dsp::fill(b->v[2], 0.0f, width);
970             dsp::fill(b->v[3], height, width);
971             dsp::axis_apply_log1(b->v[2], b->v[0], zx, dx, width);
972             dsp::axis_apply_log1(b->v[3], b->v[1], zy, dy, width);
973 
974             // Draw mesh
975             uint32_t color = (bypassing || !(active())) ? CV_SILVER : c_colors[nMode*2 + i];
976             cv->set_color_rgb(color);
977             cv->draw_lines(b->v[2], b->v[3], width);
978         }
979 
980         // Draw dot
981         if (active())
982         {
983             for (size_t i=0; i<channels; ++i)
984             {
985                 channel_t *c    = &vChannels[i];
986 
987                 uint32_t color = (bypassing) ? CV_SILVER : c_colors[nMode*2 + i];
988                 Color c1(color), c2(color);
989                 c2.alpha(0.9);
990 
991                 float ax = dx*(logf(c->fDotIn*zx));
992                 float ay = height + dy*(logf(c->fDotOut*zy));
993 
994                 cv->radial_gradient(ax, ay, c1, c2, 12);
995                 cv->set_color_rgb(0);
996                 cv->circle(ax, ay, 4);
997                 cv->set_color_rgb(color);
998                 cv->circle(ax, ay, 3);
999             }
1000         }
1001 
1002         cv->set_anti_aliasing(aa);
1003 
1004         return true;
1005     }
1006 
dump(IStateDumper * v) const1007     void compressor_base::dump(IStateDumper *v) const
1008     {
1009         plugin_t::dump(v);
1010 
1011         size_t channels = (nMode == CM_MONO) ? 1 : 2;
1012 
1013         v->write("nMode", nMode);
1014         v->write("nChannels", channels);
1015         v->write("bSidechain", bSidechain);
1016 
1017         v->begin_array("vChannels", vChannels, channels);
1018         for (size_t i=0; i<channels; ++i)
1019         {
1020             const channel_t *c = &vChannels[i];
1021 
1022             v->begin_object(c, sizeof(channel_t));
1023             {
1024                 v->write_object("sBypass", &c->sBypass);
1025                 v->write_object("sSC", &c->sSC);
1026                 v->write_object("sSCEq", &c->sSCEq);
1027                 v->write_object("sComp", &c->sComp);
1028                 v->write_object("sDelay", &c->sDelay);
1029                 v->write_object("sCompDelay", &c->sCompDelay);
1030                 v->write_object("sDryDelay", &c->sDryDelay);
1031 
1032                 v->begin_array("sGraph", c->sGraph, G_TOTAL);
1033                 for (size_t j=0; j<G_TOTAL; ++j)
1034                     v->write_object(&c->sGraph[j]);
1035                 v->end_array();
1036 
1037                 v->write("vIn", c->vIn);
1038                 v->write("vOut", c->vOut);
1039                 v->write("vSc", c->vSc);
1040                 v->write("vEnv", c->vEnv);
1041                 v->write("vGain", c->vGain);
1042                 v->write("bScListen", c->bScListen);
1043                 v->write("nSync", c->nSync);
1044                 v->write("nScType", c->nScType);
1045                 v->write("fMakeup", c->fMakeup);
1046                 v->write("fFeedback", c->fFeedback);
1047                 v->write("fDryGain", c->fDryGain);
1048                 v->write("fWetGain", c->fWetGain);
1049                 v->write("fDotIn", c->fDotIn);
1050                 v->write("fDotOut", c->fDotOut);
1051 
1052                 v->write("pIn", c->pIn);
1053                 v->write("pOut", c->pOut);
1054                 v->write("pSC", c->pSC);
1055                 v->begin_array("pGraph", c->pGraph, G_TOTAL);
1056                 for (size_t j=0; j<G_TOTAL; ++j)
1057                     v->write(c->pGraph[j]);
1058                 v->end_array();
1059                 v->begin_array("pMeter", c->pGraph, M_TOTAL);
1060                 for (size_t j=0; j<M_TOTAL; ++j)
1061                     v->write(c->pMeter[j]);
1062                 v->end_array();
1063 
1064                 v->write("pScType", c->pScType);
1065                 v->write("pScMode", c->pScMode);
1066                 v->write("pScLookahead", c->pScLookahead);
1067                 v->write("pScListen", c->pScListen);
1068                 v->write("pScSource", c->pScSource);
1069                 v->write("pScReactivity", c->pScReactivity);
1070                 v->write("pScPreamp", c->pScPreamp);
1071                 v->write("pScHpfMode", c->pScHpfMode);
1072                 v->write("pScHpfFreq", c->pScHpfFreq);
1073                 v->write("pScLpfMode", c->pScLpfMode);
1074                 v->write("pScLpfFreq", c->pScLpfFreq);
1075 
1076                 v->write("pMode", c->pMode);
1077                 v->write("pAttackLvl", c->pAttackLvl);
1078                 v->write("pReleaseLvl", c->pReleaseLvl);
1079                 v->write("pAttackTime", c->pAttackTime);
1080                 v->write("pReleaseTime", c->pReleaseTime);
1081                 v->write("pRatio", c->pRatio);
1082                 v->write("pKnee", c->pKnee);
1083                 v->write("pBThresh", c->pBThresh);
1084                 v->write("pBoost", c->pBoost);
1085                 v->write("pMakeup", c->pMakeup);
1086 
1087                 v->write("pDryGain", c->pDryGain);
1088                 v->write("pWetGain", c->pWetGain);
1089                 v->write("pCurve", c->pCurve);
1090                 v->write("pReleaseOut", c->pReleaseOut);
1091             }
1092             v->end_object();
1093         }
1094         v->end_array();
1095 
1096         v->write("vCurve", vCurve);
1097         v->write("vTime", vTime);
1098         v->write("bPause", bPause);
1099         v->write("bClear", bClear);
1100         v->write("bMSListen", bMSListen);
1101         v->write("fInGain", fInGain);
1102         v->write("bUISync", bUISync);
1103         v->write("pIDisplay", pIDisplay);
1104         v->write("pBypass", pBypass);
1105         v->write("pInGain", pInGain);
1106         v->write("pOutGain", pOutGain);
1107         v->write("pPause", pPause);
1108         v->write("pClear", pClear);
1109         v->write("pMSListen", pMSListen);
1110         v->write("pData", pData);
1111     }
1112 
1113     //-------------------------------------------------------------------------
1114     // Compressor derivatives
compressor_mono()1115     compressor_mono::compressor_mono() : compressor_base(metadata, false, CM_MONO)
1116     {
1117     }
1118 
compressor_stereo()1119     compressor_stereo::compressor_stereo() : compressor_base(metadata, false, CM_STEREO)
1120     {
1121     }
1122 
compressor_lr()1123     compressor_lr::compressor_lr() : compressor_base(metadata, false, CM_LR)
1124     {
1125     }
1126 
compressor_ms()1127     compressor_ms::compressor_ms() : compressor_base(metadata, false, CM_MS)
1128     {
1129     }
1130 
sc_compressor_mono()1131     sc_compressor_mono::sc_compressor_mono() : compressor_base(metadata, true, CM_MONO)
1132     {
1133     }
1134 
sc_compressor_stereo()1135     sc_compressor_stereo::sc_compressor_stereo() : compressor_base(metadata, true, CM_STEREO)
1136     {
1137     }
1138 
sc_compressor_lr()1139     sc_compressor_lr::sc_compressor_lr() : compressor_base(metadata, true, CM_LR)
1140     {
1141     }
1142 
sc_compressor_ms()1143     sc_compressor_ms::sc_compressor_ms() : compressor_base(metadata, true, CM_MS)
1144     {
1145     }
1146 }
1147 
1148 
1149