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.

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