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.

230 lines
6.4KB

  1. #include "Southpole.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_Southpole {
  4. #define NBUF 6
  5. struct Rakes : Module {
  6. enum ParamIds {
  7. DECAY_PARAM,
  8. QUANT_PARAM,
  9. MIX_PARAM,
  10. TUNE1_PARAM,
  11. TUNE2_PARAM,
  12. TUNE3_PARAM,
  13. TUNE4_PARAM,
  14. TUNE5_PARAM,
  15. TUNE6_PARAM,
  16. FINE1_PARAM,
  17. FINE2_PARAM,
  18. FINE3_PARAM,
  19. FINE4_PARAM,
  20. FINE5_PARAM,
  21. FINE6_PARAM,
  22. GAIN1_PARAM,
  23. GAIN2_PARAM,
  24. GAIN3_PARAM,
  25. GAIN4_PARAM,
  26. GAIN5_PARAM,
  27. GAIN6_PARAM,
  28. NUM_PARAMS
  29. };
  30. enum InputIds {
  31. INL_INPUT,
  32. INR_INPUT,
  33. DECAY_INPUT,
  34. MIX_INPUT,
  35. TUNE1_INPUT,
  36. TUNE2_INPUT,
  37. TUNE3_INPUT,
  38. TUNE4_INPUT,
  39. TUNE5_INPUT,
  40. TUNE6_INPUT,
  41. //GAIN1_INPUT,GAIN2_INPUT,
  42. //GAIN3_INPUT,GAIN4_INPUT,
  43. //GAIN5_INPUT,GAIN6_INPUT,
  44. NUM_INPUTS
  45. };
  46. enum OutputIds {
  47. OUTL_OUTPUT,
  48. OUTR_OUTPUT,
  49. NUM_OUTPUTS
  50. };
  51. enum LightIds {
  52. NUM_LIGHTS
  53. };
  54. //SchmittTrigger clock;
  55. float *bufl[NBUF];
  56. float *bufr[NBUF];
  57. int maxsize;
  58. int headl[NBUF];
  59. int headr[NBUF];
  60. int sizel[NBUF];
  61. int sizer[NBUF];
  62. int lastsizel[NBUF];
  63. int lastsizer[NBUF];
  64. Rakes() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  65. maxsize = engineGetSampleRate();
  66. for (int j=0; j < NBUF; j++) {
  67. bufl[j] = new float [maxsize];
  68. bufr[j] = new float [maxsize];
  69. for (int i=0; i < maxsize; i++) {
  70. bufl[j][i] = 0;
  71. bufr[j][i] = 0;
  72. }
  73. headl[j] = 0;
  74. headr[j] = 0;
  75. }
  76. }
  77. float xm1 = 0;
  78. float ym1 = 0;
  79. float dcblock( float x ) {
  80. float y = x - xm1 + 0.995 * ym1;
  81. xm1 = x;
  82. ym1 = y;
  83. return y;
  84. }
  85. void step() override;
  86. };
  87. void Rakes::step() {
  88. //float mix = clamp(params[MIX_PARAM].value + inputs[MIX_INPUT].normalize(0.) / 10.0, 0.0, 1.0);
  89. float mix = params[MIX_PARAM].value;
  90. float rate = clamp(params[DECAY_PARAM].value + inputs[DECAY_INPUT].normalize(0.) / 10.0, 0.0f, .99f);
  91. const float f0 = 261.626;
  92. float inl = inputs[INL_INPUT].normalize(0.);
  93. float inr = inputs[INR_INPUT].normalize(inl);
  94. float sumoutl = 0;
  95. float sumoutr = 0;
  96. float sumgain = 1.;
  97. for (int j=0; j < NBUF; j++) {
  98. //float gain = clamp(params[GAIN1_PARAM + j].value + inputs[GAIN1_INPUT + j].normalize(0.) / 10.0, 0.0, 1.0);
  99. float gain = params[GAIN1_PARAM + j].value;
  100. if (gain < 1e-3) continue;
  101. sumgain += gain;
  102. float tune = clamp(params[TUNE1_PARAM + j].value + inputs[TUNE1_INPUT + j].normalize(0.), -5.0, 5.5);
  103. float fine = clamp(params[FINE1_PARAM + j].value, -1.0, 1.0);
  104. if ( params[QUANT_PARAM].value > 0.5 ) {
  105. tune = round(12.*tune)/12.;
  106. }
  107. float freql = f0 * powf(2., tune + fine/12.);
  108. float freqr = f0 * powf(2., tune - fine/12.);
  109. // key follow
  110. //float fb = crossfade(f0, freq, follow);
  111. // full follow decay rate is T60 time
  112. float fbl = pow(10, -3./freql/fabs(5.*rate));
  113. float fbr = pow(10, -3./freqr/fabs(5.*rate));
  114. //fb = fb * ((0. < rate) - (rate < 0.));
  115. //printf("%f %f %f\n",lfreq,rate,fb);
  116. sizel[j] = maxsize / freqr;
  117. sizer[j] = maxsize / freql;
  118. if (sizel[j] > lastsizel[j]) {
  119. for (int i=sizel[j]; i < lastsizel[j]; i++ ) bufl[i]=0;
  120. }
  121. if (sizel[j] > lastsizer[j]) {
  122. for (int i=sizer[j]; i < lastsizer[j]; i++ ) bufr[i]=0;
  123. }
  124. lastsizel[j] = maxsize / freqr;
  125. lastsizer[j] = maxsize / freql;
  126. float outl = bufl[j][headl[j]];
  127. float outr = bufr[j][headr[j]];
  128. bufl[j][headl[j]] = inl + fbl * outl;
  129. bufr[j][headr[j]] = inr + fbr * outr;
  130. headl[j]++;
  131. headr[j]++;
  132. if (headl[j] > sizel[j]) { headl[j] = 0; }
  133. if (headr[j] > sizer[j]) { headr[j] = 0; }
  134. sumoutl += gain*outl;
  135. sumoutr += gain*outr;
  136. }
  137. sumoutl = clamp( dcblock(sumoutl) / sumgain, -10., 10.); //in + gain*out;
  138. sumoutr = clamp( dcblock(sumoutr) / sumgain, -10., 10.); //in + gain*out;
  139. outputs[OUTL_OUTPUT].value = crossfade(inl,sumoutl,mix);
  140. outputs[OUTR_OUTPUT].value = crossfade(inr,sumoutr,mix);
  141. }
  142. struct RakesWidget : ModuleWidget {
  143. RakesWidget(Rakes *module) : ModuleWidget(module) {
  144. box.size = Vec(15*8, 380);
  145. {
  146. SVGPanel *panel = new SVGPanel();
  147. panel->box.size = box.size;
  148. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Rakes.svg")));
  149. addChild(panel);
  150. }
  151. const float x1 = 5.;
  152. const float x2 = 35.;
  153. const float x3 = 65.;
  154. const float x4 = 95.;
  155. const float y1 = 40.;
  156. const float yh = 32.;
  157. addInput(Port::create<sp_Port>(Vec(x2, y1+0*yh), Port::INPUT, module, Rakes::DECAY_INPUT));
  158. addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x3, y1+0*yh), module, Rakes::DECAY_PARAM, 0.0, 1.0, 0.0));
  159. //addParam(ParamWidget::create<sp_SmallBlackKnob> (Vec(x3, y1+0*yh), module, Rakes::FOLLOW_PARAM, 0.0, 1.0, 0.0));
  160. for (int j=0; j < NBUF; j++) {
  161. addInput(Port::create<sp_Port> (Vec(x1, y1+(j+1.5)*yh), Port::INPUT, module, Rakes::TUNE1_INPUT + j));
  162. addParam(ParamWidget::create<sp_SmallBlackKnob> (Vec(x2, y1+(j+1.5)*yh), module, Rakes::TUNE1_PARAM + j, -5.0, 5.5, 0.0));
  163. addParam(ParamWidget::create<sp_SmallBlackKnob> (Vec(x3, y1+(j+1.5)*yh), module, Rakes::FINE1_PARAM + j, -1.0, 1.0, 0.0));
  164. addParam(ParamWidget::create<sp_SmallBlackKnob> (Vec(x4, y1+(j+1.5)*yh), module, Rakes::GAIN1_PARAM + j, 0.0, 1.0, 0.0));
  165. }
  166. addInput(Port::create<sp_Port> (Vec(x1, y1+8*yh), Port::INPUT, module, Rakes::INL_INPUT));
  167. addInput(Port::create<sp_Port> (Vec(x1, y1+9*yh), Port::INPUT, module, Rakes::INR_INPUT));
  168. addParam(ParamWidget::create<CKSS>( Vec(x2, y1+7.5*yh), module, Rakes::QUANT_PARAM, 0.0, 1.0, 0.0));
  169. addParam(ParamWidget::create<sp_SmallBlackKnob> (Vec((x2+x3)/2., y1+8.5*yh), module, Rakes::MIX_PARAM, 0.0, 1.0, 0.5));
  170. addOutput(Port::create<sp_Port> (Vec(x4, y1+8*yh), Port::OUTPUT, module, Rakes::OUTL_OUTPUT));
  171. addOutput(Port::create<sp_Port> (Vec(x4, y1+9*yh), Port::OUTPUT, module, Rakes::OUTR_OUTPUT));
  172. }
  173. };
  174. } // namespace rack_plugin_Southpole
  175. using namespace rack_plugin_Southpole;
  176. RACK_PLUGIN_MODEL_INIT(Southpole, Rakes) {
  177. Model *modelRakes = Model::create<Rakes,RakesWidget>( "Southpole", "Rakes", "Rakes - resonator bank", FILTER_TAG);
  178. return modelRakes;
  179. }