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.

SEQ3.cpp 7.1KB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "plugin.hpp"
  2. struct SEQ3 : Module {
  3. enum ParamIds {
  4. CLOCK_PARAM,
  5. RUN_PARAM,
  6. RESET_PARAM,
  7. STEPS_PARAM,
  8. ENUMS(ROW1_PARAM, 8),
  9. ENUMS(ROW2_PARAM, 8),
  10. ENUMS(ROW3_PARAM, 8),
  11. ENUMS(GATE_PARAM, 8),
  12. NUM_PARAMS
  13. };
  14. enum InputIds {
  15. CLOCK_INPUT,
  16. EXT_CLOCK_INPUT,
  17. RESET_INPUT,
  18. STEPS_INPUT,
  19. NUM_INPUTS
  20. };
  21. enum OutputIds {
  22. GATES_OUTPUT,
  23. ROW1_OUTPUT,
  24. ROW2_OUTPUT,
  25. ROW3_OUTPUT,
  26. ENUMS(GATE_OUTPUT, 8),
  27. NUM_OUTPUTS
  28. };
  29. enum LightIds {
  30. RUNNING_LIGHT,
  31. RESET_LIGHT,
  32. GATES_LIGHT,
  33. ENUMS(ROW_LIGHTS, 3),
  34. ENUMS(GATE_LIGHTS, 8),
  35. NUM_LIGHTS
  36. };
  37. bool running = true;
  38. dsp::SchmittTrigger clockTrigger;
  39. dsp::SchmittTrigger runningTrigger;
  40. dsp::SchmittTrigger resetTrigger;
  41. dsp::SchmittTrigger gateTriggers[8];
  42. /** Phase of internal LFO */
  43. float phase = 0.f;
  44. int index = 0;
  45. bool gates[8] = {};
  46. SEQ3() {
  47. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  48. configParam(CLOCK_PARAM, -2.f, 6.f, 2.f, "Clock tempo", " bpm", 2.f, 60.f);
  49. configParam(RUN_PARAM, 0.f, 1.f, 0.f);
  50. configParam(RESET_PARAM, 0.f, 1.f, 0.f);
  51. configParam(STEPS_PARAM, 1.f, 8.f, 8.f);
  52. for (int i = 0; i < 8; i++) {
  53. configParam(ROW1_PARAM + i, 0.f, 10.f, 0.f);
  54. configParam(ROW2_PARAM + i, 0.f, 10.f, 0.f);
  55. configParam(ROW3_PARAM + i, 0.f, 10.f, 0.f);
  56. configParam(GATE_PARAM + i, 0.f, 1.f, 0.f);
  57. }
  58. onReset();
  59. }
  60. void onReset() override {
  61. for (int i = 0; i < 8; i++) {
  62. gates[i] = true;
  63. }
  64. }
  65. void onRandomize() override {
  66. for (int i = 0; i < 8; i++) {
  67. gates[i] = (random::uniform() > 0.5f);
  68. }
  69. }
  70. json_t* dataToJson() override {
  71. json_t* rootJ = json_object();
  72. // running
  73. json_object_set_new(rootJ, "running", json_boolean(running));
  74. // gates
  75. json_t* gatesJ = json_array();
  76. for (int i = 0; i < 8; i++) {
  77. json_array_insert_new(gatesJ, i, json_integer((int) gates[i]));
  78. }
  79. json_object_set_new(rootJ, "gates", gatesJ);
  80. return rootJ;
  81. }
  82. void dataFromJson(json_t* rootJ) override {
  83. // running
  84. json_t* runningJ = json_object_get(rootJ, "running");
  85. if (runningJ)
  86. running = json_is_true(runningJ);
  87. // gates
  88. json_t* gatesJ = json_object_get(rootJ, "gates");
  89. if (gatesJ) {
  90. for (int i = 0; i < 8; i++) {
  91. json_t* gateJ = json_array_get(gatesJ, i);
  92. if (gateJ)
  93. gates[i] = !!json_integer_value(gateJ);
  94. }
  95. }
  96. }
  97. void setIndex(int index) {
  98. int numSteps = (int) clamp(std::round(params[STEPS_PARAM].getValue() + inputs[STEPS_INPUT].getVoltage()), 1.f, 8.f);
  99. phase = 0.f;
  100. this->index = index;
  101. if (this->index >= numSteps)
  102. this->index = 0;
  103. }
  104. void process(const ProcessArgs& args) override {
  105. // Run
  106. if (runningTrigger.process(params[RUN_PARAM].getValue())) {
  107. running = !running;
  108. }
  109. bool gateIn = false;
  110. if (running) {
  111. if (inputs[EXT_CLOCK_INPUT].isConnected()) {
  112. // External clock
  113. if (clockTrigger.process(inputs[EXT_CLOCK_INPUT].getVoltage())) {
  114. setIndex(index + 1);
  115. }
  116. gateIn = clockTrigger.isHigh();
  117. }
  118. else {
  119. // Internal clock
  120. float clockTime = std::pow(2.f, params[CLOCK_PARAM].getValue() + inputs[CLOCK_INPUT].getVoltage());
  121. phase += clockTime * args.sampleTime;
  122. if (phase >= 1.f) {
  123. setIndex(index + 1);
  124. }
  125. gateIn = (phase < 0.5f);
  126. }
  127. }
  128. // Reset
  129. if (resetTrigger.process(params[RESET_PARAM].getValue() + inputs[RESET_INPUT].getVoltage())) {
  130. setIndex(0);
  131. }
  132. // Gate buttons
  133. for (int i = 0; i < 8; i++) {
  134. if (gateTriggers[i].process(params[GATE_PARAM + i].getValue())) {
  135. gates[i] = !gates[i];
  136. }
  137. outputs[GATE_OUTPUT + i].setVoltage((running && gateIn && i == index && gates[i]) ? 10.f : 0.f);
  138. lights[GATE_LIGHTS + i].setSmoothBrightness((gateIn && i == index) ? (gates[i] ? 1.f : 0.33) : (gates[i] ? 0.66 : 0.0), args.sampleTime);
  139. }
  140. // Outputs
  141. outputs[ROW1_OUTPUT].setVoltage(params[ROW1_PARAM + index].getValue());
  142. outputs[ROW2_OUTPUT].setVoltage(params[ROW2_PARAM + index].getValue());
  143. outputs[ROW3_OUTPUT].setVoltage(params[ROW3_PARAM + index].getValue());
  144. outputs[GATES_OUTPUT].setVoltage((gateIn && gates[index]) ? 10.f : 0.f);
  145. lights[RUNNING_LIGHT].value = (running);
  146. lights[RESET_LIGHT].setSmoothBrightness(resetTrigger.isHigh(), args.sampleTime);
  147. lights[GATES_LIGHT].setSmoothBrightness(gateIn, args.sampleTime);
  148. lights[ROW_LIGHTS].value = outputs[ROW1_OUTPUT].value / 10.f;
  149. lights[ROW_LIGHTS + 1].value = outputs[ROW2_OUTPUT].value / 10.f;
  150. lights[ROW_LIGHTS + 2].value = outputs[ROW3_OUTPUT].value / 10.f;
  151. }
  152. };
  153. struct SEQ3Widget : ModuleWidget {
  154. SEQ3Widget(SEQ3* module) {
  155. setModule(module);
  156. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/SEQ3.svg")));
  157. addChild(createWidget<ScrewSilver>(Vec(15, 0)));
  158. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0)));
  159. addChild(createWidget<ScrewSilver>(Vec(15, 365)));
  160. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365)));
  161. addParam(createParam<RoundBlackKnob>(Vec(18, 56), module, SEQ3::CLOCK_PARAM));
  162. addParam(createParam<LEDButton>(Vec(60, 61 - 1), module, SEQ3::RUN_PARAM));
  163. addChild(createLight<MediumLight<GreenLight>>(Vec(64.4f, 64.4f), module, SEQ3::RUNNING_LIGHT));
  164. addParam(createParam<LEDButton>(Vec(99, 61 - 1), module, SEQ3::RESET_PARAM));
  165. addChild(createLight<MediumLight<GreenLight>>(Vec(103.4f, 64.4f), module, SEQ3::RESET_LIGHT));
  166. addParam(createParam<RoundBlackSnapKnob>(Vec(132, 56), module, SEQ3::STEPS_PARAM));
  167. addChild(createLight<MediumLight<GreenLight>>(Vec(179.4f, 64.4f), module, SEQ3::GATES_LIGHT));
  168. addChild(createLight<MediumLight<GreenLight>>(Vec(218.4f, 64.4f), module, SEQ3::ROW_LIGHTS));
  169. addChild(createLight<MediumLight<GreenLight>>(Vec(256.4f, 64.4f), module, SEQ3::ROW_LIGHTS + 1));
  170. addChild(createLight<MediumLight<GreenLight>>(Vec(295.4f, 64.4f), module, SEQ3::ROW_LIGHTS + 2));
  171. static const float portX[8] = {20, 58, 96, 135, 173, 212, 250, 289};
  172. addInput(createInput<PJ301MPort>(Vec(portX[0] - 1, 98), module, SEQ3::CLOCK_INPUT));
  173. addInput(createInput<PJ301MPort>(Vec(portX[1] - 1, 98), module, SEQ3::EXT_CLOCK_INPUT));
  174. addInput(createInput<PJ301MPort>(Vec(portX[2] - 1, 98), module, SEQ3::RESET_INPUT));
  175. addInput(createInput<PJ301MPort>(Vec(portX[3] - 1, 98), module, SEQ3::STEPS_INPUT));
  176. addOutput(createOutput<PJ301MPort>(Vec(portX[4] - 1, 98), module, SEQ3::GATES_OUTPUT));
  177. addOutput(createOutput<PJ301MPort>(Vec(portX[5] - 1, 98), module, SEQ3::ROW1_OUTPUT));
  178. addOutput(createOutput<PJ301MPort>(Vec(portX[6] - 1, 98), module, SEQ3::ROW2_OUTPUT));
  179. addOutput(createOutput<PJ301MPort>(Vec(portX[7] - 1, 98), module, SEQ3::ROW3_OUTPUT));
  180. for (int i = 0; i < 8; i++) {
  181. addParam(createParam<RoundBlackKnob>(Vec(portX[i] - 2, 157), module, SEQ3::ROW1_PARAM + i));
  182. addParam(createParam<RoundBlackKnob>(Vec(portX[i] - 2, 198), module, SEQ3::ROW2_PARAM + i));
  183. addParam(createParam<RoundBlackKnob>(Vec(portX[i] - 2, 240), module, SEQ3::ROW3_PARAM + i));
  184. addParam(createParam<LEDButton>(Vec(portX[i] + 2, 278 - 1), module, SEQ3::GATE_PARAM + i));
  185. addChild(createLight<MediumLight<GreenLight>>(Vec(portX[i] + 6.4f, 281.4f), module, SEQ3::GATE_LIGHTS + i));
  186. addOutput(createOutput<PJ301MPort>(Vec(portX[i] - 1, 307), module, SEQ3::GATE_OUTPUT + i));
  187. }
  188. }
  189. };
  190. Model* modelSEQ3 = createModel<SEQ3, SEQ3Widget>("SEQ3");