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.

421 lines
14KB

  1. #include "AudibleInstruments.hpp"
  2. #include <string.h>
  3. #include "frames/keyframer.h"
  4. #include "frames/poly_lfo.h"
  5. #include "dsp/digital.hpp"
  6. struct Frames : Module {
  7. enum ParamIds {
  8. GAIN1_PARAM,
  9. GAIN2_PARAM,
  10. GAIN3_PARAM,
  11. GAIN4_PARAM,
  12. ADD_PARAM,
  13. DEL_PARAM,
  14. FRAME_PARAM,
  15. MODULATION_PARAM,
  16. OFFSET_PARAM,
  17. NUM_PARAMS
  18. };
  19. enum InputIds {
  20. ALL_INPUT,
  21. IN1_INPUT,
  22. IN2_INPUT,
  23. IN3_INPUT,
  24. IN4_INPUT,
  25. FRAME_INPUT,
  26. NUM_INPUTS
  27. };
  28. enum OutputIds {
  29. MIX_OUTPUT,
  30. OUT1_OUTPUT,
  31. OUT2_OUTPUT,
  32. OUT3_OUTPUT,
  33. OUT4_OUTPUT,
  34. FRAME_STEP_OUTPUT,
  35. GAIN1_LIGHT,
  36. EDIT_LIGHT = GAIN1_LIGHT + 4,
  37. FRAME_LIGHT,
  38. NUM_OUTPUTS = FRAME_LIGHT + 3
  39. };
  40. frames::Keyframer keyframer;
  41. frames::PolyLfo poly_lfo;
  42. bool poly_lfo_mode = false;
  43. uint16_t lastControls[4] = {};
  44. SchmittTrigger addTrigger;
  45. SchmittTrigger delTrigger;
  46. bool clearKeyframes = false;
  47. Frames();
  48. void step() override;
  49. json_t *toJson() override {
  50. json_t *rootJ = json_object();
  51. json_object_set_new(rootJ, "polyLfo", json_boolean(poly_lfo_mode));
  52. json_t *keyframesJ = json_array();
  53. for (int i = 0; i < keyframer.num_keyframes(); i++) {
  54. json_t *keyframeJ = json_array();
  55. frames::Keyframe *keyframe = keyframer.mutable_keyframe(i);
  56. json_array_append_new(keyframeJ, json_integer(keyframe->timestamp));
  57. for (int k = 0; k < 4; k++) {
  58. json_array_append_new(keyframeJ, json_integer(keyframe->values[k]));
  59. }
  60. json_array_append_new(keyframesJ, keyframeJ);
  61. }
  62. json_object_set_new(rootJ, "keyframes", keyframesJ);
  63. // TODO Channel settings
  64. return rootJ;
  65. }
  66. void fromJson(json_t *rootJ) override {
  67. json_t *polyLfoJ = json_object_get(rootJ, "polyLfo");
  68. if (polyLfoJ)
  69. poly_lfo_mode = json_boolean_value(polyLfoJ);
  70. json_t *keyframesJ = json_object_get(rootJ, "keyframes");
  71. if (keyframesJ) {
  72. json_t *keyframeJ;
  73. size_t i;
  74. json_array_foreach(keyframesJ, i, keyframeJ) {
  75. uint16_t timestamp = json_integer_value(json_array_get(keyframeJ, 0));
  76. uint16_t values[4];
  77. for (int k = 0; k < 4; k++) {
  78. values[k] = json_integer_value(json_array_get(keyframeJ, k + 1));
  79. }
  80. keyframer.AddKeyframe(timestamp, values);
  81. }
  82. }
  83. // TODO Channel settings
  84. }
  85. void reset() override {
  86. poly_lfo_mode = false;
  87. keyframer.Clear();
  88. }
  89. void randomize() override {
  90. // TODO
  91. // Maybe something useful should go in here??
  92. }
  93. };
  94. Frames::Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
  95. memset(&keyframer, 0, sizeof(keyframer));
  96. keyframer.Init();
  97. memset(&poly_lfo, 0, sizeof(poly_lfo));
  98. poly_lfo.Init();
  99. for (int i = 0; i < 4; i++) {
  100. keyframer.mutable_settings(i)->easing_curve = frames::EASING_CURVE_LINEAR;
  101. }
  102. }
  103. void Frames::step() {
  104. // Set gain and timestamp knobs
  105. uint16_t controls[4];
  106. for (int i = 0; i < 4; i++) {
  107. controls[i] = params[GAIN1_PARAM + i].value * 65535.0;
  108. }
  109. int32_t timestamp = params[FRAME_PARAM].value * 65535.0;
  110. int32_t timestampMod = timestamp + params[MODULATION_PARAM].value * inputs[FRAME_INPUT].value / 10.0 * 65535.0;
  111. timestamp = clampi(timestamp, 0, 65535);
  112. timestampMod = clampi(timestampMod, 0, 65535);
  113. int16_t nearestIndex = -1;
  114. if (!poly_lfo_mode) {
  115. nearestIndex = keyframer.FindNearestKeyframe(timestamp, 2048);
  116. }
  117. // Render, handle buttons
  118. if (poly_lfo_mode) {
  119. if (controls[0] != lastControls[0])
  120. poly_lfo.set_shape(controls[0]);
  121. if (controls[1] != lastControls[1])
  122. poly_lfo.set_shape_spread(controls[1]);
  123. if (controls[2] != lastControls[2])
  124. poly_lfo.set_spread(controls[2]);
  125. if (controls[3] != lastControls[3])
  126. poly_lfo.set_coupling(controls[3]);
  127. poly_lfo.Render(timestampMod);
  128. }
  129. else {
  130. for (int i = 0; i < 4; i++) {
  131. if (controls[i] != lastControls[i]) {
  132. // Update recently moved control
  133. if (keyframer.num_keyframes() == 0) {
  134. keyframer.set_immediate(i, controls[i]);
  135. }
  136. if (nearestIndex >= 0) {
  137. frames::Keyframe *nearestKeyframe = keyframer.mutable_keyframe(nearestIndex);
  138. nearestKeyframe->values[i] = controls[i];
  139. }
  140. }
  141. }
  142. if (addTrigger.process(params[ADD_PARAM].value)) {
  143. if (nearestIndex < 0) {
  144. keyframer.AddKeyframe(timestamp, controls);
  145. }
  146. }
  147. if (delTrigger.process(params[DEL_PARAM].value)) {
  148. if (nearestIndex >= 0) {
  149. int32_t nearestTimestamp = keyframer.keyframe(nearestIndex).timestamp;
  150. keyframer.RemoveKeyframe(nearestTimestamp);
  151. }
  152. }
  153. keyframer.Evaluate(timestampMod);
  154. }
  155. // Get gains
  156. float gains[4];
  157. for (int i = 0; i < 4; i++) {
  158. if (poly_lfo_mode) {
  159. // gains[i] = poly_lfo.level(i) / 255.0;
  160. gains[i] = poly_lfo.level16(i) / 65535.0;
  161. }
  162. else {
  163. float lin = keyframer.level(i) / 65535.0;
  164. gains[i] = lin;
  165. }
  166. }
  167. // Update last controls
  168. for (int i = 0; i < 4; i++) {
  169. lastControls[i] = controls[i];
  170. }
  171. // Get inputs
  172. float all = ((int)params[OFFSET_PARAM].value == 1) ? 10.0 : 0.0;
  173. if (inputs[ALL_INPUT].active) {
  174. all = inputs[ALL_INPUT].value;
  175. }
  176. float ins[4];
  177. for (int i = 0; i < 4; i++) {
  178. ins[i] = inputs[IN1_INPUT + i].normalize(all) * gains[i];
  179. }
  180. // Set outputs
  181. float mix = 0.0;
  182. for (int i = 0; i < 4; i++) {
  183. if (outputs[OUT1_OUTPUT + i].active) {
  184. outputs[OUT1_OUTPUT + i].value = ins[i];
  185. }
  186. else {
  187. mix += ins[i];
  188. }
  189. }
  190. outputs[MIX_OUTPUT].value = clampf(mix / 2.0, -10.0, 10.0);
  191. // Set lights
  192. for (int i = 0; i < 4; i++) {
  193. outputs[GAIN1_LIGHT + i].value = gains[i];
  194. }
  195. if (poly_lfo_mode) {
  196. outputs[EDIT_LIGHT].value = (poly_lfo.level(0) > 128 ? 1.0 : 0.0);
  197. }
  198. else {
  199. // TODO
  200. outputs[EDIT_LIGHT].value = (nearestIndex >= 0 ? 1.0 : 0.0);
  201. }
  202. // Set frame light colors
  203. const uint8_t *colors;
  204. if (poly_lfo_mode) {
  205. colors = poly_lfo.color();
  206. }
  207. else {
  208. colors = keyframer.color();
  209. }
  210. for (int c = 0; c < 3; c++) {
  211. outputs[FRAME_LIGHT + c].value = colors[c] / 255.0;
  212. }
  213. }
  214. struct FramesLight : LightWidget {
  215. float *colors[3];
  216. FramesLight() {
  217. box.size = Vec(67, 67);
  218. }
  219. void step() override {
  220. const NVGcolor red = COLOR_RED;
  221. const NVGcolor green = COLOR_GREEN;
  222. const NVGcolor blue = COLOR_BLUE;
  223. float r = *colors[0];
  224. float g = *colors[1];
  225. float b = *colors[2];
  226. color.r = red.r * r + green.r * g + blue.r * b;
  227. color.g = red.g * r + green.g * g + blue.g * b;
  228. color.b = red.b * r + green.b * g + blue.b * b;
  229. color.a = 1.0;
  230. // Lighten
  231. color = nvgLerpRGBA(color, COLOR_WHITE, 0.5);
  232. }
  233. };
  234. struct CKSSRot : SVGSwitch, ToggleSwitch {
  235. CKSSRot() {
  236. addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_rot_0.svg")));
  237. addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_rot_1.svg")));
  238. sw->wrap();
  239. box.size = sw->box.size;
  240. }
  241. };
  242. FramesWidget::FramesWidget() {
  243. Frames *module = new Frames();
  244. setModule(module);
  245. box.size = Vec(15*18, 380);
  246. {
  247. Panel *panel = new LightPanel();
  248. panel->backgroundImage = Image::load(assetPlugin(plugin, "res/Frames.png"));
  249. panel->box.size = box.size;
  250. addChild(panel);
  251. }
  252. addChild(createScrew<ScrewSilver>(Vec(15, 0)));
  253. addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 0)));
  254. addChild(createScrew<ScrewSilver>(Vec(15, 365)));
  255. addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365)));
  256. addParam(createParam<Rogan1PSWhite>(Vec(14, 52), module, Frames::GAIN1_PARAM, 0.0, 1.0, 0.0));
  257. addParam(createParam<Rogan1PSWhite>(Vec(81, 52), module, Frames::GAIN2_PARAM, 0.0, 1.0, 0.0));
  258. addParam(createParam<Rogan1PSWhite>(Vec(149, 52), module, Frames::GAIN3_PARAM, 0.0, 1.0, 0.0));
  259. addParam(createParam<Rogan1PSWhite>(Vec(216, 52), module, Frames::GAIN4_PARAM, 0.0, 1.0, 0.0));
  260. addParam(createParam<Rogan6PSWhite>(Vec(91, 117), module, Frames::FRAME_PARAM, 0.0, 1.0, 0.0));
  261. addParam(createParam<Rogan1PSGreen>(Vec(208, 141), module, Frames::MODULATION_PARAM, -1.0, 1.0, 0.0));
  262. addParam(createParam<CKD6>(Vec(19, 123), module, Frames::ADD_PARAM, 0.0, 1.0, 0.0));
  263. addParam(createParam<CKD6>(Vec(19, 172), module, Frames::DEL_PARAM, 0.0, 1.0, 0.0));
  264. addParam(createParam<CKSSRot>(Vec(18, 239), module, Frames::OFFSET_PARAM, 0.0, 1.0, 0.0));
  265. addInput(createInput<PJ301MPort>(Vec(16, 273), module, Frames::ALL_INPUT));
  266. addInput(createInput<PJ301MPort>(Vec(59, 273), module, Frames::IN1_INPUT));
  267. addInput(createInput<PJ301MPort>(Vec(102, 273), module, Frames::IN2_INPUT));
  268. addInput(createInput<PJ301MPort>(Vec(145, 273), module, Frames::IN3_INPUT));
  269. addInput(createInput<PJ301MPort>(Vec(188, 273), module, Frames::IN4_INPUT));
  270. addInput(createInput<PJ301MPort>(Vec(231, 273), module, Frames::FRAME_INPUT));
  271. addOutput(createOutput<PJ301MPort>(Vec(16, 315), module, Frames::MIX_OUTPUT));
  272. addOutput(createOutput<PJ301MPort>(Vec(59, 315), module, Frames::OUT1_OUTPUT));
  273. addOutput(createOutput<PJ301MPort>(Vec(102, 315), module, Frames::OUT2_OUTPUT));
  274. addOutput(createOutput<PJ301MPort>(Vec(145, 315), module, Frames::OUT3_OUTPUT));
  275. addOutput(createOutput<PJ301MPort>(Vec(188, 315), module, Frames::OUT4_OUTPUT));
  276. addOutput(createOutput<PJ301MPort>(Vec(231, 315), module, Frames::FRAME_STEP_OUTPUT));
  277. addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(30, 101), &module->outputs[Frames::GAIN1_LIGHT + 0].value));
  278. addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(97, 101), &module->outputs[Frames::GAIN1_LIGHT + 1].value));
  279. addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(165, 101), &module->outputs[Frames::GAIN1_LIGHT + 2].value));
  280. addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(232, 101), &module->outputs[Frames::GAIN1_LIGHT + 3].value));
  281. addChild(createValueLight<MediumLight<GreenRedPolarityLight>>(Vec(61, 155), &module->outputs[Frames::EDIT_LIGHT].value));
  282. {
  283. FramesLight *framesLight = new FramesLight();
  284. framesLight->box.pos = Vec(102, 128);
  285. framesLight->colors[0] = &module->outputs[Frames::FRAME_LIGHT + 0].value;
  286. framesLight->colors[1] = &module->outputs[Frames::FRAME_LIGHT + 1].value;
  287. framesLight->colors[2] = &module->outputs[Frames::FRAME_LIGHT + 2].value;
  288. addChild(framesLight);
  289. }
  290. }
  291. struct FramesCurveItem : MenuItem {
  292. Frames *frames;
  293. uint8_t channel;
  294. frames::EasingCurve curve;
  295. void onAction() override {
  296. frames->keyframer.mutable_settings(channel)->easing_curve = curve;
  297. }
  298. void step() override {
  299. rightText = (frames->keyframer.mutable_settings(channel)->easing_curve == curve) ? "✔" : "";
  300. }
  301. };
  302. struct FramesResponseItem : MenuItem {
  303. Frames *frames;
  304. uint8_t channel;
  305. uint8_t response;
  306. void onAction() override {
  307. frames->keyframer.mutable_settings(channel)->response = response;
  308. }
  309. void step() override {
  310. rightText = (frames->keyframer.mutable_settings(channel)->response = response) ? "✔" : "";
  311. }
  312. };
  313. struct FramesChannelSettingsItem : MenuItem {
  314. Frames *frames;
  315. uint8_t channel;
  316. Menu *createChildMenu() override {
  317. Menu *menu = new Menu();
  318. // TODO
  319. menu->pushChild(construct<MenuLabel>(&MenuEntry::text, "Interpolation Curve"));
  320. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Step", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_STEP));
  321. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Linear", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_LINEAR));
  322. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Accelerating", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_IN_QUARTIC));
  323. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Decelerating", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_OUT_QUARTIC));
  324. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Smooth Departure/Arrival", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_SINE));
  325. menu->pushChild(construct<FramesCurveItem>(&MenuEntry::text, "Bouncing", &FramesCurveItem::frames, frames, &FramesCurveItem::channel, channel, &FramesCurveItem::curve, frames::EASING_CURVE_BOUNCE));
  326. menu->pushChild(construct<MenuLabel>());
  327. menu->pushChild(construct<MenuLabel>(&MenuEntry::text, "Response Curve"));
  328. menu->pushChild(construct<FramesResponseItem>(&MenuEntry::text, "Linear", &FramesResponseItem::frames, frames, &FramesResponseItem::channel, channel, &FramesResponseItem::response, 0));
  329. menu->pushChild(construct<FramesResponseItem>(&MenuEntry::text, "Exponential", &FramesResponseItem::frames, frames, &FramesResponseItem::channel, channel, &FramesResponseItem::response, 1));
  330. return menu;
  331. }
  332. };
  333. struct FramesClearItem : MenuItem {
  334. Frames *frames;
  335. void onAction() override {
  336. frames->keyframer.Clear();
  337. }
  338. };
  339. struct FramesModeItem : MenuItem {
  340. Frames *frames;
  341. bool poly_lfo_mode;
  342. void onAction() override {
  343. frames->poly_lfo_mode = poly_lfo_mode;
  344. }
  345. void step() override {
  346. rightText = (frames->poly_lfo_mode == poly_lfo_mode) ? "✔" : "";
  347. }
  348. };
  349. Menu *FramesWidget::createContextMenu() {
  350. Menu *menu = ModuleWidget::createContextMenu();
  351. Frames *frames = dynamic_cast<Frames*>(module);
  352. assert(frames);
  353. menu->pushChild(construct<MenuLabel>());
  354. menu->pushChild(construct<MenuLabel>(&MenuEntry::text, "Channel Settings"));
  355. for (int i = 0; i < 4; i++) {
  356. menu->pushChild(construct<FramesChannelSettingsItem>(&MenuItem::text, stringf("Channel %d", i + 1), &FramesChannelSettingsItem::frames, frames, &FramesChannelSettingsItem::channel, i));
  357. }
  358. menu->pushChild(construct<FramesClearItem>(&MenuItem::text, "Clear Keyframes", &FramesClearItem::frames, frames));
  359. menu->pushChild(construct<MenuLabel>());
  360. menu->pushChild(construct<MenuLabel>(&MenuEntry::text, "Mode"));
  361. menu->pushChild(construct<FramesModeItem>(&MenuItem::text, "Keyframer", &FramesModeItem::frames, frames, &FramesModeItem::poly_lfo_mode, false));
  362. menu->pushChild(construct<FramesModeItem>(&MenuItem::text, "Poly LFO", &FramesModeItem::frames, frames, &FramesModeItem::poly_lfo_mode, true));
  363. return menu;
  364. }