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.

213 lines
3.6KB

  1. #pragma once
  2. #include <dsp/common.hpp>
  3. #include <midi.hpp>
  4. namespace rack {
  5. namespace dsp {
  6. /** Converts gates and CV to MIDI messages.
  7. CHANNELS is the number of polyphony channels. Use 1 for monophonic.
  8. */
  9. template <int CHANNELS>
  10. struct MidiGenerator {
  11. int8_t vels[CHANNELS];
  12. int8_t notes[CHANNELS];
  13. bool gates[CHANNELS];
  14. int8_t keyPressures[CHANNELS];
  15. int8_t channelPressures[CHANNELS];
  16. int8_t ccs[128];
  17. int16_t pw;
  18. bool clk;
  19. bool start;
  20. bool stop;
  21. bool cont;
  22. MidiGenerator() {
  23. reset();
  24. }
  25. void reset() {
  26. for (int c = 0; c < CHANNELS; c++) {
  27. vels[c] = 100;
  28. notes[c] = 60;
  29. gates[c] = false;
  30. keyPressures[c] = -1;
  31. channelPressures[c] = -1;
  32. }
  33. for (int i = 0; i < 128; i++) {
  34. ccs[i] = -1;
  35. }
  36. pw = 0x2000;
  37. clk = false;
  38. start = false;
  39. stop = false;
  40. cont = false;
  41. }
  42. void panic() {
  43. reset();
  44. // Send all note off commands
  45. for (int note = 0; note <= 127; note++) {
  46. // Note off
  47. midi::Message m;
  48. m.setStatus(0x8);
  49. m.setNote(note);
  50. m.setValue(0);
  51. onMessage(m);
  52. }
  53. }
  54. /** Must be called before setNoteGate(). */
  55. void setVelocity(int8_t vel, int c) {
  56. vels[c] = vel;
  57. }
  58. void setNoteGate(int8_t note, bool gate, int c) {
  59. bool changedNote = gate && gates[c] && (note != notes[c]);
  60. bool enabledGate = gate && !gates[c];
  61. bool disabledGate = !gate && gates[c];
  62. if (changedNote || disabledGate) {
  63. // Note off
  64. midi::Message m;
  65. m.setStatus(0x8);
  66. m.setNote(notes[c]);
  67. m.setValue(vels[c]);
  68. onMessage(m);
  69. }
  70. if (changedNote || enabledGate) {
  71. // Note on
  72. midi::Message m;
  73. m.setStatus(0x9);
  74. m.setNote(note);
  75. m.setValue(vels[c]);
  76. onMessage(m);
  77. }
  78. notes[c] = note;
  79. gates[c] = gate;
  80. }
  81. void setKeyPressure(int8_t val, int c) {
  82. if (keyPressures[c] == val)
  83. return;
  84. keyPressures[c] = val;
  85. // Polyphonic key pressure
  86. midi::Message m;
  87. m.setStatus(0xa);
  88. m.setNote(notes[c]);
  89. m.setValue(val);
  90. onMessage(m);
  91. }
  92. void setChannelPressure(int8_t val, int c) {
  93. if (channelPressures[c] == val)
  94. return;
  95. channelPressures[c] = val;
  96. // Channel pressure
  97. midi::Message m;
  98. m.setSize(2);
  99. m.setStatus(0xd);
  100. m.setNote(val);
  101. onMessage(m);
  102. }
  103. void setCc(int8_t cc, int id) {
  104. if (ccs[id] == cc)
  105. return;
  106. ccs[id] = cc;
  107. // Control change
  108. midi::Message m;
  109. m.setStatus(0xb);
  110. m.setNote(id);
  111. m.setValue(cc);
  112. onMessage(m);
  113. }
  114. void setModWheel(int8_t mw) {
  115. setCc(mw, 0x01);
  116. }
  117. void setVolume(int8_t mw) {
  118. setCc(mw, 0x07);
  119. }
  120. void setPan(int8_t mw) {
  121. setCc(mw, 0x0a);
  122. }
  123. void setPitchWheel(int16_t pw) {
  124. if (this->pw == pw)
  125. return;
  126. this->pw = pw;
  127. // Pitch wheel
  128. midi::Message m;
  129. m.setStatus(0xe);
  130. m.setNote(pw & 0x7f);
  131. m.setValue((pw >> 7) & 0x7f);
  132. onMessage(m);
  133. }
  134. void setClock(bool clk) {
  135. if (this->clk == clk)
  136. return;
  137. this->clk = clk;
  138. if (clk) {
  139. // Timing clock
  140. midi::Message m;
  141. m.setSize(1);
  142. m.setStatus(0xf);
  143. m.setChannel(0x8);
  144. onMessage(m);
  145. }
  146. }
  147. void setStart(bool start) {
  148. if (this->start == start)
  149. return;
  150. this->start = start;
  151. if (start) {
  152. // Start
  153. midi::Message m;
  154. m.setSize(1);
  155. m.setStatus(0xf);
  156. m.setChannel(0xa);
  157. onMessage(m);
  158. }
  159. }
  160. void setContinue(bool cont) {
  161. if (this->cont == cont)
  162. return;
  163. this->cont = cont;
  164. if (cont) {
  165. // Continue
  166. midi::Message m;
  167. m.setSize(1);
  168. m.setStatus(0xf);
  169. m.setChannel(0xb);
  170. onMessage(m);
  171. }
  172. }
  173. void setStop(bool stop) {
  174. if (this->stop == stop)
  175. return;
  176. this->stop = stop;
  177. if (stop) {
  178. // Stop
  179. midi::Message m;
  180. m.setSize(1);
  181. m.setStatus(0xf);
  182. m.setChannel(0xc);
  183. onMessage(m);
  184. }
  185. }
  186. virtual void onMessage(midi::Message message) {}
  187. };
  188. } // namespace dsp
  189. } // namespace rack