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.

237 lines
5.6KB

  1. #include <string.h>
  2. #include "AudibleInstruments.hpp"
  3. #include "dsp.hpp"
  4. #include "braids/macro_oscillator.h"
  5. struct Braids : Module {
  6. enum ParamIds {
  7. FINE_PARAM,
  8. COARSE_PARAM,
  9. FM_PARAM,
  10. TIMBRE_PARAM,
  11. MODULATION_PARAM,
  12. COLOR_PARAM,
  13. SHAPE_PARAM,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. TRIG_INPUT,
  18. PITCH_INPUT,
  19. FM_INPUT,
  20. TIMBRE_INPUT,
  21. COLOR_INPUT,
  22. NUM_INPUTS
  23. };
  24. enum OutputIds {
  25. OUT_OUTPUT,
  26. NUM_OUTPUTS
  27. };
  28. braids::MacroOscillator *osc;
  29. SampleRateConverter<1> src;
  30. DoubleRingBuffer<Frame<1>, 256> outputBuffer;
  31. bool lastTrig = false;
  32. Braids();
  33. ~Braids();
  34. void step();
  35. void setShape(int shape);
  36. };
  37. Braids::Braids() {
  38. params.resize(NUM_PARAMS);
  39. inputs.resize(NUM_INPUTS);
  40. outputs.resize(NUM_OUTPUTS);
  41. osc = new braids::MacroOscillator();
  42. memset(osc, 0, sizeof(*osc));
  43. osc->Init();
  44. }
  45. Braids::~Braids() {
  46. delete osc;
  47. }
  48. void Braids::step() {
  49. // Trigger
  50. bool trig = getf(inputs[TRIG_INPUT]) >= 1.0;
  51. if (!lastTrig && trig) {
  52. osc->Strike();
  53. }
  54. lastTrig = trig;
  55. // Render frames
  56. if (outputBuffer.empty()) {
  57. // Set shape
  58. int shape = roundf(params[SHAPE_PARAM]);
  59. osc->set_shape((braids::MacroOscillatorShape) shape);
  60. // Set timbre/modulation
  61. float timbre = params[TIMBRE_PARAM] + params[MODULATION_PARAM] * getf(inputs[TIMBRE_INPUT]) / 5.0;
  62. float modulation = params[COLOR_PARAM] + getf(inputs[COLOR_INPUT]) / 5.0;
  63. int16_t param1 = mapf(clampf(timbre, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX);
  64. int16_t param2 = mapf(clampf(modulation, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX);
  65. osc->set_parameters(param1, param2);
  66. // Set pitch
  67. float pitch = getf(inputs[PITCH_INPUT]) + params[COARSE_PARAM] + params[FINE_PARAM] / 12.0 + params[FM_PARAM] * getf(inputs[FM_INPUT]);
  68. int16_t p = clampf((pitch * 12.0 + 60) * 128, 0, INT16_MAX);
  69. osc->set_pitch(p);
  70. // TODO: add a sync input buffer (must be sample rate converted)
  71. uint8_t sync_buffer[24] = {};
  72. int16_t render_buffer[24];
  73. osc->Render(sync_buffer, render_buffer, 24);
  74. // Sample rate convert
  75. Frame<1> in[24];
  76. for (int i = 0; i < 24; i++) {
  77. in[i].samples[0] = render_buffer[i] / 32768.0;
  78. }
  79. src.setRatio(gSampleRate / 96000.0);
  80. int inLen = 24;
  81. int outLen = outputBuffer.capacity();
  82. src.process(in, &inLen, outputBuffer.endData(), &outLen);
  83. outputBuffer.endIncr(outLen);
  84. }
  85. // Output
  86. if (!outputBuffer.empty()) {
  87. Frame<1> f = outputBuffer.shift();
  88. setf(outputs[OUT_OUTPUT], 5.0 * f.samples[0]);
  89. }
  90. }
  91. static const char *algo_values[] = {
  92. "CSAW",
  93. "/\\-_",
  94. "//-_",
  95. "FOLD",
  96. "uuuu",
  97. "SYN-",
  98. "SYN/",
  99. "//x3",
  100. "-_x3",
  101. "/\\x3",
  102. "SIx3",
  103. "RING",
  104. "////",
  105. "//uu",
  106. "TOY*",
  107. "ZLPF",
  108. "ZPKF",
  109. "ZBPF",
  110. "ZHPF",
  111. "VOSM",
  112. "VOWL",
  113. "VFOF",
  114. "HARM",
  115. "FM ",
  116. "FBFM",
  117. "WTFM",
  118. "PLUK",
  119. "BOWD",
  120. "BLOW",
  121. "FLUT",
  122. "BELL",
  123. "DRUM",
  124. "KICK",
  125. "CYMB",
  126. "SNAR",
  127. "WTBL",
  128. "WMAP",
  129. "WLIN",
  130. "WTx4",
  131. "NOIS",
  132. "TWNQ",
  133. "CLKN",
  134. "CLOU",
  135. "PRTC",
  136. "QPSK",
  137. " ",
  138. };
  139. struct BraidsDisplay : TransparentWidget {
  140. float *value;
  141. std::shared_ptr<Font> font;
  142. BraidsDisplay() {
  143. font = Font::load("plugins/AudibleInstruments/res/hdad-segment14-1.002/Segment14.ttf");
  144. }
  145. void draw(NVGcontext *vg) {
  146. int shape = roundf(getf(value));
  147. // Background
  148. NVGcolor backgroundColor = nvgRGB(0x38, 0x38, 0x38);
  149. NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
  150. nvgBeginPath(vg);
  151. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 5.0);
  152. nvgFillColor(vg, backgroundColor);
  153. nvgFill(vg);
  154. nvgStrokeWidth(vg, 1.0);
  155. nvgStrokeColor(vg, borderColor);
  156. nvgStroke(vg);
  157. nvgFontSize(vg, 36);
  158. nvgFontFaceId(vg, font->handle);
  159. nvgTextLetterSpacing(vg, 2.5);
  160. Vec textPos = Vec(10, 48);
  161. NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c);
  162. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  163. nvgText(vg, textPos.x, textPos.y, "~~~~", NULL);
  164. nvgFillColor(vg, textColor);
  165. nvgText(vg, textPos.x, textPos.y, algo_values[shape], NULL);
  166. }
  167. };
  168. BraidsWidget::BraidsWidget() {
  169. Braids *module = new Braids();
  170. setModule(module);
  171. box.size = Vec(15*16, 380);
  172. {
  173. Panel *panel = new LightPanel();
  174. panel->backgroundImage = Image::load("plugins/AudibleInstruments/res/Braids.png");
  175. panel->box.size = box.size;
  176. addChild(panel);
  177. }
  178. {
  179. BraidsDisplay *display = new BraidsDisplay();
  180. display->box.pos = Vec(14, 53);
  181. display->box.size = Vec(148, 56);
  182. display->value = &module->params[Braids::SHAPE_PARAM];
  183. addChild(display);
  184. }
  185. addChild(createScrew<ScrewSilver>(Vec(15, 0)));
  186. addChild(createScrew<ScrewSilver>(Vec(210, 0)));
  187. addChild(createScrew<ScrewSilver>(Vec(15, 365)));
  188. addChild(createScrew<ScrewSilver>(Vec(210, 365)));
  189. addParam(createParam<Rogan2SGray>(Vec(177, 60), module, Braids::SHAPE_PARAM, 0.0, braids::MACRO_OSC_SHAPE_LAST-2, 0.0));
  190. addParam(createParam<Rogan2PSWhite>(Vec(20, 139), module, Braids::FINE_PARAM, -1.0, 1.0, 0.0));
  191. addParam(createParam<Rogan2PSWhite>(Vec(98, 139), module, Braids::COARSE_PARAM, -2.0, 2.0, 0.0));
  192. addParam(createParam<Rogan2PSWhite>(Vec(177, 139), module, Braids::FM_PARAM, -1.0, 1.0, 0.0));
  193. addParam(createParam<Rogan2PSGreen>(Vec(20, 218), module, Braids::TIMBRE_PARAM, 0.0, 1.0, 0.5));
  194. addParam(createParam<Rogan2PSGreen>(Vec(98, 218), module, Braids::MODULATION_PARAM, -1.0, 1.0, 0.0));
  195. addParam(createParam<Rogan2PSRed>(Vec(177, 218), module, Braids::COLOR_PARAM, 0.0, 1.0, 0.5));
  196. addInput(createInput<PJ3410Port>(Vec(7, 313), module, Braids::TRIG_INPUT));
  197. addInput(createInput<PJ3410Port>(Vec(45, 313), module, Braids::PITCH_INPUT));
  198. addInput(createInput<PJ3410Port>(Vec(82, 313), module, Braids::FM_INPUT));
  199. addInput(createInput<PJ3410Port>(Vec(120, 313), module, Braids::TIMBRE_INPUT));
  200. addInput(createInput<PJ3410Port>(Vec(157, 313), module, Braids::COLOR_INPUT));
  201. addOutput(createOutput<PJ3410Port>(Vec(202, 313), module, Braids::OUT_OUTPUT));
  202. }