Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

813 lines
24KB

  1. /*
  2. * ZaMultiCompX2 Stereo multiband compressor
  3. * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "ZaMultiCompX2Plugin.hpp"
  18. START_NAMESPACE_DISTRHO
  19. // -----------------------------------------------------------------------
  20. ZaMultiCompX2Plugin::ZaMultiCompX2Plugin()
  21. : Plugin(paramCount, 1, 1) // 1 program, 1 state
  22. {
  23. // set default values
  24. d_setProgram(0);
  25. // reset
  26. d_deactivate();
  27. }
  28. ZaMultiCompX2Plugin::~ZaMultiCompX2Plugin()
  29. {
  30. }
  31. // -----------------------------------------------------------------------
  32. // Init
  33. void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter)
  34. {
  35. switch (index)
  36. {
  37. case paramAttack:
  38. parameter.hints = PARAMETER_IS_AUTOMABLE;
  39. parameter.name = "Attack";
  40. parameter.symbol = "att";
  41. parameter.unit = "ms";
  42. parameter.ranges.def = 10.0f;
  43. parameter.ranges.min = 0.1f;
  44. parameter.ranges.max = 100.0f;
  45. break;
  46. case paramRelease:
  47. parameter.hints = PARAMETER_IS_AUTOMABLE;
  48. parameter.name = "Release";
  49. parameter.symbol = "rel";
  50. parameter.unit = "ms";
  51. parameter.ranges.def = 80.0f;
  52. parameter.ranges.min = 1.0f;
  53. parameter.ranges.max = 500.0f;
  54. break;
  55. case paramKnee:
  56. parameter.hints = PARAMETER_IS_AUTOMABLE;
  57. parameter.name = "Knee";
  58. parameter.symbol = "kn";
  59. parameter.unit = "dB";
  60. parameter.ranges.def = 0.0f;
  61. parameter.ranges.min = 0.0f;
  62. parameter.ranges.max = 9.0f;
  63. break;
  64. case paramRatio:
  65. parameter.hints = PARAMETER_IS_AUTOMABLE;
  66. parameter.name = "Ratio";
  67. parameter.symbol = "rat";
  68. parameter.unit = " ";
  69. parameter.ranges.def = 4.0f;
  70. parameter.ranges.min = 1.0f;
  71. parameter.ranges.max = 20.0f;
  72. break;
  73. case paramThresh1:
  74. parameter.hints = PARAMETER_IS_AUTOMABLE;
  75. parameter.name = "Threshold 1";
  76. parameter.symbol = "thr1";
  77. parameter.unit = "dB";
  78. parameter.ranges.def = -20.0f;
  79. parameter.ranges.min = -60.0f;
  80. parameter.ranges.max = 0.0f;
  81. break;
  82. case paramThresh2:
  83. parameter.hints = PARAMETER_IS_AUTOMABLE;
  84. parameter.name = "Threshold 2";
  85. parameter.symbol = "thr2";
  86. parameter.unit = "dB";
  87. parameter.ranges.def = -18.0f;
  88. parameter.ranges.min = -60.0f;
  89. parameter.ranges.max = 0.0f;
  90. break;
  91. case paramThresh3:
  92. parameter.hints = PARAMETER_IS_AUTOMABLE;
  93. parameter.name = "Threshold 3";
  94. parameter.symbol = "thr3";
  95. parameter.unit = "dB";
  96. parameter.ranges.def = -16.0f;
  97. parameter.ranges.min = -60.0f;
  98. parameter.ranges.max = 0.0f;
  99. break;
  100. case paramMakeup1:
  101. parameter.hints = PARAMETER_IS_AUTOMABLE;
  102. parameter.name = "Makeup 1";
  103. parameter.symbol = "mak1";
  104. parameter.unit = "dB";
  105. parameter.ranges.def = 0.0f;
  106. parameter.ranges.min = 0.0f;
  107. parameter.ranges.max = 30.0f;
  108. break;
  109. case paramMakeup2:
  110. parameter.hints = PARAMETER_IS_AUTOMABLE;
  111. parameter.name = "Makeup 2";
  112. parameter.symbol = "mak2";
  113. parameter.unit = "dB";
  114. parameter.ranges.def = 0.0f;
  115. parameter.ranges.min = 0.0f;
  116. parameter.ranges.max = 30.0f;
  117. break;
  118. case paramMakeup3:
  119. parameter.hints = PARAMETER_IS_AUTOMABLE;
  120. parameter.name = "Makeup 3";
  121. parameter.symbol = "mak3";
  122. parameter.unit = "dB";
  123. parameter.ranges.def = 0.0f;
  124. parameter.ranges.min = 0.0f;
  125. parameter.ranges.max = 30.0f;
  126. break;
  127. case paramGainR1:
  128. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT;
  129. parameter.name = "Gain Reduction 1";
  130. parameter.symbol = "gr1";
  131. parameter.unit = "dB";
  132. parameter.ranges.def = 0.0f;
  133. parameter.ranges.min = 0.0f;
  134. parameter.ranges.max = 20.0f;
  135. break;
  136. case paramGainR2:
  137. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT;
  138. parameter.name = "Gain Reduction 2";
  139. parameter.symbol = "gr2";
  140. parameter.unit = "dB";
  141. parameter.ranges.def = 0.0f;
  142. parameter.ranges.min = 0.0f;
  143. parameter.ranges.max = 20.0f;
  144. break;
  145. case paramGainR3:
  146. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT;
  147. parameter.name = "Gain Reduction 3";
  148. parameter.symbol = "gr3";
  149. parameter.unit = "dB";
  150. parameter.ranges.def = 0.0f;
  151. parameter.ranges.min = 0.0f;
  152. parameter.ranges.max = 20.0f;
  153. break;
  154. case paramXover1:
  155. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC;
  156. parameter.name = "Crossover freq 1";
  157. parameter.symbol = "xover1";
  158. parameter.unit = "Hz";
  159. parameter.ranges.def = 500.0f;
  160. parameter.ranges.min = 20.0f;
  161. parameter.ranges.max = 20000.0f;
  162. break;
  163. case paramXover2:
  164. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC;
  165. parameter.name = "Crossover freq 2";
  166. parameter.symbol = "xover2";
  167. parameter.unit = "Hz";
  168. parameter.ranges.def = 3000.0f;
  169. parameter.ranges.min = 20.0f;
  170. parameter.ranges.max = 20000.0f;
  171. break;
  172. case paramToggle1:
  173. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  174. parameter.name = "ZamComp 1 ON";
  175. parameter.symbol = "toggle1";
  176. parameter.unit = " ";
  177. parameter.ranges.def = 0.0f;
  178. parameter.ranges.min = 0.0f;
  179. parameter.ranges.max = 1.0f;
  180. break;
  181. case paramToggle2:
  182. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  183. parameter.name = "ZamComp 2 ON";
  184. parameter.symbol = "toggle2";
  185. parameter.unit = " ";
  186. parameter.ranges.def = 0.0f;
  187. parameter.ranges.min = 0.0f;
  188. parameter.ranges.max = 1.0f;
  189. break;
  190. case paramToggle3:
  191. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  192. parameter.name = "ZamComp 3 ON";
  193. parameter.symbol = "toggle3";
  194. parameter.unit = " ";
  195. parameter.ranges.def = 0.0f;
  196. parameter.ranges.min = 0.0f;
  197. parameter.ranges.max = 1.0f;
  198. break;
  199. case paramListen1:
  200. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  201. parameter.name = "Listen 1";
  202. parameter.symbol = "listen1";
  203. parameter.unit = " ";
  204. parameter.ranges.def = 0.0f;
  205. parameter.ranges.min = 0.0f;
  206. parameter.ranges.max = 1.0f;
  207. break;
  208. case paramListen2:
  209. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  210. parameter.name = "Listen 2";
  211. parameter.symbol = "listen2";
  212. parameter.unit = " ";
  213. parameter.ranges.def = 0.0f;
  214. parameter.ranges.min = 0.0f;
  215. parameter.ranges.max = 1.0f;
  216. break;
  217. case paramListen3:
  218. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  219. parameter.name = "Listen 3";
  220. parameter.symbol = "listen3";
  221. parameter.unit = " ";
  222. parameter.ranges.def = 0.0f;
  223. parameter.ranges.min = 0.0f;
  224. parameter.ranges.max = 1.0f;
  225. break;
  226. case paramGlobalGain:
  227. parameter.hints = PARAMETER_IS_AUTOMABLE;
  228. parameter.name = "Master Trim";
  229. parameter.symbol = "globalgain";
  230. parameter.unit = "dB";
  231. parameter.ranges.def = 0.0f;
  232. parameter.ranges.min = -12.0f;
  233. parameter.ranges.max = 12.0f;
  234. break;
  235. case paramStereoDet:
  236. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  237. parameter.name = "Detection (MAX/avg)";
  238. parameter.symbol = "stereodet";
  239. parameter.unit = " ";
  240. parameter.ranges.def = 1.0f;
  241. parameter.ranges.min = 0.0f;
  242. parameter.ranges.max = 1.0f;
  243. break;
  244. case paramOutputLevelL:
  245. parameter.hints = PARAMETER_IS_OUTPUT;
  246. parameter.name = "Output Left";
  247. parameter.symbol = "outl";
  248. parameter.unit = "dB";
  249. parameter.ranges.def = -45.0f;
  250. parameter.ranges.min = -45.0f;
  251. parameter.ranges.max = 20.0f;
  252. break;
  253. case paramOutputLevelR:
  254. parameter.hints = PARAMETER_IS_OUTPUT;
  255. parameter.name = "Output Right";
  256. parameter.symbol = "outr";
  257. parameter.unit = "dB";
  258. parameter.ranges.def = -45.0f;
  259. parameter.ranges.min = -45.0f;
  260. parameter.ranges.max = 20.0f;
  261. break;
  262. }
  263. }
  264. void ZaMultiCompX2Plugin::d_initProgramName(uint32_t index, d_string& programName)
  265. {
  266. if (index != 0)
  267. return;
  268. programName = "Default";
  269. }
  270. // -----------------------------------------------------------------------
  271. // Internal data
  272. float ZaMultiCompX2Plugin::d_getParameterValue(uint32_t index) const
  273. {
  274. switch (index)
  275. {
  276. case paramAttack:
  277. return attack;
  278. break;
  279. case paramRelease:
  280. return release;
  281. break;
  282. case paramKnee:
  283. return knee;
  284. break;
  285. case paramRatio:
  286. return ratio;
  287. break;
  288. case paramThresh1:
  289. return thresdb[0];
  290. break;
  291. case paramThresh2:
  292. return thresdb[1];
  293. break;
  294. case paramThresh3:
  295. return thresdb[2];
  296. break;
  297. case paramMakeup1:
  298. return makeup[0];
  299. break;
  300. case paramMakeup2:
  301. return makeup[1];
  302. break;
  303. case paramMakeup3:
  304. return makeup[2];
  305. break;
  306. case paramGainR1:
  307. return gainr[0];
  308. break;
  309. case paramGainR2:
  310. return gainr[1];
  311. break;
  312. case paramGainR3:
  313. return gainr[2];
  314. break;
  315. case paramXover1:
  316. return xover1;
  317. break;
  318. case paramXover2:
  319. return xover2;
  320. break;
  321. case paramToggle1:
  322. return toggle[0];
  323. break;
  324. case paramToggle2:
  325. return toggle[1];
  326. break;
  327. case paramToggle3:
  328. return toggle[2];
  329. break;
  330. case paramListen1:
  331. return listen[0];
  332. break;
  333. case paramListen2:
  334. return listen[1];
  335. break;
  336. case paramListen3:
  337. return listen[2];
  338. break;
  339. case paramGlobalGain:
  340. return globalgain;
  341. break;
  342. case paramStereoDet:
  343. return stereodet;
  344. break;
  345. case paramOutputLevelL:
  346. return outl;
  347. break;
  348. case paramOutputLevelR:
  349. return outr;
  350. break;
  351. default:
  352. return 0.0f;
  353. }
  354. }
  355. void ZaMultiCompX2Plugin::d_setParameterValue(uint32_t index, float value)
  356. {
  357. switch (index)
  358. {
  359. case paramAttack:
  360. attack = value;
  361. break;
  362. case paramRelease:
  363. release = value;
  364. break;
  365. case paramKnee:
  366. knee = value;
  367. break;
  368. case paramRatio:
  369. ratio = value;
  370. break;
  371. case paramThresh1:
  372. thresdb[0] = value;
  373. break;
  374. case paramThresh2:
  375. thresdb[1] = value;
  376. break;
  377. case paramThresh3:
  378. thresdb[2] = value;
  379. break;
  380. case paramMakeup1:
  381. makeup[0] = value;
  382. break;
  383. case paramMakeup2:
  384. makeup[1] = value;
  385. break;
  386. case paramMakeup3:
  387. makeup[2] = value;
  388. break;
  389. case paramGainR1:
  390. gainr[0] = value;
  391. break;
  392. case paramGainR2:
  393. gainr[1] = value;
  394. break;
  395. case paramGainR3:
  396. gainr[2] = value;
  397. break;
  398. case paramXover1:
  399. xover1 = value;
  400. break;
  401. case paramXover2:
  402. xover2 = value;
  403. break;
  404. case paramToggle1:
  405. toggle[0] = value;
  406. if (value == 0.f)
  407. gainr[0] = 0.f;
  408. break;
  409. case paramToggle2:
  410. toggle[1] = value;
  411. if (value == 0.f)
  412. gainr[1] = 0.f;
  413. break;
  414. case paramToggle3:
  415. toggle[2] = value;
  416. if (value == 0.f)
  417. gainr[2] = 0.f;
  418. break;
  419. case paramListen1:
  420. listen[0] = value;
  421. if (value == 0.f)
  422. gainr[0] = 0.f;
  423. break;
  424. case paramListen2:
  425. listen[1] = value;
  426. if (value == 0.f)
  427. gainr[1] = 0.f;
  428. break;
  429. case paramListen3:
  430. listen[2] = value;
  431. if (value == 0.f)
  432. gainr[2] = 0.f;
  433. break;
  434. case paramGlobalGain:
  435. globalgain = value;
  436. break;
  437. case paramStereoDet:
  438. stereodet = value;
  439. break;
  440. case paramOutputLevelL:
  441. outl = value;
  442. break;
  443. case paramOutputLevelR:
  444. outr = value;
  445. break;
  446. }
  447. }
  448. void ZaMultiCompX2Plugin::d_setProgram(uint32_t index)
  449. {
  450. if (index != 0)
  451. return;
  452. /* Default parameter values */
  453. attack = 10.0f;
  454. release = 80.0f;
  455. knee = 0.0f;
  456. ratio = 4.0f;
  457. thresdb[0] = -20.0f;
  458. thresdb[1] = -18.0f;
  459. thresdb[2] = -16.0f;
  460. makeup[0] = 0.0f;
  461. makeup[1] = 0.0f;
  462. makeup[2] = 0.0f;
  463. gainr[0] = 0.0f;
  464. gainr[1] = 0.0f;
  465. gainr[2] = 0.0f;
  466. xover1 = 500.0f;
  467. xover2 = 3000.0f;
  468. toggle[0] = 0.0f;
  469. toggle[1] = 0.0f;
  470. toggle[2] = 0.0f;
  471. listen[0] = 0.0f;
  472. listen[1] = 0.0f;
  473. listen[2] = 0.0f;
  474. globalgain = 0.0f;
  475. stereodet = 1.0f;
  476. outl = -45.f;
  477. outr = -45.f;
  478. maxL = 0.f;
  479. maxR = 0.f;
  480. /* Default variable values */
  481. /* reset filter values */
  482. d_activate();
  483. }
  484. void ZaMultiCompX2Plugin::d_setState(const char* key, const char* value)
  485. {
  486. resetl = true;
  487. resetr = true;
  488. }
  489. void ZaMultiCompX2Plugin::d_initStateKey(unsigned int key, d_string& val)
  490. {
  491. }
  492. // -----------------------------------------------------------------------
  493. // Process
  494. void ZaMultiCompX2Plugin::d_activate()
  495. {
  496. int i,j;
  497. for (i = 0; i < MAX_COMP; i++)
  498. for (j = 0; j < 2; j++)
  499. old_yl[j][i]=old_y1[j][i]=0.f;
  500. for (i = 0; i < MAX_FILT; i++) {
  501. for (j = 0; j < 2; j++) {
  502. a0[j][i] = a1[j][i] = a2[j][i] = 0.f;
  503. b1[j][i] = b2[j][i] = 0.f;
  504. w1[j][i] = w2[j][i] = 0.f;
  505. z1[j][i] = z2[j][i] = 0.f;
  506. }
  507. }
  508. maxL = maxR = 0.f;
  509. }
  510. void ZaMultiCompX2Plugin::d_deactivate()
  511. {
  512. // all values to zero
  513. d_activate();
  514. }
  515. float ZaMultiCompX2Plugin::run_filter(int i, int ch, float in)
  516. {
  517. in = sanitize_denormal(in);
  518. w1[ch][i] = sanitize_denormal(w1[ch][i]);
  519. w2[ch][i] = sanitize_denormal(w2[ch][i]);
  520. z1[ch][i] = sanitize_denormal(z1[ch][i]);
  521. z2[ch][i] = sanitize_denormal(z2[ch][i]);
  522. float out = in * a0[ch][i] + w1[ch][i] * a1[ch][i] + w2[ch][i] * a2[ch][i]
  523. - z1[ch][i] * b1[ch][i] - z2[ch][i] * b2[ch][i];
  524. out = sanitize_denormal(out);
  525. w2[ch][i] = w1[ch][i];
  526. z2[ch][i] = z1[ch][i];
  527. w1[ch][i] = in;
  528. z1[ch][i] = out;
  529. return out;
  530. }
  531. void ZaMultiCompX2Plugin::set_lp_coeffs(float fc, float q, float sr, int i, int ch, float gain=1.0)
  532. {
  533. float omega=(float)(2.f*M_PI*fc/sr);
  534. float sn=sin(omega);
  535. float cs=cos(omega);
  536. float alpha=(float)(sn/(2.f*q));
  537. float inv=(float)(1.0/(1.0+alpha));
  538. a2[ch][i] = a0[ch][i] = (float)(gain*inv*(1.f - cs)*0.5f);
  539. a1[ch][i] = a0[ch][i] + a0[ch][i];
  540. b1[ch][i] = (float)(-2.f*cs*inv);
  541. b2[ch][i] = (float)((1.f - alpha)*inv);
  542. }
  543. void ZaMultiCompX2Plugin::set_hp_coeffs(float fc, float q, float sr, int i, int ch, float gain=1.0)
  544. {
  545. float omega=(float)(2.f*M_PI*fc/sr);
  546. float sn=sin(omega);
  547. float cs=cos(omega);
  548. float alpha=(float)(sn/(2.f*q));
  549. float inv=(float)(1.f/(1.f+alpha));
  550. a0[ch][i] = (float)(gain*inv*(1.f + cs)/2.f);
  551. a1[ch][i] = -2.f * a0[ch][i];
  552. a2[ch][i] = a0[ch][i];
  553. b1[ch][i] = (float)(-2.f*cs*inv);
  554. b2[ch][i] = (float)((1.f - alpha)*inv);
  555. }
  556. void ZaMultiCompX2Plugin::run_comp(int k, float inL, float inR, float *outL, float *outR)
  557. {
  558. float srate = d_getSampleRate();
  559. float width=(knee-0.99f)*6.f;
  560. float attack_coeff = exp(-1000.f/(attack * srate));
  561. float release_coeff = exp(-1000.f/(release * srate));
  562. int stereolink = (stereodet > 0.5f) ? STEREOLINK_MAX : STEREOLINK_AVERAGE;
  563. float cdb=0.f;
  564. float Lgain = 1.f;
  565. float Rgain = 1.f;
  566. float Lxg, Lyg;
  567. float Rxg, Ryg;
  568. float Lxl, Lyl, Ly1;
  569. float Rxl, Ryl, Ry1;
  570. Lyg = Ryg = 0.f;
  571. inL = sanitize_denormal(inL);
  572. inR = sanitize_denormal(inR);
  573. Lxg = (inL==0.f) ? -160.f : to_dB(fabs(inL));
  574. Rxg = (inR==0.f) ? -160.f : to_dB(fabs(inR));
  575. Lxg = sanitize_denormal(Lxg);
  576. Rxg = sanitize_denormal(Rxg);
  577. if (2.f*(Lxg-thresdb[k])<-width) {
  578. Lyg = Lxg;
  579. } else if (2.f*fabs(Lxg-thresdb[k])<=width) {
  580. Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb[k]+width/2.f)*(Lxg-thresdb[k]+width/2.f)/(2.f*width);
  581. } else if (2.f*(Lxg-thresdb[k])>width) {
  582. Lyg = thresdb[k] + (Lxg-thresdb[k])/ratio;
  583. }
  584. Lyg = sanitize_denormal(Lyg);
  585. if (2.f*(Rxg-thresdb[k])<-width) {
  586. Ryg = Rxg;
  587. } else if (2.f*fabs(Rxg-thresdb[k])<=width) {
  588. Ryg = Rxg + (1.f/ratio-1.f)*(Rxg-thresdb[k]+width/2.f)*(Rxg-thresdb[k]+width/2.f)/(2.f*width);
  589. } else if (2.f*(Rxg-thresdb[k])>width) {
  590. Ryg = thresdb[k] + (Rxg-thresdb[k])/ratio;
  591. }
  592. Ryg = sanitize_denormal(Ryg);
  593. if (stereolink == STEREOLINK_MAX) {
  594. Lxl = Rxl = fmaxf(Lxg - Lyg, Rxg - Ryg);
  595. } else {
  596. Lxl = Rxl = (Lxg - Lyg + Rxg - Ryg) / 2.f;
  597. }
  598. old_y1[0][k] = sanitize_denormal(old_y1[0][k]);
  599. old_y1[1][k] = sanitize_denormal(old_y1[1][k]);
  600. old_yl[0][k] = sanitize_denormal(old_yl[0][k]);
  601. old_yl[1][k] = sanitize_denormal(old_yl[1][k]);
  602. Ly1 = fmaxf(Lxl, release_coeff * old_y1[0][k]+(1.f-release_coeff)*Lxl);
  603. Lyl = attack_coeff * old_yl[0][k]+(1.f-attack_coeff)*Ly1;
  604. Ly1 = sanitize_denormal(Ly1);
  605. Lyl = sanitize_denormal(Lyl);
  606. cdb = -Lyl;
  607. Lgain = from_dB(cdb);
  608. Ry1 = fmaxf(Rxl, release_coeff * old_y1[1][k]+(1.f-release_coeff)*Rxl);
  609. Ryl = attack_coeff * old_yl[1][k]+(1.f-attack_coeff)*Ry1;
  610. Ry1 = sanitize_denormal(Ry1);
  611. Ryl = sanitize_denormal(Ryl);
  612. cdb = -Ryl;
  613. Rgain = from_dB(cdb);
  614. if (stereolink == STEREOLINK_MAX)
  615. gainr[k] = fmaxf(Lyl, Ryl);
  616. else
  617. gainr[k] = (Lyl + Ryl) / 2.f;
  618. *outL = inL;
  619. *outL *= Lgain;
  620. *outR = inR;
  621. *outR *= Rgain;
  622. old_yl[0][k] = Lyl;
  623. old_yl[1][k] = Ryl;
  624. old_y1[0][k] = Ly1;
  625. old_y1[1][k] = Ry1;
  626. }
  627. void ZaMultiCompX2Plugin::d_run(float** inputs, float** outputs, uint32_t frames)
  628. {
  629. float srate = d_getSampleRate();
  630. float maxxL = maxL;
  631. float maxxR = maxR;
  632. int tog1 = (toggle[0] > 0.5f) ? 1 : 0;
  633. int tog2 = (toggle[1] > 0.5f) ? 1 : 0;
  634. int tog3 = (toggle[2] > 0.5f) ? 1 : 0;
  635. int listen1 = (listen[0] > 0.5f) ? 1 : 0;
  636. int listen2 = (listen[1] > 0.5f) ? 1 : 0;
  637. int listen3 = (listen[2] > 0.5f) ? 1 : 0;
  638. set_lp_coeffs(xover1, ONEOVERROOT2, srate, 0, 0);
  639. set_lp_coeffs(xover1, ONEOVERROOT2, srate, 1, 0);
  640. set_hp_coeffs(xover1, ONEOVERROOT2, srate, 2, 0);
  641. set_hp_coeffs(xover1, ONEOVERROOT2, srate, 3, 0);
  642. set_lp_coeffs(xover2, ONEOVERROOT2, srate, 4, 0);
  643. set_lp_coeffs(xover2, ONEOVERROOT2, srate, 5, 0);
  644. set_hp_coeffs(xover2, ONEOVERROOT2, srate, 6, 0);
  645. set_hp_coeffs(xover2, ONEOVERROOT2, srate, 7, 0);
  646. set_lp_coeffs(xover1, ONEOVERROOT2, srate, 0, 1);
  647. set_lp_coeffs(xover1, ONEOVERROOT2, srate, 1, 1);
  648. set_hp_coeffs(xover1, ONEOVERROOT2, srate, 2, 1);
  649. set_hp_coeffs(xover1, ONEOVERROOT2, srate, 3, 1);
  650. set_lp_coeffs(xover2, ONEOVERROOT2, srate, 4, 1);
  651. set_lp_coeffs(xover2, ONEOVERROOT2, srate, 5, 1);
  652. set_hp_coeffs(xover2, ONEOVERROOT2, srate, 6, 1);
  653. set_hp_coeffs(xover2, ONEOVERROOT2, srate, 7, 1);
  654. for (uint32_t i = 0; i < frames; ++i) {
  655. float tmp1[2], tmp2[2], tmp3[2], tmp4[2], tmp5[2], tmp6[2];
  656. float fil1[2], fil2[2], fil3[2], fil4[2];
  657. float outL[MAX_COMP] = {0.f};
  658. float outR[MAX_COMP] = {0.f};
  659. float inl = sanitize_denormal(inputs[0][i]);
  660. float inr = sanitize_denormal(inputs[1][i]);
  661. inl = (fabs(inl) < DANGER) ? inl : 0.f;
  662. inr = (fabs(inr) < DANGER) ? inr : 0.f;
  663. int listenmode = 0;
  664. // Interleaved channel processing
  665. fil1[0] = run_filter(0, 0, inl);
  666. fil1[1] = run_filter(0, 1, inr);
  667. tmp1[0] = run_filter(1, 0, fil1[0]);
  668. tmp1[1] = run_filter(1, 1, fil1[1]);
  669. if (tog1)
  670. run_comp(0, tmp1[0], tmp1[1], &outL[0], &outR[0]);
  671. tmp2[0] = tog1 ? outL[0] * from_dB(makeup[0]) : tmp1[0];
  672. tmp2[1] = tog1 ? outR[0] * from_dB(makeup[0]) : tmp1[1];
  673. fil2[0] = run_filter(2, 0, inl);
  674. fil2[1] = run_filter(2, 1, inr);
  675. tmp3[0] = run_filter(3, 0, fil2[0]);
  676. tmp3[1] = run_filter(3, 1, fil2[1]);
  677. fil3[0] = run_filter(4, 0, tmp3[0]);
  678. fil3[1] = run_filter(4, 1, tmp3[1]);
  679. tmp4[0] = run_filter(5, 0, fil3[0]);
  680. tmp4[1] = run_filter(5, 1, fil3[1]);
  681. if (tog2)
  682. run_comp(1, tmp4[0], tmp4[1], &outL[1], &outR[1]);
  683. tmp3[0] = tog2 ? outL[1] * from_dB(makeup[1]) : tmp4[0];
  684. tmp3[1] = tog2 ? outR[1] * from_dB(makeup[1]) : tmp4[1];
  685. fil4[0] = run_filter(6, 0, inl);
  686. fil4[1] = run_filter(6, 1, inr);
  687. tmp5[0] = run_filter(7, 0, fil4[0]);
  688. tmp5[1] = run_filter(7, 1, fil4[1]);
  689. if (tog3)
  690. run_comp(2, tmp5[0], tmp5[1], &outL[2], &outR[2]);
  691. tmp6[0] = tog3 ? outL[2] * from_dB(makeup[2]) : tmp5[0];
  692. tmp6[1] = tog3 ? outR[2] * from_dB(makeup[2]) : tmp5[1];
  693. outputs[0][i] = outputs[1][i] = 0.f;
  694. if (listen1) {
  695. listenmode = 1;
  696. outputs[0][i] += outL[0] * tog1*from_dB(makeup[0])
  697. + (1.-tog1) * tmp1[0];
  698. outputs[1][i] += outR[0] * tog1*from_dB(makeup[0])
  699. + (1.-tog1) * tmp1[1];
  700. }
  701. if (listen2) {
  702. listenmode = 1;
  703. outputs[0][i] += outL[1] * tog2*from_dB(makeup[1])
  704. + (1.-tog2) * tmp4[0];
  705. outputs[1][i] += outR[1] * tog2*from_dB(makeup[1])
  706. + (1.-tog2) * tmp4[1];
  707. }
  708. if (listen3) {
  709. listenmode = 1;
  710. outputs[0][i] += outL[2] * tog3*from_dB(makeup[2])
  711. + (1.-tog3) * tmp5[0];
  712. outputs[1][i] += outR[2] * tog3*from_dB(makeup[2])
  713. + (1.-tog3) * tmp5[1];
  714. }
  715. if (!listenmode) {
  716. outputs[0][i] = tmp2[0] + tmp3[0] + tmp6[0];
  717. outputs[1][i] = tmp2[1] + tmp3[1] + tmp6[1];
  718. }
  719. outputs[0][i] = sanitize_denormal(outputs[0][i]);
  720. outputs[1][i] = sanitize_denormal(outputs[1][i]);
  721. outputs[0][i] *= from_dB(globalgain);
  722. outputs[1][i] *= from_dB(globalgain);
  723. if (resetl) {
  724. maxL = fabsf(outputs[0][i]);
  725. resetl = false;
  726. } else {
  727. maxxL = (fabsf(outputs[0][i]) > maxxL) ? fabsf(outputs[0][i]) : sanitize_denormal(maxxL);
  728. }
  729. if (resetr) {
  730. maxR = fabsf(outputs[1][i]);
  731. resetr = false;
  732. } else {
  733. maxxR = (fabsf(outputs[1][i]) > maxxR) ? fabsf(outputs[1][i]) : sanitize_denormal(maxxR);
  734. }
  735. }
  736. outl = (maxxL <= 0.f) ? -160.f : to_dB(maxxL);
  737. outr = (maxxR <= 0.f) ? -160.f : to_dB(maxxR);
  738. }
  739. // -----------------------------------------------------------------------
  740. Plugin* createPlugin()
  741. {
  742. return new ZaMultiCompX2Plugin();
  743. }
  744. // -----------------------------------------------------------------------
  745. END_NAMESPACE_DISTRHO