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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /* Play notes with a regular USB MIDI Instrument.
  2. To use this example, connect a USB instrument to Teensy 3.6's
  3. USB host port. This cable is recommended:
  4. https://www.pjrc.com/store/cable_usb_host_t36.html
  5. Requires Teensy 3.6 for USB host capability.
  6. Requires Audio Shield: https://www.pjrc.com/store/teensy3_audio.html
  7. */
  8. #include "Pizzicato_samples.h"
  9. #include "FrenchHorns_samples.h"
  10. #include "Viola_samples.h"
  11. #include "BasicFlute1_samples.h"
  12. #include "Ocarina_samples.h"
  13. #include <Bounce.h>
  14. #include <Audio.h>
  15. #include <Wire.h>
  16. #include <SPI.h>
  17. #include <SD.h>
  18. #include <SerialFlash.h>
  19. #include <USBHost_t36.h>
  20. //#define DEBUG_ALLOC
  21. const int TOTAL_VOICES = 64;
  22. const int TOTAL_MIXERS = 21;
  23. const int SECONDARY_MIXERS = 4;
  24. USBHost myusb;
  25. USBHub hub1(myusb);
  26. USBHub hub2(myusb);
  27. USBHub hub3(myusb);
  28. KeyboardController keyboard1(myusb);
  29. KeyboardController keyboard2(myusb);
  30. MIDIDevice midi1(myusb);
  31. AudioControlSGTL5000 sgtl5000_1;
  32. AudioSynthWavetable wavetable[TOTAL_VOICES];
  33. AudioMixer4 mixer[TOTAL_MIXERS];
  34. AudioOutputI2S i2s1;
  35. AudioConnection patchCord[] = {
  36. {wavetable[0], 0, mixer[0], 0}, {wavetable[1], 0, mixer[0], 1}, {wavetable[2], 0, mixer[0], 2}, {wavetable[3], 0, mixer[0], 3}, {mixer[0], 0, mixer[TOTAL_MIXERS - 2], 0},
  37. {wavetable[4], 0, mixer[1], 0}, {wavetable[5], 0, mixer[1], 1}, {wavetable[6], 0, mixer[1], 2}, {wavetable[7], 0, mixer[1], 3}, {mixer[1], 0, mixer[TOTAL_MIXERS - 2], 1},
  38. {wavetable[8], 0, mixer[2], 0}, {wavetable[9], 0, mixer[2], 1}, {wavetable[10], 0, mixer[2], 2}, {wavetable[11], 0, mixer[2], 3}, {mixer[2], 0, mixer[TOTAL_MIXERS - 2], 2},
  39. {wavetable[12], 0, mixer[3], 0}, {wavetable[13], 0, mixer[3], 1}, {wavetable[14], 0, mixer[3], 2}, {wavetable[15], 0, mixer[3], 3}, {mixer[3], 0, mixer[TOTAL_MIXERS - 2], 3},
  40. {wavetable[16], 0, mixer[4], 0}, {wavetable[17], 0, mixer[4], 1}, {wavetable[18], 0, mixer[4], 2}, {wavetable[19], 0, mixer[4], 3}, {mixer[4], 0, mixer[TOTAL_MIXERS - 3], 0},
  41. {wavetable[20], 0, mixer[5], 0}, {wavetable[21], 0, mixer[5], 1}, {wavetable[22], 0, mixer[5], 2}, {wavetable[23], 0, mixer[5], 3}, {mixer[5], 0, mixer[TOTAL_MIXERS - 3], 1},
  42. {wavetable[24], 0, mixer[6], 0}, {wavetable[25], 0, mixer[6], 1}, {wavetable[26], 0, mixer[6], 2}, {wavetable[27], 0, mixer[6], 3}, {mixer[6], 0, mixer[TOTAL_MIXERS - 3], 2},
  43. {wavetable[28], 0, mixer[7], 0}, {wavetable[29], 0, mixer[7], 1}, {wavetable[30], 0, mixer[7], 2}, {wavetable[31], 0, mixer[7], 3}, {mixer[7], 0, mixer[TOTAL_MIXERS - 3], 3},
  44. {wavetable[32], 0, mixer[8], 0}, {wavetable[33], 0, mixer[8], 1}, {wavetable[34], 0, mixer[8], 2}, {wavetable[35], 0, mixer[8], 3}, {mixer[8], 0, mixer[TOTAL_MIXERS - 4], 0},
  45. {wavetable[36], 0, mixer[9], 0}, {wavetable[37], 0, mixer[9], 1}, {wavetable[38], 0, mixer[9], 2}, {wavetable[39], 0, mixer[9], 3}, {mixer[9], 0, mixer[TOTAL_MIXERS - 4], 1},
  46. {wavetable[40], 0, mixer[10], 0}, {wavetable[41], 0, mixer[10], 1}, {wavetable[42], 0, mixer[10], 2}, {wavetable[43], 0, mixer[10], 3}, {mixer[10], 0, mixer[TOTAL_MIXERS - 4], 2},
  47. {wavetable[44], 0, mixer[11], 0}, {wavetable[45], 0, mixer[11], 1}, {wavetable[46], 0, mixer[11], 2}, {wavetable[47], 0, mixer[11], 3}, {mixer[11], 0, mixer[TOTAL_MIXERS - 4], 3},
  48. {wavetable[48], 0, mixer[12], 0}, {wavetable[49], 0, mixer[12], 1}, {wavetable[50], 0, mixer[12], 2}, {wavetable[51], 0, mixer[12], 3}, {mixer[12], 0, mixer[TOTAL_MIXERS - 5], 0},
  49. {wavetable[52], 0, mixer[13], 0}, {wavetable[53], 0, mixer[13], 1}, {wavetable[54], 0, mixer[13], 2}, {wavetable[55], 0, mixer[13], 3}, {mixer[13], 0, mixer[TOTAL_MIXERS - 5], 1},
  50. {wavetable[56], 0, mixer[14], 0}, {wavetable[57], 0, mixer[14], 1}, {wavetable[58], 0, mixer[14], 2}, {wavetable[59], 0, mixer[14], 3}, {mixer[14], 0, mixer[TOTAL_MIXERS - 5], 2},
  51. {wavetable[60], 0, mixer[15], 0}, {wavetable[61], 0, mixer[15], 1}, {wavetable[62], 0, mixer[15], 2}, {wavetable[63], 0, mixer[15], 3}, {mixer[15], 0, mixer[TOTAL_MIXERS - 5], 3},
  52. {mixer[TOTAL_MIXERS - 2], 0, mixer[TOTAL_MIXERS - 1], 0},
  53. {mixer[TOTAL_MIXERS - 3], 0, mixer[TOTAL_MIXERS - 1], 1},
  54. {mixer[TOTAL_MIXERS - 4], 0, mixer[TOTAL_MIXERS - 1], 2},
  55. {mixer[TOTAL_MIXERS - 5], 0, mixer[TOTAL_MIXERS - 1], 3},
  56. {mixer[TOTAL_MIXERS - 1], 0, i2s1, 0},
  57. {mixer[TOTAL_MIXERS - 1], 0, i2s1, 1},
  58. };
  59. Bounce buttons[] = { {0, 15}, {1, 15}, {2, 15}, };
  60. const int TOTAL_BUTTONS = sizeof(buttons) / sizeof(Bounce);
  61. void guitarHeroMode();
  62. void printVoices();
  63. void setVolume() {
  64. sgtl5000_1.volume(0.8*(analogRead(PIN_A2) - 1) / 1022.0);
  65. }
  66. struct voice_t {
  67. int wavetable_id;
  68. byte channel;
  69. byte note;
  70. };
  71. voice_t voices[TOTAL_VOICES];
  72. IntervalTimer midiMapTimer;
  73. IntervalTimer guitarHeroTimer;
  74. IntervalTimer volumeTimer;
  75. void setup() {
  76. Serial.begin(115200);
  77. pinMode(0, INPUT_PULLUP);
  78. pinMode(1, INPUT_PULLUP);
  79. pinMode(2, INPUT_PULLUP);
  80. AudioMemory(120);
  81. sgtl5000_1.enable();
  82. sgtl5000_1.volume(0.8);
  83. for (int i = 0; i < TOTAL_VOICES; ++i) {
  84. wavetable[i].setInstrument(Pizzicato);
  85. wavetable[i].amplitude(1);
  86. voices[i].wavetable_id = i;
  87. voices[i].channel = voices[i].note = 0xFF;
  88. }
  89. for (int i = 0; i < TOTAL_MIXERS - 1; ++i)
  90. for (int j = 0; j < 4; ++j)
  91. mixer[i].gain(j, 0.50);
  92. for (int i = 0; i < 4; ++i)
  93. mixer[TOTAL_MIXERS - 1].gain(i, i < SECONDARY_MIXERS ? 1.0 / SECONDARY_MIXERS : 0.0);
  94. Serial.println("USB Host Testing");
  95. myusb.begin();
  96. keyboard1.attachPress(OnPress);
  97. keyboard2.attachPress(OnPress);
  98. midi1.setHandleNoteOff(OnNoteOff);
  99. midi1.setHandleNoteOn(OnNoteOn);
  100. midi1.setHandleControlChange(OnControlChange);
  101. //volumeTimer.begin(setVolume, 100000);
  102. guitarHeroTimer.begin(guitarHeroMode, 1000000 / 120);
  103. //midiMapTimer.begin(printVoices, 5000);
  104. delay(2000);
  105. }
  106. void loop() {
  107. myusb.Task();
  108. midi1.read();
  109. //for (int i = 0; i < TOTAL_BUTTONS; ++i) buttons[i].update();
  110. //if (buttons[0].fallingEdge()) AudioSynthWavetable::print_performance();
  111. //if (buttons[1].risingEdge()) {
  112. // midiMapTimer.end();
  113. // Serial.print('\n');
  114. //}
  115. //if (buttons[1].fallingEdge()) midiMapTimer.begin(printVoices, 5000);
  116. //if (buttons[2].risingEdge()) guitarHeroTimer.end();
  117. //if (buttons[2].fallingEdge())
  118. // guitarHeroTimer.begin(guitarHeroMode, 1000000/60);
  119. }
  120. int allocateVoice(byte channel, byte note);
  121. int findVoice(byte channel, byte note);
  122. void freeVoices();
  123. int used_voices = 0;
  124. int stopped_voices = 0;
  125. int evict_voice = 0;
  126. int notes_played = 0;
  127. void OnPress(int key)
  128. {
  129. Serial.print("key '");
  130. Serial.print((char)key);
  131. Serial.print("' ");
  132. Serial.println(key);
  133. //Serial.print("key ");
  134. //Serial.print((char)keyboard1.getKey());
  135. //Serial.print(" ");
  136. //Serial.print((char)keyboard2.getKey());
  137. //Serial.println();
  138. }
  139. void OnControlChange(byte channel, byte control, byte value)
  140. {
  141. Serial.print("Control Change, ch=");
  142. Serial.print(channel);
  143. Serial.print(", control=");
  144. Serial.print(control);
  145. Serial.print(", value=");
  146. Serial.print(value);
  147. Serial.println();
  148. }
  149. void OnNoteOn(byte channel, byte note, byte velocity) {
  150. notes_played++;
  151. #ifdef DEBUG_ALLOC
  152. //Serial.printf("**** NoteOn: channel==%hhu,note==%hhu ****\n", channel, note);
  153. printVoices();
  154. #endif //DEBUG_ALLOC
  155. freeVoices();
  156. int wavetable_id = allocateVoice(channel, note);
  157. switch (channel) {
  158. case 1:
  159. wavetable[wavetable_id].setInstrument(BasicFlute1);
  160. break;
  161. case 2:
  162. wavetable[wavetable_id].setInstrument(FrenchHorns);
  163. break;
  164. case 3:
  165. wavetable[wavetable_id].setInstrument(Ocarina);
  166. break;
  167. case 4:
  168. wavetable[wavetable_id].setInstrument(Ocarina);
  169. break;
  170. case 5:
  171. wavetable[wavetable_id].setInstrument(Pizzicato);
  172. break;
  173. default:
  174. wavetable[wavetable_id].setInstrument(Pizzicato);
  175. break;
  176. }
  177. wavetable[wavetable_id].playNote(note, velocity);
  178. #ifdef DEBUG_ALLOC
  179. printVoices();
  180. #endif //DEBUG_ALLOC
  181. }
  182. void OnNoteOff(byte channel, byte note, byte velocity) {
  183. #ifdef DEBUG_ALLOC
  184. //Serial.printf("\n**** NoteOff: channel==%hhu,note==%hhu ****", channel, note);
  185. printVoices();
  186. #endif //DEBUG_ALLOC
  187. int wavetable_id = findVoice(channel, note);
  188. if (wavetable_id != TOTAL_VOICES)
  189. wavetable[wavetable_id].stop();
  190. #ifdef DEBUG_ALLOC
  191. printVoices();
  192. #endif //DEBUG_ALLOC
  193. }
  194. int allocateVoice(byte channel, byte note) {
  195. int i;
  196. int nonfree_voices = stopped_voices + used_voices;
  197. if (nonfree_voices < TOTAL_VOICES) {
  198. for (i = nonfree_voices; i < TOTAL_VOICES && voices[i].channel != channel; ++i);
  199. if (i < TOTAL_VOICES) {
  200. voice_t temp = voices[i];
  201. voices[i] = voices[nonfree_voices];
  202. voices[nonfree_voices] = temp;
  203. }
  204. i = nonfree_voices;
  205. used_voices++;
  206. }
  207. else {
  208. if (stopped_voices) {
  209. i = evict_voice % stopped_voices;
  210. voice_t temp = voices[i];
  211. stopped_voices--;
  212. voices[i] = voices[stopped_voices];
  213. voices[stopped_voices] = temp;
  214. used_voices++;
  215. i = stopped_voices;
  216. }
  217. else
  218. i = evict_voice;
  219. }
  220. voices[i].channel = channel;
  221. voices[i].note = note;
  222. evict_voice++;
  223. evict_voice %= TOTAL_VOICES;
  224. return voices[i].wavetable_id;
  225. }
  226. int findVoice(byte channel, byte note) {
  227. int i;
  228. //find match
  229. int nonfree_voices = stopped_voices + used_voices;
  230. for (i = stopped_voices; i < nonfree_voices && !(voices[i].channel == channel && voices[i].note == note); ++i);
  231. //return TOTAL_VOICES if no match
  232. if (i == (nonfree_voices)) return TOTAL_VOICES;
  233. voice_t temp = voices[i];
  234. voices[i] = voices[stopped_voices];
  235. voices[stopped_voices] = temp;
  236. --used_voices;
  237. return voices[stopped_voices++].wavetable_id;
  238. }
  239. void freeVoices() {
  240. for (int i = 0; i < stopped_voices; i++)
  241. if (wavetable[voices[i].wavetable_id].isPlaying() == false) {
  242. voice_t temp = voices[i];
  243. --stopped_voices;
  244. voices[i] = voices[stopped_voices];
  245. int nonfree_voices = stopped_voices + used_voices;
  246. voices[stopped_voices] = voices[nonfree_voices];
  247. voices[nonfree_voices] = temp;
  248. }
  249. }
  250. void guitarHeroMode() { // now unicorn friendly
  251. const int RESET = 4;
  252. const int MIDI_NOTES = 128;
  253. static char line[MIDI_NOTES + 1] = { 0 };
  254. static int accumulated = 0;
  255. if (!accumulated) {
  256. for (int i = 0; i < MIDI_NOTES; ++i) line[i] = '-';
  257. ++accumulated;
  258. }
  259. for (int i = stopped_voices; i < used_voices + stopped_voices; ++i) line[voices[i].note] = '*';
  260. if (accumulated++ == RESET) {
  261. Serial.println(line);
  262. accumulated = 0;
  263. }
  264. }
  265. const char* note_map[] = {
  266. "C","C#","D","D#","E","F","F#","G","G#","A","A#","B"
  267. };
  268. void printVoices() {
  269. static int last_notes_played = notes_played;
  270. if (last_notes_played == notes_played)
  271. return;
  272. last_notes_played = notes_played;
  273. int usage = AudioProcessorUsage();
  274. Serial.printf("\nCPU:%03i voices:%02i CPU/Voice:%02i evict:%02i", usage, used_voices, usage / used_voices, evict_voice);
  275. for (int i = 0; i < used_voices; ++i)
  276. Serial.printf(" %02hhu %-2s", voices[i].channel, note_map[voices[i].note % 12]);
  277. }