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.

304 lines
7.8KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. EQ.cpp - EQ effect
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Author: Nasca Octavian Paul
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include <cmath>
  12. #include <rtosc/ports.h>
  13. #include <rtosc/port-sugar.h>
  14. #include "EQ.h"
  15. #include "../DSP/AnalogFilter.h"
  16. #include "../Misc/Allocator.h"
  17. namespace zyncarla {
  18. using rtosc::RtData;
  19. #define rObject EQ
  20. #define rBegin [](const char *msg, RtData &d) {\
  21. rObject *obj = (rObject*)d.obj;
  22. #define rEQ(offset) \
  23. int nfilt = atoi(msg-2); \
  24. int id = 10+nfilt*5+offset; \
  25. if(rtosc_narguments(msg)) \
  26. obj->changepar(id, rtosc_argument(msg,0).i);\
  27. else \
  28. d.reply(d.loc, "i", obj->getpar(id))
  29. #define rEnd }
  30. static rtosc::Ports filterports {
  31. {"Ptype::i", rProp(parameter) rOptions(Off, LP1, HP1, LP2,
  32. HP2, BP, notch, peak, l.shelf, h.shelf)
  33. rShort("type") rDoc("Filter Type"), 0,
  34. rBegin;
  35. rEQ(0);
  36. rEnd},
  37. {"Pfreq::i", rProp(parameter) rMap(min, 0) rMap(max, 127)
  38. rShort("freq"), 0,
  39. rBegin;
  40. rEQ(1);
  41. rEnd},
  42. {"Pgain::i", rProp(parameter) rMap(min, 0) rMap(max, 127)
  43. rShort("gain"), 0,
  44. rBegin;
  45. rEQ(2);
  46. rEnd},
  47. {"Pq::i", rProp(parameter) rMap(min, 0) rMap(max, 127)
  48. rShort("q") rDoc("Resonance/Bandwidth"), 0,
  49. rBegin;
  50. rEQ(3);
  51. rEnd},
  52. {"Pstages::i", rProp(parameter) rMap(min, 0) rMap(max, 4)
  53. rShort("stages") rDoc("Additional filter stages"), 0,
  54. rBegin;
  55. rEQ(4);
  56. rEnd},
  57. };
  58. rtosc::Ports EQ::ports = {
  59. {"filter#8/", 0, &filterports,
  60. rBegin;
  61. (void)obj;
  62. SNIP;
  63. filterports.dispatch(msg, d);
  64. rEnd},
  65. {"coeff:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL,
  66. [](const char *, rtosc::RtData &d)
  67. {
  68. EQ *eq = (EQ*)d.obj;
  69. float a[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
  70. float b[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
  71. memset(a, 0, sizeof(a));
  72. memset(b, 0, sizeof(b));
  73. eq->getFilter(a,b);
  74. char type[MAX_EQ_BANDS*MAX_FILTER_STAGES*3*2+1] = {};
  75. rtosc_arg_t val[MAX_EQ_BANDS*MAX_FILTER_STAGES*3*2] = {};
  76. for(int i=0; i<MAX_EQ_BANDS*MAX_FILTER_STAGES*3; ++i) {
  77. int stride = MAX_EQ_BANDS*MAX_FILTER_STAGES*3;
  78. type[i] = type[i+stride] = 'f';
  79. val[i].f = b[i];
  80. val[i+stride].f = a[i];
  81. }
  82. d.replyArray(d.loc, type, val);
  83. }},
  84. };
  85. #undef rObject
  86. #undef rBegin
  87. #undef rEnd
  88. EQ::EQ(EffectParams pars)
  89. :Effect(pars)
  90. {
  91. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  92. filter[i].Ptype = 0;
  93. filter[i].Pfreq = 64;
  94. filter[i].Pgain = 64;
  95. filter[i].Pq = 64;
  96. filter[i].Pstages = 0;
  97. filter[i].l = memory.alloc<AnalogFilter>(6, 1000.0f, 1.0f, 0, pars.srate, pars.bufsize);
  98. filter[i].r = memory.alloc<AnalogFilter>(6, 1000.0f, 1.0f, 0, pars.srate, pars.bufsize);
  99. }
  100. //default values
  101. Pvolume = 50;
  102. setpreset(Ppreset);
  103. cleanup();
  104. }
  105. EQ::~EQ()
  106. {
  107. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  108. memory.dealloc(filter[i].l);
  109. memory.dealloc(filter[i].r);
  110. }
  111. }
  112. // Cleanup the effect
  113. void EQ::cleanup(void)
  114. {
  115. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  116. filter[i].l->cleanup();
  117. filter[i].r->cleanup();
  118. }
  119. }
  120. //Effect output
  121. void EQ::out(const Stereo<float *> &smp)
  122. {
  123. for(int i = 0; i < buffersize; ++i) {
  124. efxoutl[i] = smp.l[i] * volume;
  125. efxoutr[i] = smp.r[i] * volume;
  126. }
  127. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  128. if(filter[i].Ptype == 0)
  129. continue;
  130. filter[i].l->filterout(efxoutl);
  131. filter[i].r->filterout(efxoutr);
  132. }
  133. }
  134. //Parameter control
  135. void EQ::setvolume(unsigned char _Pvolume)
  136. {
  137. Pvolume = _Pvolume;
  138. outvolume = powf(0.005f, (1.0f - Pvolume / 127.0f)) * 10.0f;
  139. volume = (!insertion) ? 1.0f : outvolume;
  140. }
  141. void EQ::setpreset(unsigned char npreset)
  142. {
  143. const int PRESET_SIZE = 1;
  144. const int NUM_PRESETS = 2;
  145. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  146. {67}, //EQ 1
  147. {67} //EQ 2
  148. };
  149. if(npreset >= NUM_PRESETS)
  150. npreset = NUM_PRESETS - 1;
  151. for(int n = 0; n < PRESET_SIZE; ++n)
  152. changepar(n, presets[npreset][n]);
  153. Ppreset = npreset;
  154. }
  155. void EQ::changepar(int npar, unsigned char value)
  156. {
  157. switch(npar) {
  158. case 0:
  159. setvolume(value);
  160. break;
  161. }
  162. if(npar < 10)
  163. return;
  164. int nb = (npar - 10) / 5; //number of the band (filter)
  165. if(nb >= MAX_EQ_BANDS)
  166. return;
  167. int bp = npar % 5; //band paramenter
  168. float tmp;
  169. switch(bp) {
  170. case 0:
  171. filter[nb].Ptype = value;
  172. if(value > 9)
  173. filter[nb].Ptype = 0; //has to be changed if more filters will be added
  174. if(filter[nb].Ptype != 0) {
  175. filter[nb].l->settype(value - 1);
  176. filter[nb].r->settype(value - 1);
  177. }
  178. break;
  179. case 1:
  180. filter[nb].Pfreq = value;
  181. tmp = 600.0f * powf(30.0f, (value - 64.0f) / 64.0f);
  182. filter[nb].l->setfreq(tmp);
  183. filter[nb].r->setfreq(tmp);
  184. break;
  185. case 2:
  186. filter[nb].Pgain = value;
  187. tmp = 30.0f * (value - 64.0f) / 64.0f;
  188. filter[nb].l->setgain(tmp);
  189. filter[nb].r->setgain(tmp);
  190. break;
  191. case 3:
  192. filter[nb].Pq = value;
  193. tmp = powf(30.0f, (value - 64.0f) / 64.0f);
  194. filter[nb].l->setq(tmp);
  195. filter[nb].r->setq(tmp);
  196. break;
  197. case 4:
  198. filter[nb].Pstages = value;
  199. if(value >= MAX_FILTER_STAGES)
  200. filter[nb].Pstages = MAX_FILTER_STAGES - 1;
  201. filter[nb].l->setstages(value);
  202. filter[nb].r->setstages(value);
  203. break;
  204. }
  205. }
  206. unsigned char EQ::getpar(int npar) const
  207. {
  208. switch(npar) {
  209. case 0:
  210. return Pvolume;
  211. break;
  212. }
  213. if(npar < 10)
  214. return 0;
  215. int nb = (npar - 10) / 5; //number of the band (filter)
  216. if(nb >= MAX_EQ_BANDS)
  217. return 0;
  218. int bp = npar % 5; //band paramenter
  219. switch(bp) {
  220. case 0:
  221. return filter[nb].Ptype;
  222. break;
  223. case 1:
  224. return filter[nb].Pfreq;
  225. break;
  226. case 2:
  227. return filter[nb].Pgain;
  228. break;
  229. case 3:
  230. return filter[nb].Pq;
  231. break;
  232. case 4:
  233. return filter[nb].Pstages;
  234. break;
  235. default: return 0; //in case of bogus parameter number
  236. }
  237. }
  238. float EQ::getfreqresponse(float freq)
  239. {
  240. float resp = 1.0f;
  241. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  242. if(filter[i].Ptype == 0)
  243. continue;
  244. resp *= filter[i].l->H(freq);
  245. }
  246. return rap2dB(resp * outvolume);
  247. }
  248. //Not exactly the most efficient manner to derive the total taps, but it should
  249. //be fast enough in practice
  250. void EQ::getFilter(float *a, float *b) const
  251. {
  252. a[0] = 1;
  253. b[0] = 1;
  254. off_t off=0;
  255. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  256. auto &F = filter[i];
  257. if(F.Ptype == 0)
  258. continue;
  259. const double Fb[3] = {F.l->coeff.c[0], F.l->coeff.c[1], F.l->coeff.c[2]};
  260. const double Fa[3] = {1.0f, -F.l->coeff.d[1], -F.l->coeff.d[2]};
  261. for(int j=0; j<F.Pstages+1; ++j) {
  262. for(int k=0; k<3; ++k) {
  263. a[off] = Fa[k];
  264. b[off] = Fb[k];
  265. off++;
  266. }
  267. }
  268. }
  269. }
  270. }