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.

469 lines
14KB

  1. /*
  2. * ZamEQ2 2 band parametric equaliser
  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 "ZamEQ2UI.hpp"
  18. using DGL::Point;
  19. START_NAMESPACE_DISTRHO
  20. // -----------------------------------------------------------------------
  21. ZamEQ2UI::ZamEQ2UI()
  22. : UI()
  23. {
  24. // background
  25. fImgBackground = Image(ZamEQ2Artwork::zameq2Data, ZamEQ2Artwork::zameq2Width, ZamEQ2Artwork::zameq2Height, GL_BGR);
  26. // toggle image
  27. Image sliderImage(ZamEQ2Artwork::togglesliderData, ZamEQ2Artwork::togglesliderWidth, ZamEQ2Artwork::togglesliderHeight);
  28. // knob
  29. Image knobImage(ZamEQ2Artwork::knobData, ZamEQ2Artwork::knobWidth, ZamEQ2Artwork::knobHeight);
  30. // knob
  31. fKnobGain1 = new ImageKnob(this, knobImage);
  32. fKnobGain1->setPos(91, 172);
  33. fKnobGain1->setRange(-50.f, 20.0f);
  34. fKnobGain1->setRotationAngle(240);
  35. //fKnobGain1->setDefault(0.0f);
  36. fKnobGain1->setCallback(this);
  37. fKnobQ1 = new ImageKnob(this, knobImage);
  38. fKnobQ1->setPos(91, 122);
  39. fKnobQ1->setRange(0.1f, 6.0f);
  40. //fKnobQ1->setLogScale(true);
  41. fKnobQ1->setRotationAngle(240);
  42. //fKnobQ1->setDefault(1.0f);
  43. fKnobQ1->setCallback(this);
  44. fKnobFreq1 = new ImageKnob(this, knobImage);
  45. fKnobFreq1->setPos(23, 144);
  46. fKnobFreq1->setRange(20.f, 14000.0f);
  47. //fKnobFreq1->setLogScale(true);
  48. fKnobFreq1->setRotationAngle(240);
  49. //fKnobFreq1->setDefault(500.0f);
  50. fKnobFreq1->setCallback(this);
  51. fKnobGain2 = new ImageKnob(this, knobImage);
  52. fKnobGain2->setPos(567, 172);
  53. fKnobGain2->setRange(-50.f, 20.0f);
  54. fKnobGain2->setRotationAngle(240);
  55. //fKnobGain2->setDefault(0.0f);
  56. fKnobGain2->setCallback(this);
  57. fKnobQ2 = new ImageKnob(this, knobImage);
  58. fKnobQ2->setPos(567, 122);
  59. fKnobQ2->setRange(0.1f, 6.0f);
  60. //fKnobQ2->setLogScale(true);
  61. fKnobQ2->setRotationAngle(240);
  62. //fKnobQ2->setDefault(1.0f);
  63. fKnobQ2->setCallback(this);
  64. fKnobFreq2 = new ImageKnob(this, knobImage);
  65. fKnobFreq2->setPos(499, 144);
  66. fKnobFreq2->setRange(20.f, 14000.0f);
  67. //fKnobFreq2->setLogScale(true);
  68. fKnobFreq2->setRotationAngle(240);
  69. //fKnobFreq2->setDefault(3000.0f);
  70. fKnobFreq2->setCallback(this);
  71. fKnobGainL = new ImageKnob(this, knobImage);
  72. fKnobGainL->setPos(91, 52);
  73. fKnobGainL->setRange(-50.f, 20.0f);
  74. fKnobGainL->setRotationAngle(240);
  75. //fKnobGainL->setDefault(0.0f);
  76. fKnobGainL->setCallback(this);
  77. fKnobFreqL = new ImageKnob(this, knobImage);
  78. fKnobFreqL->setPos(23, 23);
  79. fKnobFreqL->setRange(20.f, 14000.0f);
  80. //fKnobFreqL->setLogScale(true);
  81. fKnobFreqL->setRotationAngle(240);
  82. //fKnobFreqL->setDefault(250.0f);
  83. fKnobFreqL->setCallback(this);
  84. fKnobGainH = new ImageKnob(this, knobImage);
  85. fKnobGainH->setPos(567, 53);
  86. fKnobGainH->setRange(-50.f, 20.0f);
  87. fKnobGainH->setRotationAngle(240);
  88. //fKnobGainH->setDefault(0.0f);
  89. fKnobGainH->setCallback(this);
  90. fKnobFreqH = new ImageKnob(this, knobImage);
  91. fKnobFreqH->setPos(499, 24);
  92. fKnobFreqH->setRange(20.f, 14000.0f);
  93. //fKnobFreqH->setLogScale(true);
  94. fKnobFreqH->setRotationAngle(240);
  95. //fKnobFreqH->setDefault(8000.0f);
  96. fKnobFreqH->setCallback(this);
  97. Point<int> masterPosStart(211,204);
  98. Point<int> masterPosEnd(288,204);
  99. fSliderMaster = new ImageSlider(this, sliderImage);
  100. fSliderMaster->setStartPos(masterPosStart);
  101. fSliderMaster->setEndPos(masterPosEnd);
  102. fSliderMaster->setRange(-12.f,12.f);
  103. fSliderMaster->setValue(0.f);
  104. fSliderMaster->setStep(6.f);
  105. fSliderMaster->setCallback(this);
  106. fCanvasArea.setPos(165,10);
  107. fCanvasArea.setSize(305,180);
  108. }
  109. ZamEQ2UI::~ZamEQ2UI()
  110. {
  111. delete fKnobGain1;
  112. delete fKnobQ1;
  113. delete fKnobFreq1;
  114. delete fKnobGain2;
  115. delete fKnobQ2;
  116. delete fKnobFreq2;
  117. delete fKnobGainL;
  118. delete fKnobFreqL;
  119. delete fKnobGainH;
  120. delete fKnobFreqH;
  121. delete fSliderMaster;
  122. }
  123. // -----------------------------------------------------------------------
  124. // DSP Callbacks
  125. void ZamEQ2UI::d_parameterChanged(uint32_t index, float value)
  126. {
  127. switch (index)
  128. {
  129. case ZamEQ2Plugin::paramGain1:
  130. fKnobGain1->setValue(value);
  131. break;
  132. case ZamEQ2Plugin::paramQ1:
  133. fKnobQ1->setValue(value);
  134. break;
  135. case ZamEQ2Plugin::paramFreq1:
  136. fKnobFreq1->setValue(value);
  137. break;
  138. case ZamEQ2Plugin::paramGain2:
  139. fKnobGain2->setValue(value);
  140. break;
  141. case ZamEQ2Plugin::paramQ2:
  142. fKnobQ2->setValue(value);
  143. break;
  144. case ZamEQ2Plugin::paramFreq2:
  145. fKnobFreq2->setValue(value);
  146. break;
  147. case ZamEQ2Plugin::paramGainL:
  148. fKnobGainL->setValue(value);
  149. break;
  150. case ZamEQ2Plugin::paramFreqL:
  151. fKnobFreqL->setValue(value);
  152. break;
  153. case ZamEQ2Plugin::paramGainH:
  154. fKnobGainH->setValue(value);
  155. break;
  156. case ZamEQ2Plugin::paramFreqH:
  157. fKnobFreqH->setValue(value);
  158. break;
  159. case ZamEQ2Plugin::paramMaster:
  160. fSliderMaster->setValue(value);
  161. break;
  162. }
  163. }
  164. void ZamEQ2UI::d_programChanged(uint32_t index)
  165. {
  166. if (index != 0)
  167. return;
  168. // Default values
  169. /*
  170. fKnobGain1->resetDefault();
  171. fKnobQ1->resetDefault();
  172. fKnobFreq1->resetDefault();
  173. fKnobGain2->resetDefault();
  174. fKnobQ2->resetDefault();
  175. fKnobFreq2->resetDefault();
  176. fKnobGainL->resetDefault();
  177. fKnobFreqL->resetDefault();
  178. fKnobGainH->resetDefault();
  179. fKnobFreqH->resetDefault();
  180. */
  181. fSliderMaster->setValue(0.f);
  182. }
  183. // -----------------------------------------------------------------------
  184. // Widget Callbacks
  185. void ZamEQ2UI::imageKnobDragStarted(ImageKnob* knob)
  186. {
  187. if (knob == fKnobGain1)
  188. d_editParameter(ZamEQ2Plugin::paramGain1, true);
  189. else if (knob == fKnobQ1)
  190. d_editParameter(ZamEQ2Plugin::paramQ1, true);
  191. else if (knob == fKnobFreq1)
  192. d_editParameter(ZamEQ2Plugin::paramFreq1, true);
  193. else if (knob == fKnobGain2)
  194. d_editParameter(ZamEQ2Plugin::paramGain2, true);
  195. else if (knob == fKnobQ2)
  196. d_editParameter(ZamEQ2Plugin::paramQ2, true);
  197. else if (knob == fKnobFreq2)
  198. d_editParameter(ZamEQ2Plugin::paramFreq2, true);
  199. else if (knob == fKnobGainL)
  200. d_editParameter(ZamEQ2Plugin::paramGainL, true);
  201. else if (knob == fKnobFreqL)
  202. d_editParameter(ZamEQ2Plugin::paramFreqL, true);
  203. else if (knob == fKnobGainH)
  204. d_editParameter(ZamEQ2Plugin::paramGainH, true);
  205. else if (knob == fKnobFreqH)
  206. d_editParameter(ZamEQ2Plugin::paramFreqH, true);
  207. }
  208. void ZamEQ2UI::imageKnobDragFinished(ImageKnob* knob)
  209. {
  210. if (knob == fKnobGain1)
  211. d_editParameter(ZamEQ2Plugin::paramGain1, false);
  212. else if (knob == fKnobQ1)
  213. d_editParameter(ZamEQ2Plugin::paramQ1, false);
  214. else if (knob == fKnobFreq1)
  215. d_editParameter(ZamEQ2Plugin::paramFreq1, false);
  216. else if (knob == fKnobGain2)
  217. d_editParameter(ZamEQ2Plugin::paramGain2, false);
  218. else if (knob == fKnobQ2)
  219. d_editParameter(ZamEQ2Plugin::paramQ2, false);
  220. else if (knob == fKnobFreq2)
  221. d_editParameter(ZamEQ2Plugin::paramFreq2, false);
  222. else if (knob == fKnobGainL)
  223. d_editParameter(ZamEQ2Plugin::paramGainL, false);
  224. else if (knob == fKnobFreqL)
  225. d_editParameter(ZamEQ2Plugin::paramFreqL, false);
  226. else if (knob == fKnobGainH)
  227. d_editParameter(ZamEQ2Plugin::paramGainH, false);
  228. else if (knob == fKnobFreqH)
  229. d_editParameter(ZamEQ2Plugin::paramFreqH, false);
  230. }
  231. void ZamEQ2UI::imageKnobValueChanged(ImageKnob* knob, float value)
  232. {
  233. if (knob == fKnobGain1)
  234. d_setParameterValue(ZamEQ2Plugin::paramGain1, value);
  235. else if (knob == fKnobQ1)
  236. d_setParameterValue(ZamEQ2Plugin::paramQ1, value);
  237. else if (knob == fKnobFreq1)
  238. d_setParameterValue(ZamEQ2Plugin::paramFreq1, value);
  239. else if (knob == fKnobGain2)
  240. d_setParameterValue(ZamEQ2Plugin::paramGain2, value);
  241. else if (knob == fKnobQ2)
  242. d_setParameterValue(ZamEQ2Plugin::paramQ2, value);
  243. else if (knob == fKnobFreq2)
  244. d_setParameterValue(ZamEQ2Plugin::paramFreq2, value);
  245. else if (knob == fKnobGainL)
  246. d_setParameterValue(ZamEQ2Plugin::paramGainL, value);
  247. else if (knob == fKnobFreqL)
  248. d_setParameterValue(ZamEQ2Plugin::paramFreqL, value);
  249. else if (knob == fKnobGainH)
  250. d_setParameterValue(ZamEQ2Plugin::paramGainH, value);
  251. else if (knob == fKnobFreqH)
  252. d_setParameterValue(ZamEQ2Plugin::paramFreqH, value);
  253. }
  254. void ZamEQ2UI::imageSliderDragStarted(ImageSlider* slider)
  255. {
  256. if (slider == fSliderMaster)
  257. d_editParameter(ZamEQ2Plugin::paramMaster, true);
  258. }
  259. void ZamEQ2UI::imageSliderDragFinished(ImageSlider* slider)
  260. {
  261. if (slider == fSliderMaster)
  262. d_editParameter(ZamEQ2Plugin::paramMaster, false);
  263. }
  264. void ZamEQ2UI::imageSliderValueChanged(ImageSlider* slider, float value)
  265. {
  266. if (slider == fSliderMaster)
  267. d_setParameterValue(ZamEQ2Plugin::paramMaster, value);
  268. }
  269. void ZamEQ2UI::lowshelf(int i, int ch, float srate, float fc, float g)
  270. {
  271. float k, v0;
  272. k = tanf(M_PI * fc / srate);
  273. v0 = powf(10., g / 20.);
  274. if (g < 0.f) {
  275. // LF cut
  276. float denom = v0 + sqrt(2. * v0)*k + k*k;
  277. b0[ch][i] = v0 * (1. + sqrt(2.)*k + k*k) / denom;
  278. b1[ch][i] = 2. * v0*(k*k - 1.) / denom;
  279. b2[ch][i] = v0 * (1. - sqrt(2.)*k + k*k) / denom;
  280. a1[ch][i] = 2. * (k*k - v0) / denom;
  281. a2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom;
  282. } else {
  283. // LF boost
  284. float denom = 1. + sqrt(2.)*k + k*k;
  285. b0[ch][i] = (1. + sqrt(2. * v0)*k + v0*k*k) / denom;
  286. b1[ch][i] = 2. * (v0*k*k - 1.) / denom;
  287. b2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom;
  288. a1[ch][i] = 2. * (k*k - 1.) / denom;
  289. a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom;
  290. }
  291. }
  292. void ZamEQ2UI::highshelf(int i, int ch, float srate, float fc, float g)
  293. {
  294. float k, v0;
  295. k = tanf(M_PI * fc / srate);
  296. v0 = powf(10., g / 20.);
  297. if (g < 0.f) {
  298. // HF cut
  299. float denom = 1. + sqrt(2. * v0)*k + v0*k*k;
  300. b0[ch][i] = v0*(1. + sqrt(2.)*k + k*k) / denom;
  301. b1[ch][i] = 2. * v0*(k*k - 1.) / denom;
  302. b2[ch][i] = v0*(1. - sqrt(2.)*k + k*k) / denom;
  303. a1[ch][i] = 2. * (v0*k*k - 1.) / denom;
  304. a2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom;
  305. } else {
  306. // HF boost
  307. float denom = 1. + sqrt(2.)*k + k*k;
  308. b0[ch][i] = (v0 + sqrt(2. * v0)*k + k*k) / denom;
  309. b1[ch][i] = 2. * (k*k - v0) / denom;
  310. b2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom;
  311. a1[ch][i] = 2. * (k*k - 1.) / denom;
  312. a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom;
  313. }
  314. }
  315. void ZamEQ2UI::peq(int i, int ch, float srate, float fc, float g, float bw)
  316. {
  317. float k, v0, q;
  318. k = tanf(M_PI * fc / srate);
  319. v0 = powf(10., g / 20.);
  320. q = powf(2., 1./bw)/(powf(2., bw) - 1.); //q from octave bw
  321. if (g < 0.f) {
  322. // cut
  323. float denom = 1. + k/(v0*q) + k*k;
  324. b0[ch][i] = (1. + k/q + k*k) / denom;
  325. b1[ch][i] = 2. * (k*k - 1.) / denom;
  326. b2[ch][i] = (1. - k/q + k*k) / denom;
  327. a1[ch][i] = b1[ch][i];
  328. a2[ch][i] = (1. - k/(v0*q) + k*k) / denom;
  329. } else {
  330. // boost
  331. float denom = 1. + k/q + k*k;
  332. b0[ch][i] = (1. + k*v0/q + k*k) / denom;
  333. b1[ch][i] = 2. * (k*k - 1.) / denom;
  334. b2[ch][i] = (1. - k*v0/q + k*k) / denom;
  335. a1[ch][i] = b1[ch][i];
  336. a2[ch][i] = (1. - k/q + k*k) / denom;
  337. }
  338. }
  339. void ZamEQ2UI::calceqcurve(float x[], float y[])
  340. {
  341. float SR = d_getSampleRate();
  342. float p1 = 10000.;
  343. float p2 = 5000.;
  344. float c2 = log10(1.+SR);
  345. float c1 = (1.+p1/SR)/(EQPOINTS*(p2/SR)*(p2/SR));
  346. double bw1 = fKnobQ1->getValue();
  347. double boost1 = fKnobGain1->getValue();
  348. double freq1 = fKnobFreq1->getValue();
  349. double bw2 = fKnobQ2->getValue();
  350. double boost2 = fKnobGain2->getValue();
  351. double freq2 = fKnobFreq2->getValue();
  352. double boostl = fKnobGainL->getValue();
  353. double freql = fKnobFreqL->getValue();
  354. double boosth = fKnobGainH->getValue();
  355. double freqh = fKnobFreqH->getValue();
  356. for (uint32_t i = 0; i < EQPOINTS; ++i) {
  357. x[i] = 1.5*log10(1.+i+c1)/c2;
  358. std::complex<double> H;
  359. double theta = -(i+0.005)*M_PI/EQPOINTS*20./(SR/1000.);
  360. std::complex<double> expiw = std::polar(1.0, theta);
  361. std::complex<double> exp2iw = std::polar(1.0, 2.0*theta);
  362. double freqH; //phaseH;
  363. lowshelf(0, 0, SR, freql, boostl);
  364. peq(1, 0, SR, freq1, boost1, bw1);
  365. peq(2, 0, SR, freq2, boost2, bw2);
  366. highshelf(3, 0, SR, freqh, boosth);
  367. H = (1. + a1[0][0]*expiw + a2[0][0]*exp2iw)/(b0[0][0] + b1[0][0]*expiw + b2[0][0]*exp2iw);
  368. H += (1. + a1[0][1]*expiw + a2[0][1]*exp2iw)/(b0[0][1] + b1[0][1]*expiw + b2[0][1]*exp2iw);
  369. H += (1. + a1[0][2]*expiw + a2[0][2]*exp2iw)/(b0[0][2] + b1[0][2]*expiw + b2[0][2]*exp2iw);
  370. H += (1. + a1[0][3]*expiw + a2[0][3]*exp2iw)/(b0[0][3] + b1[0][3]*expiw + b2[0][3]*exp2iw);
  371. freqH = std::abs(H);
  372. y[i] = (to_dB(freqH/4.)/5.)-(fSliderMaster->getValue())/24.f+0.5;
  373. x[i] = fCanvasArea.getX() + x[i]*fCanvasArea.getWidth();
  374. y[i] = fCanvasArea.getY() + y[i]*fCanvasArea.getHeight();
  375. }
  376. }
  377. void ZamEQ2UI::onDisplay()
  378. {
  379. fImgBackground.draw();
  380. calceqcurve(eqx, eqy);
  381. glEnable(GL_BLEND);
  382. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  383. glEnable(GL_LINE_SMOOTH);
  384. glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  385. glLineWidth(2);
  386. int i;
  387. glColor4f(1.f, 1.f, 0.235f, 1.0f);
  388. for (i = 1; i < EQPOINTS; ++i) {
  389. glBegin(GL_LINES);
  390. if (eqy[i-1] < fCanvasArea.getY() + fCanvasArea.getHeight()
  391. && eqy[i] < fCanvasArea.getY() + fCanvasArea.getHeight()
  392. && eqy[i-1] > fCanvasArea.getY()
  393. && eqy[i] > fCanvasArea.getY()) {
  394. glVertex2i(eqx[i-1], eqy[i-1]);
  395. glVertex2i(eqx[i], eqy[i]);
  396. }
  397. glEnd();
  398. }
  399. // reset color
  400. glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  401. }
  402. // -----------------------------------------------------------------------
  403. UI* createUI()
  404. {
  405. return new ZamEQ2UI();
  406. }
  407. // -----------------------------------------------------------------------
  408. END_NAMESPACE_DISTRHO