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.

ZamEQ2UI.cpp 14KB

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