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.

284 lines
9.6KB

  1. #include "Stochasm.hpp"
  2. namespace rack_plugin_com_soundchasing_stochasm {
  3. #define LFSR_TAPS_MAX_32 0xA3000000u;
  4. #define sMIN(a,b) (((a)>(b))?(b):(a))
  5. #define sMAX(a,b) (((a)>(b))?(a):(b))
  6. struct Resonator : Module {
  7. enum ParamIds {
  8. UPPER_CHAMBER,
  9. UPPER_FILTER1,
  10. UPPER_FILTER2,
  11. UPPER_MANUAL,
  12. LOWER_CHAMBER,
  13. LOWER_FILTER1,
  14. LOWER_FILTER2,
  15. LOWER_MANUAL,
  16. NUM_PARAMS
  17. };
  18. enum InputIds {
  19. UPPER_VOCT,
  20. UPPER_GATE,
  21. LOWER_VOCT,
  22. LOWER_GATE,
  23. NUM_INPUTS
  24. };
  25. enum OutputIds {
  26. UPPER_OUT,
  27. UPPER_BITS,
  28. LOWER_OUT,
  29. LOWER_BITS,
  30. NUM_OUTPUTS
  31. };
  32. enum LightIds {
  33. BLINK_LIGHT,
  34. NUM_LIGHTS
  35. };
  36. const int FILTER_MASK[11] = {15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383};
  37. const float IIR_FILTER_DECAY = 0.09350953781417137f;
  38. unsigned char uDelay[65536] = {0};
  39. int uDelayIndex = 0;
  40. int uDelaySize = 0;
  41. unsigned int uFilter1LFSR = 0xa3005670;
  42. int uFilter1Size = 5;
  43. int uFilter1Count = 0;
  44. unsigned int uFilter2LFSR = 0x6a10d2be;
  45. int uFilter2Size = 5;
  46. int uFilter2Count = 0;
  47. float uCurrent = 0.f;
  48. float uPre = 0.f;
  49. unsigned char lDelay[65536] = {0};
  50. int lDelayIndex = 0;
  51. int lDelaySize = 0;
  52. unsigned int lFilter1LFSR = 0x2ea88906;
  53. int lFilter1Size = 5;
  54. int lFilter1Count = 0;
  55. unsigned int lFilter2LFSR = 0xc1d18e4c;
  56. int lFilter2Size = 5;
  57. int lFilter2Count = 0;
  58. float lCurrent = 0.f;
  59. float lPre = 0.f;
  60. Resonator() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  61. void step() override;
  62. // For more advanced Module features, read Rack's engine.hpp header file
  63. // - toJson, fromJson: serialization of internal data
  64. // - onSampleRateChange: event triggered by a change of sample rate
  65. // - onReset, onRandomize, onCreate, onDelete: implements special behavior when user clicks these from the context menu
  66. };
  67. void Resonator::step() {
  68. int i;
  69. uDelaySize = pow(2, clamp(params[UPPER_CHAMBER].value + inputs[UPPER_VOCT].value, 0.f, 10.f) +6);
  70. lDelaySize = pow(2, clamp(params[LOWER_CHAMBER].value + inputs[LOWER_VOCT].value, 0.f, 10.f) +6);
  71. uDelayIndex %= uDelaySize;
  72. lDelayIndex %= lDelaySize;
  73. int size;
  74. size = (int)params[UPPER_FILTER1].value;
  75. if (size - uFilter1Size > 0)
  76. uFilter1Size << (size - uFilter1Size);
  77. else if (uFilter1Size - size > 0)
  78. uFilter1Size >> (uFilter1Size - size);
  79. uFilter1Size = size;
  80. size = (int)params[UPPER_FILTER2].value;
  81. if (size - uFilter2Size > 0)
  82. uFilter2Size << (size - uFilter2Size);
  83. else if (uFilter2Size - size > 0)
  84. uFilter2Size >> (uFilter2Size - size);
  85. uFilter2Size = size;
  86. size = (int)params[LOWER_FILTER1].value;
  87. if (size - lFilter1Size > 0)
  88. lFilter1Size << (size - lFilter1Size);
  89. else if (lFilter1Size - size > 0)
  90. lFilter1Size >> (lFilter1Size - size);
  91. lFilter1Size = size;
  92. size = (int)params[LOWER_FILTER2].value;
  93. if (size - lFilter2Size > 0)
  94. lFilter2Size << (size - lFilter2Size);
  95. else if (lFilter2Size - size > 0)
  96. lFilter2Size >> (lFilter2Size - size);
  97. lFilter2Size = size;
  98. for (i = 0; i < 32; i++)
  99. {
  100. bool uOut1, uOut2, lOut1, lOut2, uDelayOut, lDelayOut;
  101. //Update LFSR Values
  102. unsigned lsb;
  103. lsb = uFilter1LFSR & 1;
  104. uFilter1LFSR >>= 1;
  105. uFilter1LFSR ^= (-lsb) & LFSR_TAPS_MAX_32;
  106. lsb = uFilter2LFSR & 1;
  107. uFilter2LFSR >>= 1;
  108. uFilter2LFSR ^= (-lsb) & LFSR_TAPS_MAX_32;
  109. lsb = lFilter1LFSR & 1;
  110. lFilter1LFSR >>= 1;
  111. lFilter1LFSR ^= (-lsb) & LFSR_TAPS_MAX_32;
  112. lsb = lFilter2LFSR & 1;
  113. lFilter2LFSR >>= 1;
  114. lFilter2LFSR ^= (-lsb) & LFSR_TAPS_MAX_32;
  115. if (params[UPPER_MANUAL].value > 0.f || inputs[UPPER_GATE].value > 1.7f)
  116. {
  117. //Determine out values
  118. uDelayOut = (bool) uDelay[uDelayIndex];
  119. uOut1 = (uFilter1LFSR & FILTER_MASK[uFilter1Size]) < uFilter1Count;
  120. uOut2 = (uFilter2LFSR & FILTER_MASK[uFilter2Size]) < uFilter2Count;
  121. uFilter1Count = (uDelayOut && !uOut2) ? sMIN(uFilter1Count+1, FILTER_MASK[uFilter1Size]) :
  122. (!uDelayOut && uOut2) ? sMAX(uFilter1Count-1, 0) : uFilter1Count;
  123. uFilter2Count = (uOut1 && !uOut2) ? sMIN(uFilter2Count+1, FILTER_MASK[uFilter2Size]) :
  124. (!uOut1 && uOut2) ? sMAX(uFilter2Count-1, 0) : uFilter2Count;
  125. uDelay[uDelayIndex] = uOut2;
  126. uPre = uPre + IIR_FILTER_DECAY * (((uOut2) ? 5.f : -5.f) - uPre);
  127. uCurrent = uCurrent + IIR_FILTER_DECAY * (uPre - uCurrent);
  128. }
  129. else
  130. {
  131. uDelay[uDelayIndex] = (char)(uFilter2LFSR & 1);
  132. uPre = uPre + IIR_FILTER_DECAY * (-uPre);
  133. uCurrent = uCurrent + IIR_FILTER_DECAY * (-uCurrent);
  134. }
  135. if (params[LOWER_MANUAL].value > 0.f || inputs[LOWER_GATE].value > 1.7f)
  136. {
  137. //Determine out values
  138. lDelayOut = (bool) lDelay[lDelayIndex];
  139. lOut1 = (lFilter1LFSR & FILTER_MASK[lFilter1Size]) < lFilter1Count;
  140. lOut2 = (lFilter2LFSR & FILTER_MASK[lFilter2Size]) < lFilter2Count;
  141. lFilter1Count = (lDelayOut && !lOut2) ? sMIN(lFilter1Count+1, FILTER_MASK[lFilter1Size]) :
  142. (!lDelayOut && lOut2) ? sMAX(lFilter1Count-1, 0) : lFilter1Count;
  143. lFilter2Count = (lOut1 && !lOut2) ? sMIN(lFilter2Count+1, FILTER_MASK[lFilter2Size]) :
  144. (!lOut1 && lOut2) ? sMAX(lFilter2Count-1, 0) : lFilter2Count;
  145. lDelay[lDelayIndex] = lOut2;
  146. lPre = lPre + IIR_FILTER_DECAY * (((lOut2) ? 5.f : -5.f) - lPre);
  147. lCurrent = lCurrent + IIR_FILTER_DECAY * (lPre - lCurrent);
  148. }
  149. else
  150. {
  151. lDelay[lDelayIndex] = (char)(lFilter2LFSR & 1);
  152. lPre = lPre + IIR_FILTER_DECAY * (-lPre);
  153. lCurrent = lCurrent + IIR_FILTER_DECAY * (-lCurrent);
  154. }
  155. uDelayIndex = (uDelayIndex+1) % uDelaySize;
  156. lDelayIndex = (lDelayIndex+1) % lDelaySize;
  157. }
  158. outputs[UPPER_OUT].value = uCurrent;
  159. outputs[LOWER_OUT].value = lCurrent;
  160. }
  161. struct ResonatorWidget : ModuleWidget {
  162. ResonatorWidget(Resonator *module);
  163. };
  164. ResonatorWidget::ResonatorWidget(Resonator *module) : ModuleWidget(module) {
  165. //Resonator *module = new Resonator();
  166. //setModule(module);
  167. box.size = Vec(8 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  168. {
  169. SVGPanel *panel = new SVGPanel();
  170. panel->box.size = box.size;
  171. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Resonator.svg")));
  172. addChild(panel);
  173. }
  174. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  175. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  176. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  177. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  178. //Upper
  179. addParam(ParamWidget::create<StochasmMintLargeKnob>(Vec(52, 30), module, Resonator::UPPER_CHAMBER, 0.0, 10.0, 5.0));
  180. addParam(ParamWidget::create<StochasmMintKnob>(Vec(48, 104), module, Resonator::UPPER_FILTER1, 0.0, 10.0, 5.0));
  181. addParam(ParamWidget::create<StochasmMintKnob>(Vec(85, 104), module, Resonator::UPPER_FILTER2, 0.0, 10.0, 5.0));
  182. addParam(ParamWidget::create<MintMomentarySwitch>(Vec(11, 81), module, Resonator::UPPER_MANUAL, 0.0, 1.0, 0.0));
  183. addInput(Port::create<PJ301MPort>(Vec(12, 43), Port::INPUT, module, Resonator::UPPER_VOCT));
  184. addInput(Port::create<PJ301MPort>(Vec(12, 120), Port::INPUT, module, Resonator::UPPER_GATE));
  185. addOutput(Port::create<PJ301MPort>(Vec(12, 159), Port::OUTPUT, module, Resonator::UPPER_OUT));
  186. addOutput(Port::create<PJ301MPort>(Vec(86, 159), Port::OUTPUT, module, Resonator::UPPER_BITS));
  187. //Lower
  188. addParam(ParamWidget::create<StochasmMintLargeKnob>(Vec(52, 218), module, Resonator::LOWER_CHAMBER, 0.0, 10.0, 5.0));
  189. addParam(ParamWidget::create<StochasmMintKnob>(Vec(48, 292), module, Resonator::LOWER_FILTER1, 0.0, 10.0, 5.0));
  190. addParam(ParamWidget::create<StochasmMintKnob>(Vec(85, 292), module, Resonator::LOWER_FILTER2, 0.0, 10.0, 5.0));
  191. addParam(ParamWidget::create<MintMomentarySwitch>(Vec(11, 269), module, Resonator::LOWER_MANUAL, 0.0, 1.0, 0.0));
  192. addInput(Port::create<PJ301MPort>(Vec(12, 230), Port::INPUT, module, Resonator::LOWER_VOCT));
  193. addInput(Port::create<PJ301MPort>(Vec(12, 308), Port::INPUT, module, Resonator::LOWER_GATE));
  194. addOutput(Port::create<PJ301MPort>(Vec(12, 346), Port::OUTPUT, module, Resonator::LOWER_OUT));
  195. addOutput(Port::create<PJ301MPort>(Vec(86, 346), Port::OUTPUT, module, Resonator::LOWER_BITS));
  196. //addInput(createInput<PJ301MPort>(Vec(33, 186), module, Resonator::PITCH_INPUT));
  197. //addOutput(createOutput<PJ301MPort>(Vec(33, 275), module, Resonator::SINE_OUTPUT));
  198. //addChild(createLight<MediumLight<RedLight>>(Vec(41, 59), module, Resonator::BLINK_LIGHT));
  199. }
  200. /*
  201. Upper:
  202. Chamber, LargeMintKnob -> (52, 30)
  203. Filter1, MintKnob -> (48, 104)
  204. Filter2, MintKnob -> (85, 104)
  205. 1V/OCT, PJ301M -> (12, 43)
  206. Manual, MintMomentary -> (11, 81)
  207. Gate, PJ301M -> (12, 120)
  208. Out, PJ301M -> (12, 159)
  209. Bits, PJ301M -> (86, 159)
  210. Lower:
  211. Chamber, LargeMintKnob -> (52, 218)
  212. Filter1, MintKnob -> (48, 292)
  213. Filter2, MintKnob -> (85, 292)
  214. 1V/OCT, PJ301M -> (12, 230)
  215. Manual, MintMomentary -> (11, 269)
  216. Gate, PJ301M -> (12, 308)
  217. Out, PJ301M -> (12, 346)
  218. Bits, PJ301M -> (86, 346)
  219. */
  220. } // namespace rack_plugin_com_soundchasing_stochasm
  221. using namespace rack_plugin_com_soundchasing_stochasm;
  222. RACK_PLUGIN_MODEL_INIT(com_soundchasing_stochasm, Resonator) {
  223. Model *modelResonator = Model::create<Resonator, ResonatorWidget>("Stochasm", "Resonator", "Bitstream Resonator", OSCILLATOR_TAG, NOISE_TAG);
  224. return modelResonator;
  225. }