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.

423 lines
14KB

  1. #include "Bidoo.hpp"
  2. #include "BidooComponents.hpp"
  3. #include "dsp/digital.hpp"
  4. #include <iomanip>
  5. #include <sstream>
  6. #include "window.hpp"
  7. using namespace std;
  8. namespace rack_plugin_Bidoo {
  9. struct ACNE : Module {
  10. enum ParamIds {
  11. COPY_PARAM,
  12. MAIN_OUT_GAIN_PARAM,
  13. RAMP_PARAM,
  14. MUTE_PARAM,
  15. SOLO_PARAM,
  16. SEND_MUTE_PARAM,
  17. TRACKLINK_PARAMS,
  18. OUT_MUTE_PARAMS = TRACKLINK_PARAMS + 8,
  19. IN_MUTE_PARAMS = OUT_MUTE_PARAMS + ACNE_NB_OUTS,
  20. IN_SOLO_PARAMS = IN_MUTE_PARAMS + ACNE_NB_TRACKS,
  21. SNAPSHOT_PARAMS = IN_SOLO_PARAMS + ACNE_NB_TRACKS,
  22. FADERS_PARAMS = SNAPSHOT_PARAMS + ACNE_NB_SNAPSHOTS,
  23. NUM_PARAMS = FADERS_PARAMS + (ACNE_NB_TRACKS * ACNE_NB_OUTS)
  24. };
  25. enum InputIds {
  26. SNAPSHOT_INPUT,
  27. TRACKS_INPUTS,
  28. NUM_INPUTS = TRACKS_INPUTS + ACNE_NB_TRACKS
  29. };
  30. enum OutputIds {
  31. TRACKS_OUTPUTS,
  32. NUM_OUTPUTS = TRACKS_OUTPUTS + ACNE_NB_OUTS
  33. };
  34. enum LightIds {
  35. COPY_LIGHT,
  36. TRACKLINK_LIGHTS,
  37. OUT_MUTE_LIGHTS = TRACKLINK_LIGHTS + 8,
  38. IN_MUTE_LIGHTS = OUT_MUTE_LIGHTS + ACNE_NB_OUTS,
  39. IN_SOLO_LIGHTS = IN_MUTE_LIGHTS + ACNE_NB_TRACKS,
  40. SNAPSHOT_LIGHTS = IN_SOLO_LIGHTS + ACNE_NB_TRACKS,
  41. NUM_LIGHTS = SNAPSHOT_LIGHTS + ACNE_NB_SNAPSHOTS
  42. };
  43. int currentSnapshot = 0;
  44. int previousSnapshot = 0;
  45. int copySnapshot = 0;
  46. bool copyState = false;
  47. float snapshots[ACNE_NB_SNAPSHOTS][ACNE_NB_OUTS][ACNE_NB_TRACKS] = {{{0.0f}}};
  48. bool outMutes[ACNE_NB_OUTS] = {0};
  49. bool inMutes[ACNE_NB_TRACKS] = {0};
  50. bool inSolo[ACNE_NB_TRACKS] = {0};
  51. SchmittTrigger outMutesTriggers[ACNE_NB_OUTS];
  52. SchmittTrigger inMutesTriggers[ACNE_NB_TRACKS];
  53. SchmittTrigger inSoloTriggers[ACNE_NB_TRACKS];
  54. SchmittTrigger snapshotTriggers[ACNE_NB_SNAPSHOTS];
  55. SchmittTrigger muteTrigger;
  56. SchmittTrigger soloTrigger;
  57. int rampSteps = 0;
  58. int rampSize = 1;
  59. float rampedValue = 0.0;
  60. int version = 0;
  61. SchmittTrigger linksTriggers[8];
  62. bool links[8] = {0,0,0,0,0,0,0,0};
  63. ACNE() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { }
  64. void step() override;
  65. json_t *toJson() override {
  66. json_t *rootJ = json_object();
  67. // scenes
  68. json_t *snapShotsJ = json_array();
  69. for (int i = 0; i < ACNE_NB_SNAPSHOTS; i++) {
  70. json_t *snapshotJ = json_array();
  71. for (int j = 0; j < ACNE_NB_OUTS; j++) {
  72. json_t *outJ = json_array();
  73. for (int k = 0 ; k < ACNE_NB_TRACKS; k ++) {
  74. json_t *controlJ = json_real(snapshots[i][j][k]);
  75. json_array_append_new(outJ, controlJ);
  76. }
  77. json_array_append_new(snapshotJ, outJ);
  78. }
  79. json_array_append_new(snapShotsJ, snapshotJ);
  80. }
  81. json_object_set_new(rootJ, "snapshots", snapShotsJ);
  82. for (int i = 0; i < 8; i++) {
  83. json_object_set_new(rootJ, ("link" + to_string(i)).c_str(), json_boolean(links[i]));
  84. }
  85. return rootJ;
  86. }
  87. void fromJson(json_t *rootJ) override {
  88. // scenes
  89. json_t *snapShotsJ = json_object_get(rootJ, "snapshots");
  90. if (snapShotsJ) {
  91. for (int i = 0; i < ACNE_NB_SNAPSHOTS; i++) {
  92. json_t *snapshotJ = json_array_get(snapShotsJ, i);
  93. if (snapshotJ) {
  94. for (int j = 0; j < ACNE_NB_OUTS; j++) {
  95. json_t *outJ = json_array_get(snapshotJ, j);
  96. if (outJ) {
  97. for (int k = 0; k < ACNE_NB_TRACKS; k++) {
  98. json_t *inJ = json_array_get(outJ, k);
  99. if (inJ) {
  100. snapshots[i][j][k] = json_number_value(inJ);
  101. }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. }
  108. for (int i = 0; i < 8; i++) {
  109. json_t *linkJ = json_object_get(rootJ, ("link" + to_string(i)).c_str());
  110. if (linkJ)
  111. links[i] = json_is_true(linkJ);
  112. }
  113. }
  114. float getRampedValue(int i, int j) {
  115. if (rampSize>0) {
  116. return crossfade(snapshots[currentSnapshot][i][j],snapshots[previousSnapshot][i][j],(float)rampSteps/(float)rampSize);
  117. }
  118. else {
  119. return snapshots[currentSnapshot][i][j];
  120. }
  121. }
  122. };
  123. void ACNE::step() {
  124. rampSize = static_cast<int>(engineGetSampleRate()*params[RAMP_PARAM].value);
  125. if (inputs[SNAPSHOT_INPUT].active) {
  126. int newSnapshot = clamp((int)(inputs[SNAPSHOT_INPUT].value * 16 * 0.1f),0,ACNE_NB_SNAPSHOTS-1);
  127. if (currentSnapshot != newSnapshot) {
  128. previousSnapshot = currentSnapshot;
  129. currentSnapshot = newSnapshot;
  130. rampSteps = rampSize;
  131. version = (version + 1)%100;
  132. }
  133. }
  134. else {
  135. for (int i = 0; i < ACNE_NB_SNAPSHOTS; i++) {
  136. if (snapshotTriggers[i].process(params[SNAPSHOT_PARAMS + i].value)) {
  137. previousSnapshot = currentSnapshot;
  138. currentSnapshot = i;
  139. rampSteps = rampSize;
  140. version = (version + 1)%100;
  141. }
  142. }
  143. }
  144. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  145. if (outMutesTriggers[i].process(params[OUT_MUTE_PARAMS + i].value)) {
  146. outMutes[i] = !outMutes[i];
  147. }
  148. }
  149. for (int i = 0; i < 8; i++) {
  150. if (linksTriggers[i].process(params[TRACKLINK_PARAMS + i].value))
  151. links[i] = !links[i];
  152. lights[TRACKLINK_LIGHTS + i].value = (links[i] == true) ? 1 : 0;
  153. }
  154. for (int i = 0; i < ACNE_NB_TRACKS; i++) {
  155. int linkIndex = i/2;
  156. int linkSwitch = i%2;
  157. if (inMutesTriggers[i].process(params[IN_MUTE_PARAMS + i].value)) {
  158. inMutes[i] = !inMutes[i];
  159. if (links[linkIndex]) {
  160. if (linkSwitch == 0)
  161. inMutes[i+1] = inMutes[i];
  162. else
  163. inMutes[i-1] = inMutes[i];
  164. }
  165. }
  166. if (inSoloTriggers[i].process(params[IN_SOLO_PARAMS + i].value)) {
  167. inSolo[i] = !inSolo[i];
  168. if (links[linkIndex]) {
  169. if (linkSwitch == 0)
  170. inSolo[i+1] = inSolo[i];
  171. else
  172. inSolo[i-1] = inSolo[i];
  173. }
  174. }
  175. }
  176. if (muteTrigger.process(params[MUTE_PARAM].value)) {
  177. for (int i = 0; i < ACNE_NB_TRACKS; i++) {
  178. inMutes[i] = false;
  179. }
  180. }
  181. if (muteTrigger.process(params[SEND_MUTE_PARAM].value)) {
  182. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  183. outMutes[i] = false;
  184. }
  185. }
  186. if (soloTrigger.process(params[SOLO_PARAM].value)) {
  187. for (int i = 0; i < ACNE_NB_TRACKS; i++) {
  188. inSolo[i] = false;
  189. }
  190. }
  191. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  192. outputs[TRACKS_OUTPUTS + i].value = 0.0f;
  193. if (!outMutes[i]) {
  194. int sum = 0;
  195. for (int s = 0; s < ACNE_NB_TRACKS; ++s) {
  196. sum |= (inSolo[s] == true ? 1 : 0);
  197. }
  198. if (sum > 0) {
  199. for (int j = 0; j < ACNE_NB_TRACKS; j ++) {
  200. if ((inputs[TRACKS_INPUTS + j].active) && (inSolo[j])) {
  201. outputs[TRACKS_OUTPUTS + i].value += (getRampedValue(i,j) * 0.1f) * inputs[TRACKS_INPUTS + j].value * 30517578125e-15f;
  202. }
  203. }
  204. }
  205. else {
  206. for (int j = 0; j < ACNE_NB_TRACKS; j ++) {
  207. if ((inputs[TRACKS_INPUTS + j].active) && (!inMutes[j])) {
  208. if (rampSize>0) {
  209. rampedValue = crossfade(snapshots[currentSnapshot][i][j],snapshots[previousSnapshot][i][j],(float)rampSteps/(float)rampSize);
  210. }
  211. else {
  212. rampedValue = snapshots[currentSnapshot][i][j];
  213. }
  214. outputs[TRACKS_OUTPUTS + i].value += (getRampedValue(i,j) * 0.1f) * inputs[TRACKS_INPUTS + j].value * 30517578125e-15f;
  215. }
  216. }
  217. }
  218. outputs[TRACKS_OUTPUTS + i].value = outputs[TRACKS_OUTPUTS + i].value * 32768.0f;
  219. }
  220. }
  221. if (rampSteps > 0)
  222. rampSteps--;
  223. outputs[TRACKS_OUTPUTS].value = outputs[TRACKS_OUTPUTS].value * params[MAIN_OUT_GAIN_PARAM].value * 0.1f;
  224. outputs[TRACKS_OUTPUTS + 1].value = outputs[TRACKS_OUTPUTS + 1].value * params[MAIN_OUT_GAIN_PARAM].value * 0.1f;
  225. lights[COPY_LIGHT].value = (copyState == true) ? 1 : 0;
  226. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  227. lights[OUT_MUTE_LIGHTS + i].value = (outMutes[i] == true) ? 1 : 0;
  228. }
  229. for (int i = 0; i < ACNE_NB_TRACKS; i++) {
  230. lights[IN_MUTE_LIGHTS + i].value = (inMutes[i] == true) ? 1 : 0;
  231. lights[IN_SOLO_LIGHTS + i].value = (inSolo[i] == true) ? 1 : 0;
  232. }
  233. for (int i = 0; i < ACNE_NB_SNAPSHOTS; i++) {
  234. lights[SNAPSHOT_LIGHTS + i].value = (i == currentSnapshot) ? 1 : 0;
  235. }
  236. }
  237. struct ACNEWidget : ModuleWidget {
  238. ParamWidget *faders[ACNE_NB_OUTS][ACNE_NB_TRACKS];
  239. void UpdateSnapshot(int snapshot);
  240. void step() override;
  241. int moduleVersion = 0;
  242. int frames=0;
  243. ACNEWidget(ACNE *module);
  244. };
  245. struct ACNETrimPot : BidooColoredTrimpot {
  246. void onChange(EventChange &e) override {
  247. ACNEWidget *parent = dynamic_cast<ACNEWidget*>(this->parent);
  248. ACNE *module = dynamic_cast<ACNE*>(this->module);
  249. if (parent && module) {
  250. module->snapshots[module->currentSnapshot][(int)((this->paramId - ACNE::FADERS_PARAMS) / ACNE_NB_TRACKS)][(this->paramId - ACNE::FADERS_PARAMS) % ACNE_NB_TRACKS] = value;
  251. }
  252. BidooColoredTrimpot::onChange(e);
  253. }
  254. virtual void onMouseDown(EventMouseDown &e) override {
  255. BidooColoredTrimpot::onMouseDown(e);
  256. ACNEWidget *parent = dynamic_cast<ACNEWidget*>(this->parent);
  257. ACNE *module = dynamic_cast<ACNE*>(this->module);
  258. if (parent && module) {
  259. if ((e.button == RACK_MOUSE_BUTTON_MIDDLE) || ((e.button == RACK_MOUSE_BUTTON_LEFT) && (windowIsShiftPressed()))) {
  260. this->setValue(10);
  261. module->snapshots[module->currentSnapshot][(int)((this->paramId - ACNE::FADERS_PARAMS) / ACNE_NB_TRACKS)][(this->paramId - ACNE::FADERS_PARAMS) % ACNE_NB_TRACKS] = 10;
  262. }
  263. }
  264. }
  265. };
  266. struct ACNEChoseSceneLedButton : LEDButton {
  267. void onMouseDown(EventMouseDown &e) override {
  268. ACNEWidget *parent = dynamic_cast<ACNEWidget*>(this->parent);
  269. ACNE *module = dynamic_cast<ACNE*>(this->module);
  270. if (parent && module) {
  271. module->currentSnapshot = this->paramId - ACNE::SNAPSHOT_PARAMS;
  272. parent->UpdateSnapshot(module->currentSnapshot);
  273. }
  274. LEDButton::onMouseDown(e);
  275. }
  276. };
  277. struct ACNECOPYPASTECKD6 : BlueCKD6 {
  278. void onMouseDown(EventMouseDown &e) override {
  279. ACNEWidget *parent = dynamic_cast<ACNEWidget*>(this->parent);
  280. ACNE *module = dynamic_cast<ACNE*>(this->module);
  281. if (parent && module) {
  282. if (!module->copyState) {
  283. module->copySnapshot = module->currentSnapshot;
  284. module->copyState = true;
  285. } else if ((module->copyState) && (module->copySnapshot != module->currentSnapshot)) {
  286. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  287. for (int j = 0; j < ACNE_NB_TRACKS; j++) {
  288. module->snapshots[module->currentSnapshot][i][j] = module->snapshots[module->copySnapshot][i][j];
  289. }
  290. }
  291. parent->UpdateSnapshot(module->currentSnapshot);
  292. module->copyState = false;
  293. }
  294. }
  295. BlueCKD6::onMouseDown(e);
  296. }
  297. };
  298. ACNEWidget::ACNEWidget(ACNE *module) : ModuleWidget(module) {
  299. setPanel(SVG::load(assetPlugin(plugin, "res/ACNE.svg")));
  300. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  301. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  302. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  303. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  304. addParam(ParamWidget::create<BidooBlueKnob>(Vec(474.0f, 39.0f), module, ACNE::MAIN_OUT_GAIN_PARAM, 0.0f, 10.0f, 7.0f));
  305. addParam(ParamWidget::create<ACNECOPYPASTECKD6>(Vec(7.0f, 39.0f), module, ACNE::COPY_PARAM, 0.0f, 1.0f, 0.0f));
  306. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(18.0f, 28.0f), module, ACNE::COPY_LIGHT));
  307. addParam(ParamWidget::create<BidooBlueTrimpot>(Vec(432.0f, 28.0f), module, ACNE::RAMP_PARAM, 0.0f, 0.01f, 0.001f));
  308. addInput(Port::create<TinyPJ301MPort>(Vec(58.0f, 30.0f), Port::INPUT, module, ACNE::SNAPSHOT_INPUT));
  309. addParam(ParamWidget::create<MuteBtn>(Vec(2.0f, 293.0f), module, ACNE::SEND_MUTE_PARAM, 0.0f, 1.0f, 0.0f));
  310. addParam(ParamWidget::create<MuteBtn>(Vec(21.0f, 293.0f), module, ACNE::MUTE_PARAM, 0.0f, 1.0f, 0.0f));
  311. addParam(ParamWidget::create<SoloBtn>(Vec(11.0f, 314.0f), module, ACNE::SOLO_PARAM, 0.0f, 1.0f, 0.0f));
  312. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  313. addOutput(Port::create<TinyPJ301MPort>(Vec(482.0f, 79.0f+i*27.0f),Port::OUTPUT, module, ACNE::TRACKS_OUTPUTS + i));
  314. addParam(ParamWidget::create<LEDButton>(Vec(10.0f, 77.0f+i*27.0f), module, ACNE::OUT_MUTE_PARAMS + i, 0.0f, 1.0f, 0.0f));
  315. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(16.0f, 82.0f+i*27.0f), module, ACNE::OUT_MUTE_LIGHTS + i));
  316. }
  317. for (int i = 0; i < ACNE_NB_TRACKS; i++) {
  318. addParam(ParamWidget::create<ACNEChoseSceneLedButton>(Vec(43.0f+i*27.0f, 49.0f), module, ACNE::SNAPSHOT_PARAMS + i, 0.0f, 1.0f, 0.0f));
  319. addChild(ModuleLightWidget::create<SmallLight<BlueLight>>(Vec(49.0f+i*27.0f, 55.0f), module, ACNE::SNAPSHOT_LIGHTS + i));
  320. addInput(Port::create<TinyPJ301MPort>(Vec(45.0f+i*27.0f, 338.0f),Port::INPUT, module, ACNE::TRACKS_INPUTS + i));
  321. addParam(ParamWidget::create<LEDButton>(Vec(43.0f+i*27.0f, 292.0f), module, ACNE::IN_MUTE_PARAMS + i, 0.0f, 1.0f, 0.0f));
  322. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(49.0f+i*27.0f, 297.0f), module, ACNE::IN_MUTE_LIGHTS + i));
  323. addParam(ParamWidget::create<LEDButton>(Vec(43.0f+i*27.0f, 314.0f), module, ACNE::IN_SOLO_PARAMS + i, 0.0f, 1.0f, 0.0f));
  324. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(49.0f+i*27.0f, 320.0f), module, ACNE::IN_SOLO_LIGHTS + i));
  325. }
  326. for (int i = 0; i < 8; i++) {
  327. addParam(ParamWidget::create<MiniLEDButton>(Vec(62.0f+i*54.0f, 309.0f), module, ACNE::TRACKLINK_PARAMS + i, 0.0f, 10.0f, 0.0f));
  328. addChild(ModuleLightWidget::create<SmallLight<BlueLight>>(Vec(62.0f+i*54.0f, 309.0f), module, ACNE::TRACKLINK_LIGHTS + i));
  329. }
  330. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  331. for (int j = 0; j < ACNE_NB_TRACKS; j++) {
  332. faders[i][j] = ParamWidget::create<ACNETrimPot>(Vec(43.0f+j*27.0f, 77.0f+i*27.0f), module, ACNE::FADERS_PARAMS + j + i * (ACNE_NB_TRACKS), 0.0f, 10.0f, 0.0f);
  333. addParam(faders[i][j]);
  334. }
  335. }
  336. module->currentSnapshot = 0;
  337. UpdateSnapshot(module->currentSnapshot);
  338. }
  339. void ACNEWidget::UpdateSnapshot(int snapshot) {
  340. ACNE *module = dynamic_cast<ACNE*>(this->module);
  341. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  342. for (int j = 0; j < ACNE_NB_TRACKS; j++) {
  343. if (faders[i][j]->value != module->snapshots[module->currentSnapshot][i][j])
  344. faders[i][j]->setValue(module->snapshots[module->currentSnapshot][i][j]);
  345. }
  346. }
  347. }
  348. void ACNEWidget::step() {
  349. frames++;
  350. if (frames>2){
  351. ACNE *module = dynamic_cast<ACNE*>(this->module);
  352. if (module->version != moduleVersion) {
  353. for (int i = 0; i < ACNE_NB_OUTS; i++) {
  354. for (int j = 0; j < ACNE_NB_TRACKS; j++) {
  355. if (faders[i][j]->value != module->snapshots[module->currentSnapshot][i][j])
  356. faders[i][j]->setValue(module->snapshots[module->currentSnapshot][i][j]);
  357. }
  358. }
  359. moduleVersion = module->version;
  360. }
  361. frames = 0;
  362. }
  363. ModuleWidget::step();
  364. }
  365. } // namespace rack_plugin_Bidoo
  366. using namespace rack_plugin_Bidoo;
  367. RACK_PLUGIN_MODEL_INIT(Bidoo, ACNE) {
  368. Model *modelACNE = Model::create<ACNE, ACNEWidget>("Bidoo", "ACnE", "ACnE mixer", MIXER_TAG);
  369. return modelACNE;
  370. }