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.

523 lines
18KB

  1. #include "RJModules.hpp"
  2. #include <iostream>
  3. #include <stdlib.h>
  4. #include <random>
  5. #include <cmath>
  6. #include "dsp/digital.hpp"
  7. #include "dsp/samplerate.hpp"
  8. #include "dsp/ringbuffer.hpp"
  9. #include "dsp/filter.hpp"
  10. namespace rack_plugin_RJModules {
  11. #define NUM_CHANNELS 10
  12. #define HISTORY_SIZE (1<<21)
  13. struct Buffers : Module {
  14. enum ParamIds {
  15. MUTE_PARAM,
  16. NUM_PARAMS = MUTE_PARAM + NUM_CHANNELS
  17. };
  18. enum InputIds {
  19. IN_INPUT,
  20. NUM_INPUTS = IN_INPUT + NUM_CHANNELS
  21. };
  22. enum OutputIds {
  23. OUT_OUTPUT,
  24. NUM_OUTPUTS = OUT_OUTPUT + NUM_CHANNELS
  25. };
  26. enum LightIds {
  27. MUTE_LIGHT,
  28. NUM_LIGHTS = MUTE_LIGHT + NUM_CHANNELS
  29. };
  30. bool state[NUM_CHANNELS];
  31. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer;
  32. DoubleRingBuffer<float, 16> outBuffer;
  33. SampleRateConverter<1> src;
  34. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer10;
  35. DoubleRingBuffer<float, 16> outBuffer10;
  36. SampleRateConverter<1> src10;
  37. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer2;
  38. DoubleRingBuffer<float, 16> outBuffer2;
  39. SampleRateConverter<1> src2;
  40. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer3;
  41. DoubleRingBuffer<float, 16> outBuffer3;
  42. SampleRateConverter<1> src3;
  43. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer4;
  44. DoubleRingBuffer<float, 16> outBuffer4;
  45. SampleRateConverter<1> src4;
  46. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer5;
  47. DoubleRingBuffer<float, 16> outBuffer5;
  48. SampleRateConverter<1> src5;
  49. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer6;
  50. DoubleRingBuffer<float, 16> outBuffer6;
  51. SampleRateConverter<1> src6;
  52. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer7;
  53. DoubleRingBuffer<float, 16> outBuffer7;
  54. SampleRateConverter<1> src7;
  55. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer8;
  56. DoubleRingBuffer<float, 16> outBuffer8;
  57. SampleRateConverter<1> src8;
  58. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer9;
  59. DoubleRingBuffer<float, 16> outBuffer9;
  60. SampleRateConverter<1> src9;
  61. Buffers() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  62. reset();
  63. }
  64. void step() override;
  65. void reset() override {
  66. for (int i = 0; i < NUM_CHANNELS; i++) {
  67. state[i] = true;
  68. }
  69. }
  70. void randomize() override {
  71. for (int i = 0; i < NUM_CHANNELS; i++) {
  72. state[i] = (randomUniform() < 0.5);
  73. }
  74. }
  75. json_t *toJson() override {
  76. json_t *rootJ = json_object();
  77. // states
  78. json_t *statesJ = json_array();
  79. for (int i = 0; i < NUM_CHANNELS; i++) {
  80. json_t *stateJ = json_boolean(state[i]);
  81. json_array_append_new(statesJ, stateJ);
  82. }
  83. json_object_set_new(rootJ, "states", statesJ);
  84. return rootJ;
  85. }
  86. void fromJson(json_t *rootJ) override {
  87. // states
  88. json_t *statesJ = json_object_get(rootJ, "states");
  89. if (statesJ) {
  90. for (int i = 0; i < NUM_CHANNELS; i++) {
  91. json_t *stateJ = json_array_get(statesJ, i);
  92. if (stateJ)
  93. state[i] = json_boolean_value(stateJ);
  94. }
  95. }
  96. }
  97. };
  98. void Buffers::step() {
  99. for (int i = 0; i < NUM_CHANNELS; i++) {
  100. float in = inputs[IN_INPUT + i].value;
  101. outputs[OUT_OUTPUT + i].value = in + round(params[MUTE_PARAM + i].value);
  102. }
  103. int outFrames = outBuffer.capacity();
  104. double ratio = 1.0;
  105. float inSR = engineGetSampleRate();
  106. float outSR = ratio * inSR;
  107. int inFrames = min(historyBuffer.size(), 16);
  108. /*
  109. Oh god I'm so sorry I'm just so lazy right now
  110. Don't judge me on this, just send a PR
  111. */
  112. /*
  113. 1
  114. */
  115. float in = inputs[IN_INPUT].value;
  116. // Compute delay time in seconds
  117. float delay = .01 * params[MUTE_PARAM].value;
  118. // Number of delay samples
  119. float index = delay * engineGetSampleRate();
  120. if (!historyBuffer.full()) {
  121. historyBuffer.push(in);
  122. }
  123. // How many samples do we need consume to catch up?
  124. float consume = index - historyBuffer.size();
  125. if (outBuffer.empty()) {
  126. ratio = 1.0;
  127. if (consume <= -16)
  128. ratio = 0.5;
  129. else if (consume >= 16)
  130. ratio = 2.0;
  131. inSR = engineGetSampleRate();
  132. outSR = ratio * inSR;
  133. inFrames = min(historyBuffer.size(), 16);
  134. outFrames = outBuffer.capacity();
  135. src.setRates(inSR, outSR);
  136. src.process((const Frame<1>*)historyBuffer.startData(), &inFrames, (Frame<1>*)outBuffer.endData(), &outFrames);
  137. historyBuffer.startIncr(inFrames);
  138. outBuffer.endIncr(outFrames);
  139. }
  140. float wet = 0.0;
  141. if (!outBuffer.empty()) {
  142. wet = outBuffer.shift();
  143. }
  144. outputs[OUT_OUTPUT].value = wet;
  145. /*
  146. 2
  147. */
  148. in = inputs[IN_INPUT + 1].value;
  149. // Compute delay time in seconds
  150. delay = .01 * params[MUTE_PARAM + 1].value;
  151. // Number of delay samples
  152. index = delay * engineGetSampleRate();
  153. if (!historyBuffer2.full()) {
  154. historyBuffer2.push(in);
  155. }
  156. // How many samples do we need consume to catch up?
  157. consume = index - historyBuffer2.size();
  158. if (outBuffer2.empty()) {
  159. ratio = 1.0;
  160. if (consume <= -16)
  161. ratio = 0.5;
  162. else if (consume >= 16)
  163. ratio = 2.0;
  164. outSR = ratio * inSR;
  165. inFrames = min(historyBuffer2.size(), 16);
  166. outFrames = outBuffer2.capacity();
  167. src.setRates(inSR, outSR);
  168. src.process((const Frame<1>*)historyBuffer2.startData(), &inFrames, (Frame<1>*)outBuffer2.endData(), &outFrames);
  169. historyBuffer2.startIncr(inFrames);
  170. outBuffer2.endIncr(outFrames);
  171. }
  172. wet = 0.0;
  173. if (!outBuffer2.empty()) {
  174. wet = outBuffer2.shift();
  175. }
  176. outputs[OUT_OUTPUT+1].value = wet;
  177. /*
  178. 3
  179. */
  180. in = inputs[IN_INPUT + 2].value;
  181. // Compute delay time in seconds
  182. delay = .01 * params[MUTE_PARAM + 2].value;
  183. // Number of delay samples
  184. index = delay * engineGetSampleRate();
  185. if (!historyBuffer3.full()) {
  186. historyBuffer3.push(in);
  187. }
  188. // How many samples do we need consume to catch up?
  189. consume = index - historyBuffer3.size();
  190. if (outBuffer3.empty()) {
  191. ratio = 1.0;
  192. if (consume <= -16)
  193. ratio = 0.5;
  194. else if (consume >= 16)
  195. ratio = 2.0;
  196. outSR = ratio * inSR;
  197. inFrames = min(historyBuffer3.size(), 16);
  198. outFrames = outBuffer3.capacity();
  199. src.setRates(inSR, outSR);
  200. src.process((const Frame<1>*)historyBuffer3.startData(), &inFrames, (Frame<1>*)outBuffer3.endData(), &outFrames);
  201. historyBuffer3.startIncr(inFrames);
  202. outBuffer3.endIncr(outFrames);
  203. }
  204. wet = 0.0;
  205. if (!outBuffer3.empty()) {
  206. wet = outBuffer3.shift();
  207. }
  208. outputs[OUT_OUTPUT+2].value = wet;
  209. /*
  210. 4
  211. */
  212. in = inputs[IN_INPUT + 3].value;
  213. // Compute delay time in seconds
  214. delay = .01 * params[MUTE_PARAM + 3].value;
  215. // Number of delay samples
  216. index = delay * engineGetSampleRate();
  217. if (!historyBuffer4.full()) {
  218. historyBuffer4.push(in);
  219. }
  220. // How many samples do we need consume to catch up?
  221. consume = index - historyBuffer4.size();
  222. if (outBuffer4.empty()) {
  223. ratio = 1.0;
  224. if (consume <= -16)
  225. ratio = 0.5;
  226. else if (consume >= 16)
  227. ratio = 2.0;
  228. outSR = ratio * inSR;
  229. inFrames = min(historyBuffer4.size(), 16);
  230. outFrames = outBuffer4.capacity();
  231. src.setRates(inSR, outSR);
  232. src.process((const Frame<1>*)historyBuffer4.startData(), &inFrames, (Frame<1>*)outBuffer4.endData(), &outFrames);
  233. historyBuffer4.startIncr(inFrames);
  234. outBuffer4.endIncr(outFrames);
  235. }
  236. wet = 0.0;
  237. if (!outBuffer4.empty()) {
  238. wet = outBuffer4.shift();
  239. }
  240. outputs[OUT_OUTPUT+3].value = wet;
  241. /*
  242. 5
  243. */
  244. in = inputs[IN_INPUT + 4].value;
  245. // Compute delay time in seconds
  246. delay = .01 * params[MUTE_PARAM + 4].value;
  247. // Number of delay samples
  248. index = delay * engineGetSampleRate();
  249. if (!historyBuffer5.full()) {
  250. historyBuffer5.push(in);
  251. }
  252. // How many samples do we need consume to catch up?
  253. consume = index - historyBuffer5.size();
  254. if (outBuffer5.empty()) {
  255. ratio = 1.0;
  256. if (consume <= -16)
  257. ratio = 0.5;
  258. else if (consume >= 16)
  259. ratio = 2.0;
  260. outSR = ratio * inSR;
  261. inFrames = min(historyBuffer5.size(), 16);
  262. outFrames = outBuffer5.capacity();
  263. src.setRates(inSR, outSR);
  264. src.process((const Frame<1>*)historyBuffer5.startData(), &inFrames, (Frame<1>*)outBuffer5.endData(), &outFrames);
  265. historyBuffer5.startIncr(inFrames);
  266. outBuffer5.endIncr(outFrames);
  267. }
  268. wet = 0.0;
  269. if (!outBuffer5.empty()) {
  270. wet = outBuffer5.shift();
  271. }
  272. outputs[OUT_OUTPUT+4].value = wet;
  273. /*
  274. 6
  275. */
  276. in = inputs[IN_INPUT + 5].value;
  277. // Compute delay time in seconds
  278. delay = .01 * params[MUTE_PARAM + 5].value;
  279. // Number of delay samples
  280. index = delay * engineGetSampleRate();
  281. if (!historyBuffer6.full()) {
  282. historyBuffer6.push(in);
  283. }
  284. // How many samples do we need consume to catch up?
  285. consume = index - historyBuffer6.size();
  286. if (outBuffer6.empty()) {
  287. ratio = 1.0;
  288. if (consume <= -16)
  289. ratio = 0.5;
  290. else if (consume >= 16)
  291. ratio = 2.0;
  292. outSR = ratio * inSR;
  293. inFrames = min(historyBuffer6.size(), 16);
  294. outFrames = outBuffer6.capacity();
  295. src.setRates(inSR, outSR);
  296. src.process((const Frame<1>*)historyBuffer6.startData(), &inFrames, (Frame<1>*)outBuffer6.endData(), &outFrames);
  297. historyBuffer6.startIncr(inFrames);
  298. outBuffer6.endIncr(outFrames);
  299. }
  300. wet = 0.0;
  301. if (!outBuffer6.empty()) {
  302. wet = outBuffer6.shift();
  303. }
  304. outputs[OUT_OUTPUT+5].value = wet;
  305. /*
  306. 7
  307. */
  308. in = inputs[IN_INPUT + 6].value;
  309. // Compute delay time in seconds
  310. delay = .01 * params[MUTE_PARAM + 6].value;
  311. // Number of delay samples
  312. index = delay * engineGetSampleRate();
  313. if (!historyBuffer7.full()) {
  314. historyBuffer7.push(in);
  315. }
  316. // How many samples do we need consume to catch up?
  317. consume = index - historyBuffer7.size();
  318. if (outBuffer7.empty()) {
  319. ratio = 1.0;
  320. if (consume <= -16)
  321. ratio = 0.5;
  322. else if (consume >= 16)
  323. ratio = 2.0;
  324. outSR = ratio * inSR;
  325. inFrames = min(historyBuffer7.size(), 16);
  326. outFrames = outBuffer7.capacity();
  327. src.setRates(inSR, outSR);
  328. src.process((const Frame<1>*)historyBuffer7.startData(), &inFrames, (Frame<1>*)outBuffer7.endData(), &outFrames);
  329. historyBuffer7.startIncr(inFrames);
  330. outBuffer7.endIncr(outFrames);
  331. }
  332. wet = 0.0;
  333. if (!outBuffer7.empty()) {
  334. wet = outBuffer7.shift();
  335. }
  336. outputs[OUT_OUTPUT+6].value = wet;
  337. /*
  338. 8
  339. */
  340. in = inputs[IN_INPUT + 7].value;
  341. // Compute delay time in seconds
  342. delay = .01 * params[MUTE_PARAM + 7].value;
  343. // Number of delay samples
  344. index = delay * engineGetSampleRate();
  345. if (!historyBuffer8.full()) {
  346. historyBuffer8.push(in);
  347. }
  348. // How many samples do we need consume to catch up?
  349. consume = index - historyBuffer8.size();
  350. if (outBuffer8.empty()) {
  351. ratio = 1.0;
  352. if (consume <= -16)
  353. ratio = 0.5;
  354. else if (consume >= 16)
  355. ratio = 2.0;
  356. outSR = ratio * inSR;
  357. inFrames = min(historyBuffer8.size(), 16);
  358. outFrames = outBuffer8.capacity();
  359. src.setRates(inSR, outSR);
  360. src.process((const Frame<1>*)historyBuffer8.startData(), &inFrames, (Frame<1>*)outBuffer8.endData(), &outFrames);
  361. historyBuffer8.startIncr(inFrames);
  362. outBuffer8.endIncr(outFrames);
  363. }
  364. wet = 0.0;
  365. if (!outBuffer8.empty()) {
  366. wet = outBuffer8.shift();
  367. }
  368. outputs[OUT_OUTPUT+7].value = wet;
  369. /*
  370. 9
  371. */
  372. in = inputs[IN_INPUT + 8].value;
  373. // Compute delay time in seconds
  374. delay = .01 * params[MUTE_PARAM + 8].value;
  375. // Number of delay samples
  376. index = delay * engineGetSampleRate();
  377. if (!historyBuffer9.full()) {
  378. historyBuffer9.push(in);
  379. }
  380. // How many samples do we need consume to catch up?
  381. consume = index - historyBuffer9.size();
  382. if (outBuffer9.empty()) {
  383. ratio = 1.0;
  384. if (consume <= -16)
  385. ratio = 0.5;
  386. else if (consume >= 16)
  387. ratio = 2.0;
  388. outSR = ratio * inSR;
  389. inFrames = min(historyBuffer9.size(), 16);
  390. outFrames = outBuffer9.capacity();
  391. src.setRates(inSR, outSR);
  392. src.process((const Frame<1>*)historyBuffer9.startData(), &inFrames, (Frame<1>*)outBuffer9.endData(), &outFrames);
  393. historyBuffer9.startIncr(inFrames);
  394. outBuffer9.endIncr(outFrames);
  395. }
  396. wet = 0.0;
  397. if (!outBuffer9.empty()) {
  398. wet = outBuffer9.shift();
  399. }
  400. outputs[OUT_OUTPUT+8].value = wet;
  401. /*
  402. 10
  403. */
  404. in = inputs[IN_INPUT + 9].value;
  405. // Compute delay time in seconds
  406. delay = .01 * params[MUTE_PARAM + 9].value;
  407. // Number of delay samples
  408. index = delay * engineGetSampleRate();
  409. if (!historyBuffer10.full()) {
  410. historyBuffer10.push(in);
  411. }
  412. // How many samples do we need consume to catch up?
  413. consume = index - historyBuffer10.size();
  414. if (outBuffer10.empty()) {
  415. ratio = 1.0;
  416. if (consume <= -16)
  417. ratio = 0.5;
  418. else if (consume >= 16)
  419. ratio = 2.0;
  420. outSR = ratio * inSR;
  421. inFrames = min(historyBuffer10.size(), 16);
  422. outFrames = outBuffer10.capacity();
  423. src.setRates(inSR, outSR);
  424. src.process((const Frame<1>*)historyBuffer10.startData(), &inFrames, (Frame<1>*)outBuffer10.endData(), &outFrames);
  425. historyBuffer10.startIncr(inFrames);
  426. outBuffer10.endIncr(outFrames);
  427. }
  428. wet = 0.0;
  429. if (!outBuffer10.empty()) {
  430. wet = outBuffer10.shift();
  431. }
  432. outputs[OUT_OUTPUT+9].value = wet;
  433. }
  434. template <typename BASE>
  435. struct MuteLight : BASE {
  436. MuteLight() {
  437. this->box.size = mm2px(Vec(6.0, 6.0));
  438. }
  439. };
  440. struct BuffersWidget: ModuleWidget {
  441. BuffersWidget(Buffers *module);
  442. };
  443. BuffersWidget::BuffersWidget(Buffers *module) : ModuleWidget(module) {
  444. setPanel(SVG::load(assetPlugin(plugin, "res/Buffers.svg")));
  445. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  446. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  447. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  448. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  449. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 17.165)), module, Buffers::MUTE_PARAM + 0, 0.0, 3.6, 0.0));
  450. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 27.164)), module, Buffers::MUTE_PARAM + 1, 0.0, 3.6, 0.0));
  451. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 37.164)), module, Buffers::MUTE_PARAM + 2, 0.0, 3.6, 0.0));
  452. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 47.165)), module, Buffers::MUTE_PARAM + 3, 0.0, 3.6, 0.0));
  453. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 57.164)), module, Buffers::MUTE_PARAM + 4, 0.0, 3.6, 0.0));
  454. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 67.165)), module, Buffers::MUTE_PARAM + 5, 0.0, 2.6, 0.0));
  455. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 77.164)), module, Buffers::MUTE_PARAM + 6, 0.0, 3.6, 0.0));
  456. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 87.164)), module, Buffers::MUTE_PARAM + 7, 0.0, 3.6, 0.0));
  457. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 97.165)), module, Buffers::MUTE_PARAM + 8, 0.0, 3.6, 0.0));
  458. addParam(ParamWidget::create<RoundSmallBlackKnob>(mm2px(Vec(16.57, 107.166)), module, Buffers::MUTE_PARAM + 9, 0.0, 3.6, 0.0));
  459. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 17.81)), Port::INPUT, module, Buffers::IN_INPUT + 0));
  460. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 27.809)), Port::INPUT, module, Buffers::IN_INPUT + 1));
  461. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 37.809)), Port::INPUT, module, Buffers::IN_INPUT + 2));
  462. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 47.81)), Port::INPUT, module, Buffers::IN_INPUT + 3));
  463. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 57.81)), Port::INPUT, module, Buffers::IN_INPUT + 4));
  464. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 67.809)), Port::INPUT, module, Buffers::IN_INPUT + 5));
  465. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 77.81)), Port::INPUT, module, Buffers::IN_INPUT + 6));
  466. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 87.81)), Port::INPUT, module, Buffers::IN_INPUT + 7));
  467. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 97.809)), Port::INPUT, module, Buffers::IN_INPUT + 8));
  468. addInput(Port::create<PJ301MPort>(mm2px(Vec(4.214, 107.809)), Port::INPUT, module, Buffers::IN_INPUT + 9));
  469. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 17.81)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 0));
  470. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 27.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 1));
  471. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 37.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 2));
  472. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 47.81)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 3));
  473. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 57.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 4));
  474. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 67.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 5));
  475. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 77.81)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 6));
  476. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 87.81)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 7));
  477. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 97.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 8));
  478. addOutput(Port::create<PJ301MPort>(mm2px(Vec(28.214, 107.809)), Port::OUTPUT, module, Buffers::OUT_OUTPUT + 9));
  479. }
  480. } // namespace rack_plugin_RJModules
  481. using namespace rack_plugin_RJModules;
  482. RACK_PLUGIN_MODEL_INIT(RJModules, Buffers) {
  483. Model *modelBuffers = Model::create<Buffers, BuffersWidget>("RJModules", "Buffers", "[UTIL] Buffers", UTILITY_TAG);
  484. return modelBuffers;
  485. }