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.

365 lines
9.3KB

  1. #include "global_pre.hpp"
  2. #include "Erratic.hpp"
  3. #include "midi.hpp"
  4. #include "MPEBaseWidget.hpp"
  5. #include "global_ui.hpp"
  6. struct MidiValue {
  7. int val = 0; // Controller value
  8. // TransitionSmoother tSmooth;
  9. bool changed = false; // Value has been changed by midi message (only if it is in sync!)
  10. };
  11. struct MPEPlusValue {
  12. uint16_t val = 0; // Controller value
  13. int MSB = 0 ;
  14. int LSB = 0;
  15. bool changed = false; // Value has been changed by midi message (only if it is in sync!)
  16. };
  17. struct MidiPedalValue {
  18. int val = 0; // Controller value
  19. int cc ; // need to set it
  20. bool changed = false; // Value has been changed by midi message (only if it is in sync!)
  21. };
  22. struct MPEToCV : Module {
  23. enum ParamIds {
  24. RESET_PARAM,
  25. NUM_PARAMS,
  26. BEND_RANGE_PARAM
  27. };
  28. enum InputIds {
  29. NUM_INPUTS
  30. };
  31. enum OutputIds {
  32. PITCH_OUTPUT = 0,
  33. GATE_OUTPUT,
  34. VELOCITY_OUTPUT,
  35. PRESSURE_OUTPUT,
  36. Y_OUTPUT,
  37. PEDAL_OUTPUT,
  38. NUM_OUTPUTS
  39. };
  40. enum LightIds {
  41. RESET_LIGHT,
  42. VELOCITY_LIGHT,
  43. PRESSURE_LIGHT,
  44. Y_AXIS_LIGHT,
  45. PEDAL_LIGHT,
  46. NUM_LIGHTS
  47. };
  48. MidiInputQueue midiInput;
  49. int bendRange = 48; // our default is 48 (common for ROLI), Continuum has 96.
  50. int channel = 2; // Our default channel is 2. ROLI users will want to set this is 2
  51. int globalChannel = 16; // Our default channel is 16. ROLI users will want to set this is 1
  52. bool MPEPlus = false ; // This is specially useful for Haken Continuum
  53. int YaxisCC = 74 ;
  54. bool newNote = false;
  55. std::list<int> notes;
  56. bool pedal = false;
  57. int note = 60; // C4, most modules should use 261.626 Hz
  58. int vel = 0;
  59. MidiValue mod;
  60. MidiValue afterTouch;
  61. MidiValue pitchWheel;
  62. MidiValue Yaxis ;
  63. MidiPedalValue midiPedalOne ;
  64. // Used for MPE+
  65. MPEPlusValue MPEPlusyAxis, MPEPluszAxis ;
  66. bool gate = false;
  67. // Reset note parameters when you release, ie, receive note off
  68. bool noteOffReset = true;
  69. bool resetNoteNow = false;
  70. // SchmittTrigger resetTrigger;
  71. MPEToCV();
  72. // ~MPEToCV() {
  73. // };
  74. void step() override;
  75. void pressNote(int note);
  76. void releaseNote(int note);
  77. void processMessage(MidiMessage msg);
  78. json_t *toJson() override {
  79. json_t *rootJ = json_object();
  80. json_object_set_new(rootJ, "midi", midiInput.toJson());
  81. json_object_set_new(rootJ, "bendRange", json_integer(bendRange));
  82. json_object_set_new(rootJ, "midiChannel", json_integer(channel));
  83. json_object_set_new(rootJ, "globalMidiChannel", json_integer(globalChannel));
  84. json_object_set_new(rootJ, "MPEMode", json_integer(MPEPlus));
  85. json_object_set_new(rootJ, "noteOffReset", json_boolean(noteOffReset));
  86. return rootJ;
  87. }
  88. void fromJson(json_t *rootJ) override {
  89. json_t *midiJ = json_object_get(rootJ, "midi");
  90. midiInput.fromJson(midiJ);
  91. json_t *bendRangeJ = json_object_get(rootJ, "bendRange");
  92. if (bendRangeJ) {
  93. bendRange = json_integer_value(bendRangeJ);
  94. }
  95. json_t *midiChannelJ = json_object_get(rootJ, "midiChannel");
  96. if (midiChannelJ) {
  97. channel = json_integer_value(midiChannelJ);
  98. }
  99. json_t *globalMidiChannelJ = json_object_get(rootJ, "globalMidiChannel");
  100. if (globalMidiChannelJ) {
  101. globalChannel = json_integer_value(globalMidiChannelJ);
  102. }
  103. json_t *MPEModeJ = json_object_get(rootJ, "MPEMode");
  104. if (MPEModeJ) {
  105. MPEPlus = json_integer_value(MPEModeJ);
  106. }
  107. json_t *noteOffResetJ = json_object_get(rootJ, "noteOffReset");
  108. if (noteOffResetJ) {
  109. noteOffReset = json_boolean_value(noteOffResetJ);
  110. }
  111. }
  112. };
  113. // MPEMidiWidget stuff
  114. struct BendRangeItem : MenuItem {
  115. MPEToCV *mpetocv;
  116. int bendRange ;
  117. void onAction(EventAction &e) override {
  118. mpetocv->bendRange = bendRange;
  119. }
  120. };
  121. struct BendRangeChoice : LedDisplayChoice {
  122. // MPEToCVWidget *mpetocvwidget;
  123. MPEToCV *mpetocv;
  124. int bendRange ;
  125. void onAction(EventAction &e) override {
  126. #ifdef USE_VST2
  127. Menu *menu = rack::global_ui->ui.gScene->createMenu();
  128. #else
  129. Menu *menu = gScene->createMenu();
  130. #endif // USE_VST2
  131. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Bend Range"));
  132. std::vector<int> bendRanges = {1,2,3,4,12,24,48,96}; // The bend range we use
  133. for (auto const& bendRangeValue: bendRanges) {
  134. BendRangeItem *item = new BendRangeItem();
  135. item->mpetocv = mpetocv;
  136. item->text = std::to_string(bendRangeValue);
  137. item->bendRange = bendRangeValue;
  138. menu->addChild(item);
  139. }
  140. // mpetocv->bendRange = bendRange;
  141. }
  142. void step() override {
  143. color = nvgRGB(0xff, 0x00, 0x00);
  144. color.a = 0.8f;
  145. text = stringf("%d", mpetocv->bendRange);
  146. // text = stringf("Range: %d semitones", mpetocv->bendRange);
  147. // rightText = (mpetocv->bendRange==bendRange) ? "✔" : "";
  148. }
  149. };
  150. struct MidiChannelItem : MenuItem {
  151. MPEToCV *mpetocv;
  152. int channel ;
  153. void onAction(EventAction &e) override {
  154. mpetocv->channel = channel;
  155. }
  156. };
  157. struct MidiChannelChoice : LedDisplayChoice {
  158. // MPEToCVWidget *mpetocvwidget;
  159. MPEToCV *mpetocv;
  160. int channel ;
  161. void onAction(EventAction &e) override {
  162. #ifdef USE_VST2
  163. Menu *menu = rack::global_ui->ui.gScene->createMenu();
  164. #else
  165. Menu *menu = gScene->createMenu();
  166. #endif // USE_VST2
  167. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Midi channel"));
  168. std::vector<int> bendRanges = {1,2,3,4,12,24,48,96}; // The bend range we use
  169. for (int c=1; c <= 16 ; c++) {
  170. MidiChannelItem *item = new MidiChannelItem();
  171. item->mpetocv = mpetocv;
  172. item->text = std::to_string(c);
  173. item->channel = c;
  174. menu->addChild(item);
  175. }
  176. }
  177. void step() override {
  178. color = nvgRGB(0xff, 0x00, 0x00);
  179. color.a = 0.8f;
  180. text = std::to_string(mpetocv->channel);
  181. }
  182. };
  183. struct GlobalMidiChannelItem : MenuItem {
  184. MPEToCV *mpetocv;
  185. int channel ;
  186. void onAction(EventAction &e) override {
  187. mpetocv->globalChannel = channel;
  188. }
  189. };
  190. struct GlobalMidiChannelChoice : LedDisplayChoice {
  191. // MPEToCVWidget *mpetocvwidget;
  192. MPEToCV *mpetocv;
  193. int channel ;
  194. void onAction(EventAction &e) override {
  195. #ifdef USE_VST2
  196. Menu *menu = rack::global_ui->ui.gScene->createMenu();
  197. #else
  198. Menu *menu = gScene->createMenu();
  199. #endif // USE_VST2
  200. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Global Midi channel"));
  201. for (int c=1; c <= 16 ; c++) {
  202. GlobalMidiChannelItem *item = new GlobalMidiChannelItem();
  203. item->mpetocv = mpetocv;
  204. item->text = std::to_string(c);
  205. item->channel = c;
  206. menu->addChild(item);
  207. }
  208. }
  209. void step() override {
  210. color = nvgRGB(0xff, 0x00, 0x00);
  211. color.a = 0.8f;
  212. text = std::to_string(mpetocv->globalChannel);
  213. }
  214. };
  215. struct MPEModeItem : MenuItem {
  216. MPEToCV *mpetocv;
  217. bool MPEPlus ;
  218. void onAction(EventAction &e) override {
  219. mpetocv->MPEPlus = MPEPlus;
  220. }
  221. };
  222. struct MPEModeChoice : LedDisplayChoice {
  223. // MPEToCVWidget *mpetocvwidget;
  224. MPEToCV *mpetocv;
  225. bool MPEPlus ;
  226. void onAction(EventAction &e) override {
  227. #ifdef USE_VST2
  228. Menu *menu = rack::global_ui->ui.gScene->createMenu();
  229. #else
  230. Menu *menu = gScene->createMenu();
  231. #endif // USE_VST2
  232. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "MPE mode"));
  233. // MPE
  234. MPEModeItem *MPE = new MPEModeItem();
  235. MPE->mpetocv = mpetocv;
  236. MPE->text = "MPE - Standard (ROLI, etc)";
  237. MPE->MPEPlus = false;
  238. menu->addChild(MPE);
  239. // MPE Plus
  240. MPEModeItem *MPEPlus = new MPEModeItem();
  241. MPEPlus->mpetocv = mpetocv;
  242. MPEPlus->text = "MPE+ - High Res for Haken Continuum";
  243. MPEPlus->MPEPlus = true;
  244. menu->addChild(MPEPlus);
  245. }
  246. void step() override {
  247. // color = nvgRGB(0xff, 0x00, 0x00);
  248. // color.a = 0.8f;
  249. if (mpetocv->MPEPlus) {
  250. text = "MPE+";
  251. } else {
  252. text = "MPE";
  253. }
  254. }
  255. };
  256. // We extend the midi to follow similar design
  257. struct MPEMidiWidget : MPEBaseWidget {
  258. LedDisplaySeparator *hSeparators[2];
  259. LedDisplaySeparator *vSeparators[3];
  260. // LedDisplayChoice *ccChoices[4][4];
  261. MPEToCV *mpetocv ;
  262. BendRangeChoice *bendRangeChoice ;
  263. MidiChannelChoice *midiChannelChoice ;
  264. GlobalMidiChannelChoice *globalMidiChannelChoice ;
  265. MPEModeChoice *mpeModeChoice ;
  266. MPEMidiWidget() {
  267. }
  268. void initialize(MPEToCV *mpetocv) {
  269. this->mpetocv = mpetocv;
  270. Vec pos = deviceChoice->box.getBottomLeft();
  271. for (int y = 0; y < 2; y++) {
  272. hSeparators[y] = Widget::create<LedDisplaySeparator>(pos);
  273. addChild(hSeparators[y]);
  274. }
  275. midiChannelChoice = Widget::create<MidiChannelChoice>(pos);
  276. midiChannelChoice->mpetocv = mpetocv ;
  277. addChild(midiChannelChoice);
  278. globalMidiChannelChoice = Widget::create<GlobalMidiChannelChoice>(pos);
  279. globalMidiChannelChoice->mpetocv = mpetocv ;
  280. addChild(globalMidiChannelChoice);
  281. bendRangeChoice = Widget::create<BendRangeChoice>(pos);
  282. bendRangeChoice->mpetocv = mpetocv ;
  283. addChild(bendRangeChoice);
  284. mpeModeChoice = Widget::create<MPEModeChoice>(pos);
  285. mpeModeChoice->mpetocv = mpetocv ;
  286. addChild(mpeModeChoice);
  287. for (int x = 0; x < 3; x++) {
  288. vSeparators[x] = Widget::create<LedDisplaySeparator>(pos);
  289. vSeparators[x]->box.size.y = midiChannelChoice->box.size.y;
  290. addChild(vSeparators[x]);
  291. }
  292. // for (int x = 0; x < 3; x++) {
  293. // }
  294. }
  295. void step() override {
  296. MPEBaseWidget::step();
  297. midiChannelChoice->box.size.x = box.size.x/4;
  298. midiChannelChoice->box.pos.x = 0;
  299. globalMidiChannelChoice->box.size.x = box.size.x/4;
  300. globalMidiChannelChoice->box.pos.x = box.size.x/4;
  301. bendRangeChoice->box.size.x = box.size.x/4;
  302. bendRangeChoice->box.pos.x = box.size.x/4 * 2 ;
  303. mpeModeChoice->box.size.x = box.size.x/4;
  304. mpeModeChoice->box.pos.x = box.size.x/4 * 3 - 5 ;
  305. for (int y = 0; y < 2; y++) {
  306. hSeparators[y]->box.size.x = box.size.x;
  307. }
  308. for (int x = 0; x < 3; x++) {
  309. vSeparators[x]->box.pos.x = box.size.x / 4 * (x+1);
  310. }
  311. }
  312. };