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