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.

356 lines
12KB

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