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.

382 lines
9.0KB

  1. // Reverb model implementation
  2. //
  3. // Written by Jezar at Dreampoint, June 2000
  4. // http://www.dreampoint.co.uk
  5. // This code is public domain
  6. #include "revmodel.hpp"
  7. #include <math.h>
  8. #include <string.h> // memset
  9. namespace rack_plugin_Bidoo {
  10. revmodel::revmodel()
  11. {
  12. // (note) still doesn't fix REI noise burst issue
  13. #define Dclearbuf(b) memset((void*)b, 0, sizeof(b))
  14. Dclearbuf(bufcombL1);
  15. Dclearbuf(bufcombR1);
  16. Dclearbuf(bufcombL2);
  17. Dclearbuf(bufcombR2);
  18. Dclearbuf(bufcombL3);
  19. Dclearbuf(bufcombR3);
  20. Dclearbuf(bufcombL4);
  21. Dclearbuf(bufcombR4);
  22. Dclearbuf(bufcombL5);
  23. Dclearbuf(bufcombR5);
  24. Dclearbuf(bufcombL6);
  25. Dclearbuf(bufcombR6);
  26. Dclearbuf(bufcombL7);
  27. Dclearbuf(bufcombR7);
  28. Dclearbuf(bufcombL8);
  29. Dclearbuf(bufcombR8);
  30. // Buffers for the allpasses
  31. Dclearbuf(bufallpassL1);
  32. Dclearbuf(bufallpassR1);
  33. Dclearbuf(bufallpassL2);
  34. Dclearbuf(bufallpassR2);
  35. Dclearbuf(bufallpassL3);
  36. Dclearbuf(bufallpassR3);
  37. Dclearbuf(bufallpassL4);
  38. Dclearbuf(bufallpassR4);
  39. #undef Dclearbuf
  40. // Tie the components to their buffers
  41. combL[0].setbuffer(bufcombL1,combtuningL1);
  42. combR[0].setbuffer(bufcombR1,combtuningR1);
  43. combL[1].setbuffer(bufcombL2,combtuningL2);
  44. combR[1].setbuffer(bufcombR2,combtuningR2);
  45. combL[2].setbuffer(bufcombL3,combtuningL3);
  46. combR[2].setbuffer(bufcombR3,combtuningR3);
  47. combL[3].setbuffer(bufcombL4,combtuningL4);
  48. combR[3].setbuffer(bufcombR4,combtuningR4);
  49. combL[4].setbuffer(bufcombL5,combtuningL5);
  50. combR[4].setbuffer(bufcombR5,combtuningR5);
  51. combL[5].setbuffer(bufcombL6,combtuningL6);
  52. combR[5].setbuffer(bufcombR6,combtuningR6);
  53. combL[6].setbuffer(bufcombL7,combtuningL7);
  54. combR[6].setbuffer(bufcombR7,combtuningR7);
  55. combL[7].setbuffer(bufcombL8,combtuningL8);
  56. combR[7].setbuffer(bufcombR8,combtuningR8);
  57. allpassL[0].setbuffer(bufallpassL1,allpasstuningL1);
  58. allpassR[0].setbuffer(bufallpassR1,allpasstuningR1);
  59. allpassL[1].setbuffer(bufallpassL2,allpasstuningL2);
  60. allpassR[1].setbuffer(bufallpassR2,allpasstuningR2);
  61. allpassL[2].setbuffer(bufallpassL3,allpasstuningL3);
  62. allpassR[2].setbuffer(bufallpassR3,allpasstuningR3);
  63. allpassL[3].setbuffer(bufallpassL4,allpasstuningL4);
  64. allpassR[3].setbuffer(bufallpassR4,allpasstuningR4);
  65. // Set default values
  66. allpassL[0].setfeedback(0.5f);
  67. allpassR[0].setfeedback(0.5f);
  68. allpassL[1].setfeedback(0.5f);
  69. allpassR[1].setfeedback(0.5f);
  70. allpassL[2].setfeedback(0.5f);
  71. allpassR[2].setfeedback(0.5f);
  72. allpassL[3].setfeedback(0.5f);
  73. allpassR[3].setfeedback(0.5f);
  74. setwet(initialwet);
  75. setroomsize(initialroom);
  76. setdry(initialdry);
  77. setdamp(initialdamp);
  78. setwidth(initialwidth);
  79. setmode(initialmode);
  80. // Buffer will be full of rubbish - so we MUST mute them
  81. mute();
  82. }
  83. void revmodel::mute()
  84. {
  85. if (getmode() >= freezemode)
  86. return;
  87. for (int i=0;i<numcombs;i++)
  88. {
  89. combL[i].mute();
  90. combR[i].mute();
  91. }
  92. for (int i=0;i<numallpasses;i++)
  93. {
  94. allpassL[i].mute();
  95. allpassR[i].mute();
  96. }
  97. }
  98. void revmodel::processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip)
  99. {
  100. float outL,outR,input;
  101. while(numsamples-- > 0)
  102. {
  103. outL = outR = 0;
  104. input = (*inputL + *inputR) * gain;
  105. // Accumulate comb filters in parallel
  106. for(int i=0; i<numcombs; i++)
  107. {
  108. outL += combL[i].process(input);
  109. outR += combR[i].process(input);
  110. }
  111. // Feed through allpasses in series
  112. for(int i=0; i<numallpasses; i++)
  113. {
  114. outL = allpassL[i].process(outL);
  115. outR = allpassR[i].process(outR);
  116. }
  117. // Calculate output REPLACING anything already there
  118. *outputL = outL*wet1 + outR*wet2 + *inputL*dry;
  119. *outputR = outR*wet1 + outL*wet2 + *inputR*dry;
  120. // Increment sample pointers, allowing for interleave (if any)
  121. inputL += skip;
  122. inputR += skip;
  123. outputL += skip;
  124. outputR += skip;
  125. }
  126. }
  127. void revmodel::processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip)
  128. {
  129. float outL,outR,input;
  130. while(numsamples-- > 0)
  131. {
  132. outL = outR = 0;
  133. input = (*inputL + *inputR) * gain;
  134. // Accumulate comb filters in parallel
  135. for(int i=0; i<numcombs; i++)
  136. {
  137. outL += combL[i].process(input);
  138. outR += combR[i].process(input);
  139. }
  140. // Feed through allpasses in series
  141. for(int i=0; i<numallpasses; i++)
  142. {
  143. outL = allpassL[i].process(outL);
  144. outR = allpassR[i].process(outR);
  145. }
  146. // Calculate output MIXING with anything already there
  147. *outputL += outL*wet1 + outR*wet2 + *inputL*dry;
  148. *outputR += outR*wet1 + outL*wet2 + *inputR*dry;
  149. // Increment sample pointers, allowing for interleave (if any)
  150. inputL += skip;
  151. inputR += skip;
  152. outputL += skip;
  153. outputR += skip;
  154. }
  155. }
  156. void revmodel::process(const float inL, const float inR, const float fbIn, float &outputL, float &outputR, float &wOutputL, float &wOutputR)
  157. {
  158. float outL = 0.0f, outR = 0.0f;
  159. float input = (inL + inR + fbIn) * gain;
  160. // Accumulate comb filters in parallel
  161. for(int i=0; i<numcombs; i++)
  162. {
  163. outL += combL[i].process(input);
  164. outR += combR[i].process(input);
  165. }
  166. // Feed through allpasses in series
  167. for(int i=0; i<numallpasses; i++)
  168. {
  169. outL = allpassL[i].process(outL);
  170. outR = allpassR[i].process(outR);
  171. }
  172. outputL = outL*wet1 + outR*wet2 + inL*dry;
  173. outputR = outR*wet1 + outL*wet2 + inR*dry;
  174. wOutputL = outL*wet1 + outR*wet2;
  175. wOutputR = outR*wet1 + outL*wet2;
  176. }
  177. void revmodel::update()
  178. {
  179. // Recalculate internal values after parameter change
  180. int i;
  181. wet1 = wet*(width/2 + 0.5f);
  182. wet2 = wet*((1-width)/2);
  183. if (mode >= freezemode)
  184. {
  185. roomsize1 = 1;
  186. damp1 = 0;
  187. gain = muted;
  188. }
  189. else
  190. {
  191. roomsize1 = roomsize;
  192. damp1 = damp;
  193. gain = fixedgain;
  194. }
  195. for(i=0; i<numcombs; i++)
  196. {
  197. combL[i].setfeedback(roomsize1);
  198. combR[i].setfeedback(roomsize1);
  199. }
  200. for(i=0; i<numcombs; i++)
  201. {
  202. combL[i].setdamp(damp1);
  203. combR[i].setdamp(damp1);
  204. }
  205. }
  206. // The following get/set functions are not inlined, because
  207. // speed is never an issue when calling them, and also
  208. // because as you develop the reverb model, you may
  209. // wish to take dynamic action when they are called.
  210. void revmodel::setroomsize(float value)
  211. {
  212. roomsize = (value*scaleroom) + offsetroom;
  213. update();
  214. }
  215. float revmodel::getroomsize()
  216. {
  217. return (roomsize-offsetroom)/scaleroom;
  218. }
  219. void revmodel::setdamp(float value)
  220. {
  221. damp = value * scaledamp;
  222. update();
  223. }
  224. float revmodel::getdamp()
  225. {
  226. return damp/scaledamp;
  227. }
  228. void revmodel::setwet(float value)
  229. {
  230. wet = value*scalewet;
  231. update();
  232. }
  233. float revmodel::getwet()
  234. {
  235. return wet/scalewet;
  236. }
  237. void revmodel::setdry(float value)
  238. {
  239. dry = value*scaledry;
  240. }
  241. float revmodel::getdry()
  242. {
  243. return dry/scaledry;
  244. }
  245. void revmodel::setwidth(float value)
  246. {
  247. width = value;
  248. update();
  249. }
  250. float revmodel::getwidth()
  251. {
  252. return width;
  253. }
  254. void revmodel::setmode(float value)
  255. {
  256. mode = value;
  257. update();
  258. }
  259. float revmodel::getmode()
  260. {
  261. if (mode >= freezemode)
  262. return 1;
  263. else
  264. return 0;
  265. }
  266. void revmodel::setsamplerate(const float samplerate) {
  267. sampleRate = samplerate;
  268. float coeff = sampleRate/44100.0;
  269. int mctL1 = round(coeff * combtuningL1);
  270. int mctR1 = round(coeff * combtuningR1);
  271. int mctL2 = round(coeff * combtuningL2);
  272. int mctR2 = round(coeff * combtuningR2);
  273. int mctL3 = round(coeff * combtuningL3);
  274. int mctR3 = round(coeff * combtuningR3);
  275. int mctL4 = round(coeff * combtuningL4);
  276. int mctR4 = round(coeff * combtuningR4);
  277. int mctL5 = round(coeff * combtuningL5);
  278. int mctR5 = round(coeff * combtuningR5);
  279. int mctL6 = round(coeff * combtuningL6);
  280. int mctR6 = round(coeff * combtuningR6);
  281. int mctL7 = round(coeff * combtuningL7);
  282. int mctR7 = round(coeff * combtuningR7);
  283. int mctL8 = round(coeff * combtuningL8);
  284. int mctR8 = round(coeff * combtuningR8);
  285. int maptL1 = round(coeff * allpasstuningL1);
  286. int maptR1 = round(coeff * allpasstuningR1);
  287. int maptL2 = round(coeff * allpasstuningL2);
  288. int maptR2 = round(coeff * allpasstuningR2);
  289. int maptL3 = round(coeff * allpasstuningL3);
  290. int maptR3 = round(coeff * allpasstuningR3);
  291. int maptL4 = round(coeff * allpasstuningL4);
  292. int maptR4 = round(coeff * allpasstuningR4);
  293. mute();
  294. combL[0].changebuffer(bufcombL1,mctL1);
  295. combR[0].changebuffer(bufcombR1,mctR1);
  296. combL[1].changebuffer(bufcombL2,mctL2);
  297. combR[1].changebuffer(bufcombR2,mctR2);
  298. combL[2].changebuffer(bufcombL3,mctL3);
  299. combR[2].changebuffer(bufcombR3,mctR3);
  300. combL[3].changebuffer(bufcombL4,mctL4);
  301. combR[3].changebuffer(bufcombR4,mctR4);
  302. combL[4].changebuffer(bufcombL5,mctL5);
  303. combR[4].changebuffer(bufcombR5,mctR5);
  304. combL[5].changebuffer(bufcombL6,mctL6);
  305. combR[5].changebuffer(bufcombR6,mctR6);
  306. combL[6].changebuffer(bufcombL7,mctL7);
  307. combR[6].changebuffer(bufcombR7,mctR7);
  308. combL[7].changebuffer(bufcombL8,mctL8);
  309. combR[7].changebuffer(bufcombR8,mctR8);
  310. allpassL[0].changebuffer(bufallpassL1,maptL1);
  311. allpassR[0].changebuffer(bufallpassR1,maptR1);
  312. allpassL[1].changebuffer(bufallpassL2,maptL2);
  313. allpassR[1].changebuffer(bufallpassR2,maptR2);
  314. allpassL[2].changebuffer(bufallpassL3,maptL3);
  315. allpassR[2].changebuffer(bufallpassR3,maptR3);
  316. allpassL[3].changebuffer(bufallpassL4,maptL4);
  317. allpassR[3].changebuffer(bufallpassR4,maptR4);
  318. setwet(initialwet);
  319. setroomsize(initialroom);
  320. setdry(initialdry);
  321. setdamp(initialdamp);
  322. setwidth(initialwidth);
  323. setmode(initialmode);
  324. }
  325. } // namespace rack_plugin_Bidoo
  326. //ends