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.

204 lines
6.4KB

  1. #include <string.h>
  2. #include "AudibleInstruments.hpp"
  3. #include "dsp.hpp"
  4. #include "clouds/dsp/granular_processor.h"
  5. struct Clouds : Module {
  6. enum ParamIds {
  7. POSITION_PARAM,
  8. SIZE_PARAM,
  9. PITCH_PARAM,
  10. IN_GAIN_PARAM,
  11. DENSITY_PARAM,
  12. TEXTURE_PARAM,
  13. BLEND_PARAM,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. FREEZE_INPUT,
  18. TRIG_INPUT,
  19. POSITION_INPUT,
  20. SIZE_INPUT,
  21. PITCH_INPUT,
  22. BLEND_INPUT,
  23. IN_L_INPUT,
  24. IN_R_INPUT,
  25. DENSITY_INPUT,
  26. TEXTURE_INPUT,
  27. NUM_INPUTS
  28. };
  29. enum OutputIds {
  30. OUT_L_OUTPUT,
  31. OUT_R_OUTPUT,
  32. NUM_OUTPUTS
  33. };
  34. SampleRateConverter<2> inputSrc;
  35. SampleRateConverter<2> outputSrc;
  36. DoubleRingBuffer<Frame<2>, 256> inputBuffer;
  37. DoubleRingBuffer<Frame<2>, 256> outputBuffer;
  38. uint8_t *block_mem;
  39. uint8_t *block_ccm;
  40. clouds::GranularProcessor *processor;
  41. bool triggered = false;
  42. Clouds();
  43. ~Clouds();
  44. void step();
  45. };
  46. Clouds::Clouds() {
  47. params.resize(NUM_PARAMS);
  48. inputs.resize(NUM_INPUTS);
  49. outputs.resize(NUM_OUTPUTS);
  50. const int memLen = 118784;
  51. const int ccmLen = 65536 - 128;
  52. block_mem = new uint8_t[memLen]();
  53. block_ccm = new uint8_t[ccmLen]();
  54. processor = new clouds::GranularProcessor();
  55. memset(processor, 0, sizeof(*processor));
  56. processor->Init(block_mem, memLen, block_ccm, ccmLen);
  57. }
  58. Clouds::~Clouds() {
  59. delete processor;
  60. delete[] block_mem;
  61. delete[] block_ccm;
  62. }
  63. void Clouds::step() {
  64. // Get input
  65. if (!inputBuffer.full()) {
  66. Frame<2> inputFrame;
  67. inputFrame.samples[0] = getf(inputs[IN_L_INPUT]) * params[IN_GAIN_PARAM] / 5.0;
  68. inputFrame.samples[1] = getf(inputs[IN_R_INPUT]) * params[IN_GAIN_PARAM] / 5.0;
  69. inputBuffer.push(inputFrame);
  70. }
  71. // Trigger
  72. if (getf(inputs[TRIG_INPUT]) >= 1.0) {
  73. triggered = true;
  74. }
  75. // Render frames
  76. if (outputBuffer.empty()) {
  77. clouds::ShortFrame input[32] = {};
  78. // Convert input buffer
  79. {
  80. inputSrc.setRatio(32000.0 / gSampleRate);
  81. Frame<2> inputFrames[32];
  82. int inLen = inputBuffer.size();
  83. int outLen = 32;
  84. inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen);
  85. inputBuffer.startIncr(inLen);
  86. // We might not fill all of the input buffer if there is a deficiency, but this cannot be avoided due to imprecisions between the input and output SRC.
  87. for (int i = 0; i < outLen; i++) {
  88. input[i].l = clampf(inputFrames[i].samples[0] * 32767.0, -32768, 32767);
  89. input[i].r = clampf(inputFrames[i].samples[1] * 32767.0, -32768, 32767);
  90. }
  91. }
  92. // Set up processor
  93. processor->set_num_channels(2);
  94. processor->set_low_fidelity(false);
  95. // TODO Support the other modes
  96. processor->set_playback_mode(clouds::PLAYBACK_MODE_GRANULAR);
  97. processor->Prepare();
  98. clouds::Parameters* p = processor->mutable_parameters();
  99. p->trigger = triggered;
  100. p->gate = triggered;
  101. p->freeze = (getf(inputs[FREEZE_INPUT]) >= 1.0);
  102. p->position = clampf(params[POSITION_PARAM] + getf(inputs[POSITION_INPUT]) / 5.0, 0.0, 1.0);
  103. p->size = clampf(params[SIZE_PARAM] + getf(inputs[SIZE_INPUT]) / 5.0, 0.0, 1.0);
  104. p->pitch = clampf((params[PITCH_PARAM] + getf(inputs[PITCH_INPUT])) * 12.0, -48.0, 48.0);
  105. p->density = clampf(params[DENSITY_PARAM] + getf(inputs[DENSITY_INPUT]) / 5.0, 0.0, 1.0);
  106. p->texture = clampf(params[TEXTURE_PARAM] + getf(inputs[TEXTURE_INPUT]) / 5.0, 0.0, 1.0);
  107. float blend = clampf(params[BLEND_PARAM] + getf(inputs[BLEND_INPUT]) / 5.0, 0.0, 1.0);
  108. p->dry_wet = blend;
  109. p->stereo_spread = 0.0;
  110. p->feedback = 0.0;
  111. p->reverb = 0.0;
  112. clouds::ShortFrame output[32];
  113. processor->Process(input, output, 32);
  114. // Convert output buffer
  115. {
  116. Frame<2> outputFrames[32];
  117. for (int i = 0; i < 32; i++) {
  118. outputFrames[i].samples[0] = output[i].l / 32768.0;
  119. outputFrames[i].samples[1] = output[i].r / 32768.0;
  120. }
  121. outputSrc.setRatio(gSampleRate / 32000.0);
  122. int inLen = 32;
  123. int outLen = outputBuffer.capacity();
  124. outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen);
  125. outputBuffer.endIncr(outLen);
  126. }
  127. triggered = false;
  128. }
  129. // Set output
  130. if (!outputBuffer.empty()) {
  131. Frame<2> outputFrame = outputBuffer.shift();
  132. setf(outputs[OUT_L_OUTPUT], 5.0 * outputFrame.samples[0]);
  133. setf(outputs[OUT_R_OUTPUT], 5.0 * outputFrame.samples[1]);
  134. }
  135. }
  136. CloudsWidget::CloudsWidget() {
  137. Clouds *module = new Clouds();
  138. setModule(module);
  139. box.size = Vec(15*18, 380);
  140. {
  141. Panel *panel = new LightPanel();
  142. panel->backgroundImage = Image::load(assetPlugin(plugin, "res/Clouds.png"));
  143. panel->box.size = box.size;
  144. addChild(panel);
  145. }
  146. addChild(createScrew<ScrewSilver>(Vec(15, 0)));
  147. addChild(createScrew<ScrewSilver>(Vec(240, 0)));
  148. addChild(createScrew<ScrewSilver>(Vec(15, 365)));
  149. addChild(createScrew<ScrewSilver>(Vec(240, 365)));
  150. // TODO
  151. // addParam(createParam<MediumMomentarySwitch>(Vec(211, 51), module, Clouds::POSITION_PARAM, 0.0, 1.0, 0.5));
  152. // addParam(createParam<MediumMomentarySwitch>(Vec(239, 51), module, Clouds::POSITION_PARAM, 0.0, 1.0, 0.5));
  153. addParam(createParam<Rogan3PSRed>(Vec(28, 94), module, Clouds::POSITION_PARAM, 0.0, 1.0, 0.5));
  154. addParam(createParam<Rogan3PSGreen>(Vec(109, 94), module, Clouds::SIZE_PARAM, 0.0, 1.0, 0.5));
  155. addParam(createParam<Rogan3PSWhite>(Vec(191, 94), module, Clouds::PITCH_PARAM, -2.0, 2.0, 0.0));
  156. addParam(createParam<Rogan1PSRed>(Vec(15, 181), module, Clouds::IN_GAIN_PARAM, 0.0, 1.0, 0.5));
  157. addParam(createParam<Rogan1PSRed>(Vec(82, 181), module, Clouds::DENSITY_PARAM, 0.0, 1.0, 0.5));
  158. addParam(createParam<Rogan1PSGreen>(Vec(147, 181), module, Clouds::TEXTURE_PARAM, 0.0, 1.0, 0.5));
  159. addParam(createParam<Rogan1PSWhite>(Vec(214, 181), module, Clouds::BLEND_PARAM, 0.0, 1.0, 0.5));
  160. addInput(createInput<PJ3410Port>(Vec(11, 270), module, Clouds::FREEZE_INPUT));
  161. addInput(createInput<PJ3410Port>(Vec(54, 270), module, Clouds::TRIG_INPUT));
  162. addInput(createInput<PJ3410Port>(Vec(97, 270), module, Clouds::POSITION_INPUT));
  163. addInput(createInput<PJ3410Port>(Vec(140, 270), module, Clouds::SIZE_INPUT));
  164. addInput(createInput<PJ3410Port>(Vec(184, 270), module, Clouds::PITCH_INPUT));
  165. addInput(createInput<PJ3410Port>(Vec(227, 270), module, Clouds::BLEND_INPUT));
  166. addInput(createInput<PJ3410Port>(Vec(11, 313), module, Clouds::IN_L_INPUT));
  167. addInput(createInput<PJ3410Port>(Vec(54, 313), module, Clouds::IN_R_INPUT));
  168. addInput(createInput<PJ3410Port>(Vec(97, 313), module, Clouds::DENSITY_INPUT));
  169. addInput(createInput<PJ3410Port>(Vec(140, 313), module, Clouds::TEXTURE_INPUT));
  170. addOutput(createOutput<PJ3410Port>(Vec(184, 313), module, Clouds::OUT_L_OUTPUT));
  171. addOutput(createOutput<PJ3410Port>(Vec(227, 313), module, Clouds::OUT_R_OUTPUT));
  172. }