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.

166 lines
6.0KB

  1. #include "plugin.hpp"
  2. #include "warps/dsp/modulator.h"
  3. struct Warps : Module {
  4. enum ParamIds {
  5. ALGORITHM_PARAM,
  6. TIMBRE_PARAM,
  7. STATE_PARAM,
  8. LEVEL1_PARAM,
  9. LEVEL2_PARAM,
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. LEVEL1_INPUT,
  14. LEVEL2_INPUT,
  15. ALGORITHM_INPUT,
  16. TIMBRE_INPUT,
  17. CARRIER_INPUT,
  18. MODULATOR_INPUT,
  19. NUM_INPUTS
  20. };
  21. enum OutputIds {
  22. MODULATOR_OUTPUT,
  23. AUX_OUTPUT,
  24. NUM_OUTPUTS
  25. };
  26. enum LightIds {
  27. CARRIER_GREEN_LIGHT, CARRIER_RED_LIGHT,
  28. ALGORITHM_LIGHT,
  29. NUM_LIGHTS = ALGORITHM_LIGHT + 3
  30. };
  31. int frame = 0;
  32. warps::Modulator modulator;
  33. warps::ShortFrame inputFrames[60] = {};
  34. warps::ShortFrame outputFrames[60] = {};
  35. dsp::SchmittTrigger stateTrigger;
  36. Warps() {
  37. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  38. configParam(ALGORITHM_PARAM, 0.0, 8.0, 0.0, "Algorithm");
  39. configParam(TIMBRE_PARAM, 0.0, 1.0, 0.5, "Timbre", "%", 0, 100);
  40. configButton(STATE_PARAM, "Internal oscillator mode");
  41. configParam(LEVEL1_PARAM, 0.0, 1.0, 1.0, "External oscillator amplitude / internal oscillator frequency", "%", 0, 100);
  42. configParam(LEVEL2_PARAM, 0.0, 1.0, 1.0, "Modulator amplitude", "%", 0, 100);
  43. configInput(LEVEL1_INPUT, "Level 1");
  44. configInput(LEVEL2_INPUT, "Level 2");
  45. configInput(ALGORITHM_INPUT, "Algorithm");
  46. configInput(TIMBRE_INPUT, "Timbre");
  47. configInput(CARRIER_INPUT, "Carrier");
  48. configInput(MODULATOR_INPUT, "Modulator");
  49. configOutput(MODULATOR_OUTPUT, "Modulator");
  50. configOutput(AUX_OUTPUT, "Auxiliary");
  51. memset(&modulator, 0, sizeof(modulator));
  52. modulator.Init(96000.0f);
  53. }
  54. void process(const ProcessArgs& args) override {
  55. // State trigger
  56. warps::Parameters* p = modulator.mutable_parameters();
  57. if (stateTrigger.process(params[STATE_PARAM].getValue())) {
  58. p->carrier_shape = (p->carrier_shape + 1) % 4;
  59. }
  60. lights[CARRIER_GREEN_LIGHT].value = (p->carrier_shape == 1 || p->carrier_shape == 2) ? 1.0 : 0.0;
  61. lights[CARRIER_RED_LIGHT].value = (p->carrier_shape == 2 || p->carrier_shape == 3) ? 1.0 : 0.0;
  62. // Buffer loop
  63. if (++frame >= 60) {
  64. frame = 0;
  65. p->channel_drive[0] = clamp(params[LEVEL1_PARAM].getValue() + inputs[LEVEL1_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f);
  66. p->channel_drive[1] = clamp(params[LEVEL2_PARAM].getValue() + inputs[LEVEL2_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f);
  67. p->modulation_algorithm = clamp(params[ALGORITHM_PARAM].getValue() / 8.0f + inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f);
  68. {
  69. // TODO
  70. // Use the correct light color
  71. NVGcolor algorithmColor = nvgHSL(p->modulation_algorithm, 1.0, 0.5);
  72. lights[ALGORITHM_LIGHT + 0].setBrightness(algorithmColor.r);
  73. lights[ALGORITHM_LIGHT + 1].setBrightness(algorithmColor.g);
  74. lights[ALGORITHM_LIGHT + 2].setBrightness(algorithmColor.b);
  75. }
  76. p->modulation_parameter = clamp(params[TIMBRE_PARAM].getValue() + inputs[TIMBRE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f);
  77. p->frequency_shift_pot = params[ALGORITHM_PARAM].getValue() / 8.0;
  78. p->frequency_shift_cv = clamp(inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f);
  79. p->phase_shift = p->modulation_algorithm;
  80. p->note = 60.0 * params[LEVEL1_PARAM].getValue() + 12.0 * inputs[LEVEL1_INPUT].getNormalVoltage(2.0) + 12.0;
  81. p->note += log2f(96000.0f * args.sampleTime) * 12.0f;
  82. modulator.Process(inputFrames, outputFrames, 60);
  83. }
  84. inputFrames[frame].l = clamp((int)(inputs[CARRIER_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff);
  85. inputFrames[frame].r = clamp((int)(inputs[MODULATOR_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff);
  86. outputs[MODULATOR_OUTPUT].setVoltage((float)outputFrames[frame].l / 0x8000 * 5.0);
  87. outputs[AUX_OUTPUT].setVoltage((float)outputFrames[frame].r / 0x8000 * 5.0);
  88. }
  89. json_t* dataToJson() override {
  90. json_t* rootJ = json_object();
  91. warps::Parameters* p = modulator.mutable_parameters();
  92. json_object_set_new(rootJ, "shape", json_integer(p->carrier_shape));
  93. return rootJ;
  94. }
  95. void dataFromJson(json_t* rootJ) override {
  96. json_t* shapeJ = json_object_get(rootJ, "shape");
  97. warps::Parameters* p = modulator.mutable_parameters();
  98. if (shapeJ) {
  99. p->carrier_shape = json_integer_value(shapeJ);
  100. }
  101. }
  102. void onReset() override {
  103. warps::Parameters* p = modulator.mutable_parameters();
  104. p->carrier_shape = 0;
  105. }
  106. void onRandomize() override {
  107. warps::Parameters* p = modulator.mutable_parameters();
  108. p->carrier_shape = random::u32() % 4;
  109. }
  110. };
  111. struct WarpsWidget : ModuleWidget {
  112. WarpsWidget(Warps* module) {
  113. setModule(module);
  114. setPanel(Svg::load(asset::plugin(pluginInstance, "res/Warps.svg")));
  115. addChild(createWidget<ScrewSilver>(Vec(15, 0)));
  116. addChild(createWidget<ScrewSilver>(Vec(120, 0)));
  117. addChild(createWidget<ScrewSilver>(Vec(15, 365)));
  118. addChild(createWidget<ScrewSilver>(Vec(120, 365)));
  119. addParam(createParamCentered<Rogan6PSWhite>(Vec(73.556641, 96.560532), module, Warps::ALGORITHM_PARAM));
  120. addParam(createParam<Rogan1PSWhite>(Vec(94, 173), module, Warps::TIMBRE_PARAM));
  121. addParam(createParam<TL1105>(Vec(16, 182), module, Warps::STATE_PARAM));
  122. addParam(createParam<Trimpot>(Vec(14, 213), module, Warps::LEVEL1_PARAM));
  123. addParam(createParam<Trimpot>(Vec(53, 213), module, Warps::LEVEL2_PARAM));
  124. addInput(createInput<PJ301MPort>(Vec(8, 273), module, Warps::LEVEL1_INPUT));
  125. addInput(createInput<PJ301MPort>(Vec(44, 273), module, Warps::LEVEL2_INPUT));
  126. addInput(createInput<PJ301MPort>(Vec(80, 273), module, Warps::ALGORITHM_INPUT));
  127. addInput(createInput<PJ301MPort>(Vec(116, 273), module, Warps::TIMBRE_INPUT));
  128. addInput(createInput<PJ301MPort>(Vec(8, 316), module, Warps::CARRIER_INPUT));
  129. addInput(createInput<PJ301MPort>(Vec(44, 316), module, Warps::MODULATOR_INPUT));
  130. addOutput(createOutput<PJ301MPort>(Vec(80, 316), module, Warps::MODULATOR_OUTPUT));
  131. addOutput(createOutput<PJ301MPort>(Vec(116, 316), module, Warps::AUX_OUTPUT));
  132. addChild(createLight<SmallLight<GreenRedLight>>(Vec(21, 167), module, Warps::CARRIER_GREEN_LIGHT));
  133. addChild(createLightCentered<Rogan6PSLight<RedGreenBlueLight>>(Vec(73.556641, 96.560532), module, Warps::ALGORITHM_LIGHT));
  134. }
  135. };
  136. Model* modelWarps = createModel<Warps, WarpsWidget>("Warps");