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.

222 lines
5.5KB

  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 "EQ.h"
  13. #include "../DSP/AnalogFilter.h"
  14. #include "../Misc/Allocator.h"
  15. EQ::EQ(EffectParams pars)
  16. :Effect(pars)
  17. {
  18. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  19. filter[i].Ptype = 0;
  20. filter[i].Pfreq = 64;
  21. filter[i].Pgain = 64;
  22. filter[i].Pq = 64;
  23. filter[i].Pstages = 0;
  24. filter[i].l = memory.alloc<AnalogFilter>(6, 1000.0f, 1.0f, 0, pars.srate, pars.bufsize);
  25. filter[i].r = memory.alloc<AnalogFilter>(6, 1000.0f, 1.0f, 0, pars.srate, pars.bufsize);
  26. }
  27. //default values
  28. Pvolume = 50;
  29. setpreset(Ppreset);
  30. cleanup();
  31. }
  32. EQ::~EQ()
  33. {
  34. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  35. memory.dealloc(filter[i].l);
  36. memory.dealloc(filter[i].r);
  37. }
  38. }
  39. // Cleanup the effect
  40. void EQ::cleanup(void)
  41. {
  42. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  43. filter[i].l->cleanup();
  44. filter[i].r->cleanup();
  45. }
  46. }
  47. //Effect output
  48. void EQ::out(const Stereo<float *> &smp)
  49. {
  50. for(int i = 0; i < buffersize; ++i) {
  51. efxoutl[i] = smp.l[i] * volume;
  52. efxoutr[i] = smp.r[i] * volume;
  53. }
  54. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  55. if(filter[i].Ptype == 0)
  56. continue;
  57. filter[i].l->filterout(efxoutl);
  58. filter[i].r->filterout(efxoutr);
  59. }
  60. }
  61. //Parameter control
  62. void EQ::setvolume(unsigned char _Pvolume)
  63. {
  64. Pvolume = _Pvolume;
  65. outvolume = powf(0.005f, (1.0f - Pvolume / 127.0f)) * 10.0f;
  66. volume = (!insertion) ? 1.0f : outvolume;
  67. }
  68. void EQ::setpreset(unsigned char npreset)
  69. {
  70. const int PRESET_SIZE = 1;
  71. const int NUM_PRESETS = 2;
  72. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  73. {67}, //EQ 1
  74. {67} //EQ 2
  75. };
  76. if(npreset >= NUM_PRESETS)
  77. npreset = NUM_PRESETS - 1;
  78. for(int n = 0; n < PRESET_SIZE; ++n)
  79. changepar(n, presets[npreset][n]);
  80. Ppreset = npreset;
  81. }
  82. void EQ::changepar(int npar, unsigned char value)
  83. {
  84. switch(npar) {
  85. case 0:
  86. setvolume(value);
  87. break;
  88. }
  89. if(npar < 10)
  90. return;
  91. int nb = (npar - 10) / 5; //number of the band (filter)
  92. if(nb >= MAX_EQ_BANDS)
  93. return;
  94. int bp = npar % 5; //band paramenter
  95. float tmp;
  96. switch(bp) {
  97. case 0:
  98. filter[nb].Ptype = value;
  99. if(value > 9)
  100. filter[nb].Ptype = 0; //has to be changed if more filters will be added
  101. if(filter[nb].Ptype != 0) {
  102. filter[nb].l->settype(value - 1);
  103. filter[nb].r->settype(value - 1);
  104. }
  105. break;
  106. case 1:
  107. filter[nb].Pfreq = value;
  108. tmp = 600.0f * powf(30.0f, (value - 64.0f) / 64.0f);
  109. filter[nb].l->setfreq(tmp);
  110. filter[nb].r->setfreq(tmp);
  111. break;
  112. case 2:
  113. filter[nb].Pgain = value;
  114. tmp = 30.0f * (value - 64.0f) / 64.0f;
  115. filter[nb].l->setgain(tmp);
  116. filter[nb].r->setgain(tmp);
  117. break;
  118. case 3:
  119. filter[nb].Pq = value;
  120. tmp = powf(30.0f, (value - 64.0f) / 64.0f);
  121. filter[nb].l->setq(tmp);
  122. filter[nb].r->setq(tmp);
  123. break;
  124. case 4:
  125. filter[nb].Pstages = value;
  126. if(value >= MAX_FILTER_STAGES)
  127. filter[nb].Pstages = MAX_FILTER_STAGES - 1;
  128. filter[nb].l->setstages(value);
  129. filter[nb].r->setstages(value);
  130. break;
  131. }
  132. }
  133. unsigned char EQ::getpar(int npar) const
  134. {
  135. switch(npar) {
  136. case 0:
  137. return Pvolume;
  138. break;
  139. }
  140. if(npar < 10)
  141. return 0;
  142. int nb = (npar - 10) / 5; //number of the band (filter)
  143. if(nb >= MAX_EQ_BANDS)
  144. return 0;
  145. int bp = npar % 5; //band paramenter
  146. switch(bp) {
  147. case 0:
  148. return filter[nb].Ptype;
  149. break;
  150. case 1:
  151. return filter[nb].Pfreq;
  152. break;
  153. case 2:
  154. return filter[nb].Pgain;
  155. break;
  156. case 3:
  157. return filter[nb].Pq;
  158. break;
  159. case 4:
  160. return filter[nb].Pstages;
  161. break;
  162. default: return 0; //in case of bogus parameter number
  163. }
  164. }
  165. float EQ::getfreqresponse(float freq)
  166. {
  167. float resp = 1.0f;
  168. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  169. if(filter[i].Ptype == 0)
  170. continue;
  171. resp *= filter[i].l->H(freq);
  172. }
  173. return rap2dB(resp * outvolume);
  174. }
  175. //Not exactly the most efficient manner to derive the total taps, but it should
  176. //be fast enough in practice
  177. void EQ::getFilter(float *a, float *b) const
  178. {
  179. a[0] = 1;
  180. b[0] = 1;
  181. off_t off=0;
  182. for(int i = 0; i < MAX_EQ_BANDS; ++i) {
  183. auto &F = filter[i];
  184. if(F.Ptype == 0)
  185. continue;
  186. const double Fb[3] = {F.l->coeff.c[0], F.l->coeff.c[1], F.l->coeff.c[2]};
  187. const double Fa[3] = {1.0f, -F.l->coeff.d[1], -F.l->coeff.d[2]};
  188. for(int j=0; j<F.Pstages+1; ++j) {
  189. for(int k=0; k<3; ++k) {
  190. a[off] = Fa[k];
  191. b[off] = Fb[k];
  192. off++;
  193. }
  194. }
  195. }
  196. }