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.

306 lines
11KB

  1. #include "LFSR.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_alto777_LFSR {
  4. struct YASeq3 : Module {
  5. enum ParamIds {
  6. CLOCK_PARAM,
  7. RUN_PARAM,
  8. RESET_PARAM,
  9. STEPS_PARAM,
  10. ENUMS(ROW1_PARAM, 8),
  11. ENUMS(ROW2_PARAM, 8),
  12. ENUMS(ROW3_PARAM, 8),
  13. ENUMS(GATE_PARAM, 8),
  14. ENUMS(MODE_PARAM, 3),
  15. ENUMS(RANGE_PARAM, 3),
  16. NUM_PARAMS
  17. };
  18. enum InputIds {
  19. CLOCK_INPUT,
  20. EXT_CLOCK_INPUT,
  21. RESET_INPUT,
  22. STEPS_INPUT,
  23. NUM_INPUTS
  24. };
  25. enum OutputIds {
  26. GATES_OUTPUT,
  27. ROW1_OUTPUT,
  28. ROW2_OUTPUT,
  29. ROW3_OUTPUT,
  30. ENUMS(GATE_OUTPUT, 8),
  31. NUM_OUTPUTS
  32. };
  33. enum LightIds {
  34. RUNNING_LIGHT,
  35. RESET_LIGHT,
  36. // GATES_LIGHT,
  37. // ENUMS(ROW_LIGHTS, 3),
  38. ENUMS(GATE_LIGHTS, 8),
  39. NUM_LIGHTS
  40. };
  41. bool running = true;
  42. SchmittTrigger clockTrigger;
  43. SchmittTrigger runningTrigger;
  44. SchmittTrigger resetTrigger;
  45. SchmittTrigger gateTriggers[8];
  46. /** Phase of internal LFO */
  47. float phase = 0.f;
  48. int index = 0;
  49. bool gates[8] = {};
  50. const int chromaticScale[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  51. const int diatonicScale[13] = {0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21};
  52. YASeq3() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  53. onReset();
  54. }
  55. void onReset() override {
  56. for (int i = 0; i < 8; i++) {
  57. gates[i] = true;
  58. }
  59. }
  60. void onRandomize() override {
  61. for (int i = 0; i < 8; i++) {
  62. gates[i] = (randomUniform() > 0.5f);
  63. }
  64. }
  65. json_t *toJson() override {
  66. json_t *rootJ = json_object();
  67. // running
  68. json_object_set_new(rootJ, "running", json_boolean(running));
  69. // gates
  70. json_t *gatesJ = json_array();
  71. for (int i = 0; i < 8; i++) {
  72. json_array_insert_new(gatesJ, i, json_integer((int) gates[i]));
  73. }
  74. json_object_set_new(rootJ, "gates", gatesJ);
  75. return rootJ;
  76. }
  77. void fromJson(json_t *rootJ) override {
  78. // running
  79. json_t *runningJ = json_object_get(rootJ, "running");
  80. if (runningJ)
  81. running = json_is_true(runningJ);
  82. // gates
  83. json_t *gatesJ = json_object_get(rootJ, "gates");
  84. if (gatesJ) {
  85. for (int i = 0; i < 8; i++) {
  86. json_t *gateJ = json_array_get(gatesJ, i);
  87. if (gateJ)
  88. gates[i] = !!json_integer_value(gateJ);
  89. }
  90. }
  91. }
  92. void setIndex(int index) {
  93. int numSteps = (int) clamp(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value), 1.0f, 8.0f);
  94. phase = 0.f;
  95. this->index = index;
  96. if (this->index >= numSteps)
  97. this->index = 0;
  98. }
  99. void step() override {
  100. // Run
  101. if (runningTrigger.process(params[RUN_PARAM].value)) {
  102. running = !running;
  103. }
  104. bool gateIn = false;
  105. if (running) {
  106. if (inputs[EXT_CLOCK_INPUT].active) {
  107. // External clock
  108. if (clockTrigger.process(inputs[EXT_CLOCK_INPUT].value)) {
  109. setIndex(index + 1);
  110. }
  111. gateIn = clockTrigger.isHigh();
  112. }
  113. else {
  114. // Internal clock
  115. float clockTime = powf(2.0f, params[CLOCK_PARAM].value + inputs[CLOCK_INPUT].value);
  116. phase += clockTime * engineGetSampleTime();
  117. if (phase >= 1.0f) {
  118. setIndex(index + 1);
  119. }
  120. gateIn = (phase < 0.5f);
  121. }
  122. }
  123. // Reset
  124. if (resetTrigger.process(params[RESET_PARAM].value + inputs[RESET_INPUT].value)) {
  125. setIndex(0);
  126. }
  127. // Gate buttons
  128. for (int i = 0; i < 8; i++) {
  129. if (gateTriggers[i].process(params[GATE_PARAM + i].value)) {
  130. gates[i] = !gates[i];
  131. }
  132. outputs[GATE_OUTPUT + i].value = (running && gateIn && i == index && gates[i]) ? 10.0f : 0.0f;
  133. lights[GATE_LIGHTS + i].setBrightnessSmooth((gateIn && i == index) ? (gates[i] ? 1.f : 0.33) : (gates[i] ? 0.66 : 0.0));
  134. }
  135. // Outputs
  136. /* figure out how to loopy loop enumerated enums */
  137. int rowSetting = round(params[ROW1_PARAM + index].value + 0.1);
  138. if (params[MODE_PARAM + 0].value > 1.1f) { /* infinite */
  139. outputs[ROW1_OUTPUT].value = params[ROW1_PARAM + index].value * ((params[RANGE_PARAM + 0].value > 0.5f) ? 1.0f : 0.1f);
  140. }
  141. else if (params[MODE_PARAM + 0].value < 0.9f) { /* diatonic */
  142. outputs[ROW1_OUTPUT].value = chromaticScale[rowSetting] / 12.0f;
  143. }
  144. else { /* chromatic */
  145. outputs[ROW1_OUTPUT].value = diatonicScale[rowSetting] / 12.0f;
  146. }
  147. rowSetting = round(params[ROW2_PARAM + index].value + 0.1);
  148. if (params[MODE_PARAM + 1].value > 1.1f) { /* infinite */
  149. outputs[ROW2_OUTPUT].value = params[ROW2_PARAM + index].value * ((params[RANGE_PARAM + 1].value > 0.5f) ? 1.0f : 0.1f);
  150. }
  151. else if (params[MODE_PARAM + 1].value < 0.9f) { /* diatonic */
  152. outputs[ROW2_OUTPUT].value = chromaticScale[rowSetting] / 12.0f;
  153. }
  154. else { /* chromatic */
  155. outputs[ROW2_OUTPUT].value = diatonicScale[rowSetting] / 12.0f;
  156. }
  157. rowSetting = round(params[ROW3_PARAM + index].value + 0.1);
  158. if (params[MODE_PARAM + 2].value > 1.1f) { /* infinite */
  159. outputs[ROW3_OUTPUT].value = params[ROW3_PARAM + index].value * ((params[RANGE_PARAM + 2].value > 0.5f) ? 1.0f : 0.1f);
  160. }
  161. else if (params[MODE_PARAM + 2].value < 0.9f) { /* diatonic */
  162. outputs[ROW3_OUTPUT].value = chromaticScale[rowSetting] / 12.0f;
  163. }
  164. else { /* chromatic */
  165. outputs[ROW3_OUTPUT].value = diatonicScale[rowSetting] / 12.0f;
  166. }
  167. outputs[GATES_OUTPUT].value = (gateIn && gates[index]) ? 10.0f : 0.0f;
  168. lights[RUNNING_LIGHT].value = (running);
  169. lights[RESET_LIGHT].setBrightnessSmooth(resetTrigger.isHigh());
  170. // lights[GATES_LIGHT].setBrightnessSmooth(gateIn);
  171. // lights[ROW_LIGHTS].value = outputs[ROW1_OUTPUT].value / 10.0f;
  172. // lights[ROW_LIGHTS + 1].value = outputs[ROW2_OUTPUT].value / 10.0f;
  173. // lights[ROW_LIGHTS + 2].value = outputs[ROW3_OUTPUT].value / 10.0f;
  174. }
  175. };
  176. /* from Playground MyModule */
  177. struct x13SlidePot : SVGSlider { /* 13 steps 6 px per = 78 tall, so */
  178. x13SlidePot() {
  179. maxHandlePos = Vec(-1.65, 0);// .plus(margin);
  180. minHandlePos = Vec(-1.65, 72);// .plus(margin);
  181. setSVGs(SVG::load(assetPlugin(plugin, "res/x13SlidePot.svg")), SVG::load(assetPlugin(plugin, "res/x13SlidePotHandle.svg")));
  182. }
  183. };
  184. template <typename BASE>
  185. struct bigLight : BASE {
  186. bigLight() {
  187. this->box.size = mm2px(Vec(6.0, 6.0));
  188. }
  189. };
  190. struct myOther2Switch : SVGSwitch, ToggleSwitch {
  191. myOther2Switch() {
  192. addFrame(SVG::load(assetPlugin(plugin, "res/myCKSS_1.svg")));
  193. addFrame(SVG::load(assetPlugin(plugin, "res/myCKSS_0.svg")));
  194. }
  195. };
  196. struct my3Switch : SVGSwitch, ToggleSwitch {
  197. my3Switch() {
  198. addFrame(SVG::load(assetPlugin(plugin, "res/myCKSSThree_0.svg")));
  199. addFrame(SVG::load(assetPlugin(plugin, "res/myCKSSThree_1.svg")));
  200. addFrame(SVG::load(assetPlugin(plugin, "res/myCKSSThree_2.svg")));
  201. }
  202. };
  203. // addParam(ParamWidget::create<myOther2Switch>(Vec(330, 87), module, YASeq3::RANGE + 0, 0.0, 1.0, 0.0));
  204. // addParam(ParamWidget::create<my3Switch>(Vec(352, 92), module, YASeq3::MODE + 0, 0.0, 2.0, 0.0));
  205. struct YASeq3Widget : ModuleWidget {
  206. YASeq3Widget(YASeq3 *module) : ModuleWidget(module) {
  207. setPanel(SVG::load(assetPlugin(plugin, "res/YASeq3.svg")));
  208. addChild(Widget::create<ScrewSilver>(Vec(0, 0)));
  209. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15, 0)));
  210. addChild(Widget::create<ScrewSilver>(Vec(0, 365)));
  211. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15, 365)));
  212. addParam(ParamWidget::create<RoundBlackKnob>(Vec(20, 98 - 50 - 15 - 4), module, YASeq3::CLOCK_PARAM, -2.0f, 6.0f, 2.0f));
  213. addParam(ParamWidget::create<LEDBezel>(Vec(154, 98 - 50 - 15), module, YASeq3::RUN_PARAM, 0.0f, 1.0f, 0.0f));
  214. addChild(ModuleLightWidget::create<bigLight<GreenLight>>(Vec(154 + 2, 98 - 50 - 15 + 2), module, YASeq3::RUNNING_LIGHT));
  215. addParam(ParamWidget::create<LEDBezel>(Vec(192, 98 - 50 - 15), module, YASeq3::RESET_PARAM, 0.0f, 1.0f, 0.0f));
  216. addChild(ModuleLightWidget::create<bigLight<YellowLight>>(Vec(192 + 2, 98 - 50 - 15 + 2), module, YASeq3::RESET_LIGHT));
  217. addInput(Port::create<PJ301MPort>(Vec(230, 98 - 50 - 15), Port::INPUT, module, YASeq3::RESET_INPUT));
  218. addParam(ParamWidget::create<RoundBlackSnapKnob>(Vec(268, 98 - 50 - 15 - 4), module, YASeq3::STEPS_PARAM, 1.0f, 8.0f, 8.0f));
  219. addInput(Port::create<PJ301MPort>(Vec(306, 98 - 50 - 15), Port::INPUT, module, YASeq3::STEPS_INPUT));
  220. // addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(179.4f, 64.4f), module, YASeq3::GATES_LIGHT));
  221. // addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(218.4f, 64.4f), module, YASeq3::ROW_LIGHTS));
  222. // addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(256.4f, 64.4f), module, YASeq3::ROW_LIGHTS + 1));
  223. // addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(295.4f, 64.4f), module, YASeq3::ROW_LIGHTS + 2));
  224. static const float portX[8] = {20, 58, 96, 135, 173, 212, 250, 289};
  225. addInput(Port::create<PJ301MPort>(Vec(64.4f - 6, 98 - 50 - 15), Port::INPUT, module, YASeq3::CLOCK_INPUT));
  226. addInput(Port::create<PJ301MPort>(Vec(103.4 - 12, 98 - 50 - 15), Port::INPUT, module, YASeq3::EXT_CLOCK_INPUT));
  227. addOutput(Port::create<PJ301MPort>(Vec(332, 307 + 50 - 13), Port::OUTPUT, module, YASeq3::GATES_OUTPUT));
  228. addOutput(Port::create<PJ301MPort>(Vec(332, 132), Port::OUTPUT, module, YASeq3::ROW1_OUTPUT));
  229. addOutput(Port::create<PJ301MPort>(Vec(332, 212), Port::OUTPUT, module, YASeq3::ROW2_OUTPUT));
  230. addOutput(Port::create<PJ301MPort>(Vec(332, 292), Port::OUTPUT, module, YASeq3::ROW3_OUTPUT));
  231. addParam(ParamWidget::create<myOther2Switch>(Vec(330, 97), module, YASeq3::RANGE_PARAM + 0, 0.0, 1.0, 0.0));
  232. addParam(ParamWidget::create<my3Switch>(Vec(352, 102), module, YASeq3::MODE_PARAM + 0, 0.0, 2.0, 0.0));
  233. addParam(ParamWidget::create<myOther2Switch>(Vec(330, 97 + 80), module, YASeq3::RANGE_PARAM + 1, 0.0, 1.0, 0.0));
  234. addParam(ParamWidget::create<my3Switch>(Vec(352, 102 + 80), module, YASeq3::MODE_PARAM + 1, 0.0, 2.0, 0.0));
  235. addParam(ParamWidget::create<myOther2Switch>(Vec(330, 97 + 160), module, YASeq3::RANGE_PARAM + 2, 0.0, 1.0, 0.0));
  236. addParam(ParamWidget::create<my3Switch>(Vec(352, 102 + 160), module, YASeq3::MODE_PARAM + 2, 0.0, 2.0, 0.0));
  237. for (int i = 0; i < 8; i++) {
  238. addParam(ParamWidget::create<x13SlidePot>(Vec(portX[i]-2 + 10, 157 - 80), module, YASeq3::ROW1_PARAM + i, 0.0f, 12.0f, 0.0f));
  239. addParam(ParamWidget::create<x13SlidePot>(Vec(portX[i]-2 + 10, 198 - 40), module, YASeq3::ROW2_PARAM + i, 0.0f, 12.0f, 0.0f));
  240. addParam(ParamWidget::create<x13SlidePot>(Vec(portX[i]-2 + 10, 240 - 0), module, YASeq3::ROW3_PARAM + i, 0.0f, 12.0f, 0.0f));
  241. /**/ addParam(ParamWidget::create<LEDButton>(Vec(portX[i]+2, 278-1 + 50 - 7), module, YASeq3::GATE_PARAM + i, 0.0f, 1.0f, 0.0f));
  242. /**/ addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(portX[i]+6.4f, 281.4f + 50 - 7), module, YASeq3::GATE_LIGHTS + i));
  243. /**/ addOutput(Port::create<PJ301MPort>(Vec(portX[i]-1, 307 + 50 - 13), Port::OUTPUT, module, YASeq3::GATE_OUTPUT + i));
  244. }
  245. }
  246. };
  247. } // namespace rack_plugin_alto777_LFSR
  248. using namespace rack_plugin_alto777_LFSR;
  249. RACK_PLUGIN_MODEL_INIT(alto777_LFSR, YASeq3) {
  250. Model *modelYASeq3 = Model::create<YASeq3, YASeq3Widget>("alto777_LFSR", "YASeq3", "Yet Another SEQ3", SEQUENCER_TAG);
  251. return modelYASeq3;
  252. }