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.

346 lines
10.0KB

  1. /*
  2. * ZamCompX2 Stereo 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 "ZamCompX2Plugin.hpp"
  18. START_NAMESPACE_DISTRHO
  19. // -----------------------------------------------------------------------
  20. ZamCompX2Plugin::ZamCompX2Plugin()
  21. : Plugin(paramCount, 1, 0) // 1 program, 0 states
  22. {
  23. // set default values
  24. d_setProgram(0);
  25. // reset
  26. d_deactivate();
  27. }
  28. ZamCompX2Plugin::~ZamCompX2Plugin()
  29. {
  30. }
  31. // -----------------------------------------------------------------------
  32. // Init
  33. void ZamCompX2Plugin::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 paramThresh:
  74. parameter.hints = PARAMETER_IS_AUTOMABLE;
  75. parameter.name = "Threshold";
  76. parameter.symbol = "thr";
  77. parameter.unit = "dB";
  78. parameter.ranges.def = 0.0f;
  79. parameter.ranges.min = -80.0f;
  80. parameter.ranges.max = 0.0f;
  81. break;
  82. case paramMakeup:
  83. parameter.hints = PARAMETER_IS_AUTOMABLE;
  84. parameter.name = "Makeup";
  85. parameter.symbol = "mak";
  86. parameter.unit = "dB";
  87. parameter.ranges.def = 0.0f;
  88. parameter.ranges.min = 0.0f;
  89. parameter.ranges.max = 30.0f;
  90. break;
  91. case paramGainRed:
  92. parameter.hints = PARAMETER_IS_OUTPUT;
  93. parameter.name = "Gain Reduction";
  94. parameter.symbol = "gr";
  95. parameter.unit = "dB";
  96. parameter.ranges.def = 0.0f;
  97. parameter.ranges.min = 0.0f;
  98. parameter.ranges.max = 20.0f;
  99. break;
  100. case paramStereo:
  101. parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER;
  102. parameter.name = "Stereolink";
  103. parameter.symbol = "stereo";
  104. parameter.unit = " ";
  105. parameter.ranges.def = 1.0f;
  106. parameter.ranges.min = 0.0f;
  107. parameter.ranges.max = 2.0f;
  108. break;
  109. case paramOutputLevel:
  110. parameter.hints = PARAMETER_IS_OUTPUT;
  111. parameter.name = "Output Level";
  112. parameter.symbol = "outlevel";
  113. parameter.unit = "dB";
  114. parameter.ranges.def = -45.0f;
  115. parameter.ranges.min = -45.0f;
  116. parameter.ranges.max = 20.0f;
  117. break;
  118. }
  119. }
  120. void ZamCompX2Plugin::d_initProgramName(uint32_t index, d_string& programName)
  121. {
  122. if (index != 0)
  123. return;
  124. programName = "Default";
  125. }
  126. // -----------------------------------------------------------------------
  127. // Internal data
  128. float ZamCompX2Plugin::d_getParameterValue(uint32_t index) const
  129. {
  130. switch (index)
  131. {
  132. case paramAttack:
  133. return attack;
  134. break;
  135. case paramRelease:
  136. return release;
  137. break;
  138. case paramKnee:
  139. return knee;
  140. break;
  141. case paramRatio:
  142. return ratio;
  143. break;
  144. case paramThresh:
  145. return thresdb;
  146. break;
  147. case paramMakeup:
  148. return makeup;
  149. break;
  150. case paramGainRed:
  151. return gainred;
  152. break;
  153. case paramStereo:
  154. return stereolink;
  155. break;
  156. case paramOutputLevel:
  157. return outlevel;
  158. break;
  159. default:
  160. return 0.0f;
  161. }
  162. }
  163. void ZamCompX2Plugin::d_setParameterValue(uint32_t index, float value)
  164. {
  165. switch (index)
  166. {
  167. case paramAttack:
  168. attack = value;
  169. break;
  170. case paramRelease:
  171. release = value;
  172. break;
  173. case paramKnee:
  174. knee = value;
  175. break;
  176. case paramRatio:
  177. ratio = value;
  178. break;
  179. case paramThresh:
  180. thresdb = value;
  181. break;
  182. case paramMakeup:
  183. makeup = value;
  184. break;
  185. case paramGainRed:
  186. gainred = value;
  187. break;
  188. case paramStereo:
  189. stereolink = value;
  190. break;
  191. case paramOutputLevel:
  192. outlevel = value;
  193. break;
  194. }
  195. }
  196. void ZamCompX2Plugin::d_setProgram(uint32_t index)
  197. {
  198. if (index != 0)
  199. return;
  200. /* Default parameter values */
  201. attack = 10.0f;
  202. release = 80.0f;
  203. knee = 0.0f;
  204. ratio = 4.0f;
  205. thresdb = 0.0f;
  206. makeup = 0.0f;
  207. gainred = 0.0f;
  208. stereolink = 1.0f;
  209. outlevel = -45.0f;
  210. /* Default variable values */
  211. /* reset filter values */
  212. d_activate();
  213. }
  214. // -----------------------------------------------------------------------
  215. // Process
  216. void ZamCompX2Plugin::d_activate()
  217. {
  218. oldL_yl = oldL_y1 = oldR_yl = oldR_y1 = 0.f;
  219. }
  220. void ZamCompX2Plugin::d_deactivate()
  221. {
  222. // all values to zero
  223. }
  224. void ZamCompX2Plugin::d_run(float** inputs, float** outputs, uint32_t frames)
  225. {
  226. float srate = d_getSampleRate();
  227. float width=(knee-0.99f)*6.f;
  228. float cdb=0.f;
  229. float attack_coeff = exp(-1000.f/(attack * srate));
  230. float release_coeff = exp(-1000.f/(release * srate));
  231. int stereo = (stereolink > 1.f) ? STEREOLINK_MAX : (stereolink > 0.f) ? STEREOLINK_AVERAGE : STEREOLINK_UNCOUPLED;
  232. float max = 0.f;
  233. float Lgain = 1.f;
  234. float Rgain = 1.f;
  235. float Lxg, Lxl, Lyg, Lyl, Ly1;
  236. float Rxg, Rxl, Ryg, Ryl, Ry1;
  237. uint32_t i;
  238. for (i = 0; i < frames; i++) {
  239. Lyg = Ryg = 0.f;
  240. Lxg = (inputs[0][i]==0.f) ? -160.f : to_dB(fabs(inputs[0][i]));
  241. Rxg = (inputs[1][i]==0.f) ? -160.f : to_dB(fabs(inputs[1][i]));
  242. Lxg = sanitize_denormal(Lxg);
  243. Rxg = sanitize_denormal(Rxg);
  244. if (2.f*(Lxg-thresdb)<-width) {
  245. Lyg = Lxg;
  246. } else if (2.f*fabs(Lxg-thresdb)<=width) {
  247. Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width);
  248. } else if (2.f*(Lxg-thresdb)>width) {
  249. Lyg = thresdb + (Lxg-thresdb)/ratio;
  250. }
  251. Lyg = sanitize_denormal(Lyg);
  252. if (2.f*(Rxg-thresdb)<-width) {
  253. Ryg = Rxg;
  254. } else if (2.f*fabs(Rxg-thresdb)<=width) {
  255. Ryg = Rxg + (1.f/ratio-1.f)*(Rxg-thresdb+width/2.f)*(Rxg-thresdb+width/2.f)/(2.f*width);
  256. } else if (2.f*(Rxg-thresdb)>width) {
  257. Ryg = thresdb + (Rxg-thresdb)/ratio;
  258. }
  259. Ryg = sanitize_denormal(Ryg);
  260. if (stereo == STEREOLINK_UNCOUPLED) {
  261. Lxl = Lxg - Lyg;
  262. Rxl = Rxg - Ryg;
  263. } else if (stereo == STEREOLINK_MAX) {
  264. Lxl = Rxl = fmaxf(Lxg - Lyg, Rxg - Ryg);
  265. } else {
  266. Lxl = Rxl = (Lxg - Lyg + Rxg - Ryg) / 2.f;
  267. }
  268. oldL_y1 = sanitize_denormal(oldL_y1);
  269. oldR_y1 = sanitize_denormal(oldR_y1);
  270. oldL_yl = sanitize_denormal(oldL_yl);
  271. oldR_yl = sanitize_denormal(oldR_yl);
  272. Ly1 = fmaxf(Lxl, release_coeff * oldL_y1+(1.f-release_coeff)*Lxl);
  273. Lyl = attack_coeff * oldL_yl+(1.f-attack_coeff)*Ly1;
  274. Ly1 = sanitize_denormal(Ly1);
  275. Lyl = sanitize_denormal(Lyl);
  276. cdb = -Lyl;
  277. Lgain = from_dB(cdb);
  278. gainred = Lyl;
  279. Ry1 = fmaxf(Rxl, release_coeff * oldR_y1+(1.f-release_coeff)*Rxl);
  280. Ryl = attack_coeff * oldR_yl+(1.f-attack_coeff)*Ry1;
  281. Ry1 = sanitize_denormal(Ry1);
  282. Ryl = sanitize_denormal(Ryl);
  283. cdb = -Ryl;
  284. Rgain = from_dB(cdb);
  285. outputs[0][i] = inputs[0][i];
  286. outputs[0][i] *= Lgain * from_dB(makeup);
  287. outputs[1][i] = inputs[1][i];
  288. outputs[1][i] *= Rgain * from_dB(makeup);
  289. max = (fabsf(outputs[0][i]) > max) ? fabsf(outputs[0][i]) : sanitize_denormal(max);
  290. max = (fabsf(outputs[1][i]) > max) ? fabsf(outputs[1][i]) : sanitize_denormal(max);
  291. oldL_yl = Lyl;
  292. oldR_yl = Ryl;
  293. oldL_y1 = Ly1;
  294. oldR_y1 = Ry1;
  295. }
  296. outlevel = (max == 0.f) ? -45.f : to_dB(max);
  297. }
  298. // -----------------------------------------------------------------------
  299. Plugin* createPlugin()
  300. {
  301. return new ZamCompX2Plugin();
  302. }
  303. // -----------------------------------------------------------------------
  304. END_NAMESPACE_DISTRHO