PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

343 lines
13KB

  1. /* Play notes when your computer sends USB MIDI messages.
  2. To use this example, you must run software on your computer which
  3. sends MIDI. Tools > USB Type must be set to MIDI when uploading.
  4. Requires Teensy 3.6 due to 820 kbytes of wavetable data
  5. Requires Audio Shield: https://www.pjrc.com/store/teensy3_audio.html
  6. */
  7. #include "bassoon_samples.h"
  8. #include "clarinet_samples.h"
  9. #include "distortiongt_samples.h"
  10. #include "epiano_samples.h"
  11. #include "flute_samples.h"
  12. #include "frenchhorn_samples.h"
  13. #include "glockenspiel_samples.h"
  14. #include "gtfretnoise_samples.h"
  15. #include "harmonica_samples.h"
  16. #include "harp_samples.h"
  17. #include "mutedgtr_samples.h"
  18. #include "nylonstrgtr_samples.h"
  19. #include "oboe_samples.h"
  20. #include "overdrivegt_samples.h"
  21. #include "recorder_samples.h"
  22. #include "standard_DRUMS_samples.h"
  23. #include "steelstrgtr_samples.h"
  24. #include "strings_samples.h"
  25. #include "timpani_samples.h"
  26. #include "trombone_samples.h"
  27. #include "trumpet_samples.h"
  28. #include "tuba_samples.h"
  29. #include "piano_samples.h"
  30. #include "vibraphone_samples.h"
  31. #include <Bounce.h>
  32. #include <Audio.h>
  33. #include <Wire.h>
  34. #include <SPI.h>
  35. #include <SD.h>
  36. #include <SerialFlash.h>
  37. //#define DEBUG_ALLOC
  38. const int TOTAL_VOICES = 64;
  39. const int TOTAL_MIXERS = 21;
  40. const int SECONDARY_MIXERS = 4;
  41. AudioControlSGTL5000 sgtl5000_1;
  42. AudioSynthWavetable wavetable[TOTAL_VOICES];
  43. AudioMixer4 mixer[TOTAL_MIXERS];
  44. AudioOutputI2S i2s1;
  45. AudioConnection patchCord[] = {
  46. {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},
  47. {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},
  48. {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},
  49. {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},
  50. {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},
  51. {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},
  52. {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},
  53. {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},
  54. {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},
  55. {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},
  56. {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},
  57. {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},
  58. {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},
  59. {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},
  60. {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},
  61. {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},
  62. {mixer[TOTAL_MIXERS - 2], 0, mixer[TOTAL_MIXERS - 1], 0},
  63. {mixer[TOTAL_MIXERS - 3], 0, mixer[TOTAL_MIXERS - 1], 1},
  64. {mixer[TOTAL_MIXERS - 4], 0, mixer[TOTAL_MIXERS - 1], 2},
  65. {mixer[TOTAL_MIXERS - 5], 0, mixer[TOTAL_MIXERS - 1], 3},
  66. {mixer[TOTAL_MIXERS - 1], 0, i2s1, 0},
  67. {mixer[TOTAL_MIXERS - 1], 0, i2s1, 1},
  68. };
  69. Bounce buttons[] = { {0, 15}, {1, 15}, {2, 15}, };
  70. const int TOTAL_BUTTONS = sizeof(buttons) / sizeof(Bounce);
  71. void guitarHeroMode();
  72. void printVoices();
  73. void setVolume() {
  74. sgtl5000_1.volume(0.8*(analogRead(PIN_A2) - 1) / 1022.0);
  75. }
  76. struct voice_t {
  77. int wavetable_id;
  78. byte channel;
  79. byte note;
  80. };
  81. voice_t voices[TOTAL_VOICES];
  82. IntervalTimer midiMapTimer;
  83. IntervalTimer guitarHeroTimer;
  84. IntervalTimer volumeTimer;
  85. void setup() {
  86. Serial.begin(115200);
  87. pinMode(0, INPUT_PULLUP);
  88. pinMode(1, INPUT_PULLUP);
  89. pinMode(2, INPUT_PULLUP);
  90. AudioMemory(120);
  91. sgtl5000_1.enable();
  92. sgtl5000_1.volume(0.8);
  93. for (int i = 0; i < TOTAL_VOICES; ++i) {
  94. wavetable[i].setInstrument(nylonstrgtr);
  95. voices[i].wavetable_id = i;
  96. voices[i].channel = voices[i].note = 0xFF;
  97. }
  98. for (int i = 0; i < TOTAL_MIXERS - 1; ++i)
  99. for (int j = 0; j < 4; ++j)
  100. mixer[i].gain(j, 0.50);
  101. for (int i = 0; i < 4; ++i)
  102. mixer[TOTAL_MIXERS - 1].gain(i, i < SECONDARY_MIXERS ? 2.0 / SECONDARY_MIXERS : 0.0);
  103. usbMIDI.setHandleNoteOn(OnNoteOn);
  104. usbMIDI.setHandleNoteOff(OnNoteOff);
  105. usbMIDI.setHandleProgramChange(OnProgramChange);
  106. usbMIDI.setHandleControlChange(OnControlChange);
  107. //volumeTimer.begin(setVolume, 100000);
  108. //guitarHeroTimer.begin(guitarHeroMode, 1000000 / 120);
  109. //midiMapTimer.begin(printVoices, 5000);
  110. delay(2000);
  111. }
  112. void loop() {
  113. usbMIDI.read();
  114. //for (int i = 0; i < TOTAL_BUTTONS; ++i) buttons[i].update();
  115. //if (buttons[0].fallingEdge()) AudioSynthWavetable::print_performance();
  116. //if (buttons[1].risingEdge()) {
  117. // midiMapTimer.end();
  118. // Serial.print('\n');
  119. //}
  120. //if (buttons[1].fallingEdge()) midiMapTimer.begin(printVoices, 5000);
  121. //if (buttons[2].risingEdge()) guitarHeroTimer.end();
  122. //if (buttons[2].fallingEdge())
  123. // guitarHeroTimer.begin(guitarHeroMode, 1000000/60);
  124. }
  125. int allocateVoice(byte channel, byte note);
  126. int findVoice(byte channel, byte note);
  127. void freeVoices();
  128. int used_voices = 0;
  129. int stopped_voices = 0;
  130. int evict_voice = 0;
  131. int notes_played = 0;
  132. void OnPress(int key)
  133. {
  134. Serial.print("key '");
  135. Serial.print((char)key);
  136. Serial.print("' ");
  137. Serial.println(key);
  138. //Serial.print("key ");
  139. //Serial.print((char)keyboard1.getKey());
  140. //Serial.print(" ");
  141. //Serial.print((char)keyboard2.getKey());
  142. //Serial.println();
  143. }
  144. const AudioSynthWavetable::instrument_data * const midi_map[] = {
  145. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 000: pianos
  146. &vibraphone, &vibraphone, &vibraphone, &vibraphone, &vibraphone, &vibraphone, &vibraphone, &vibraphone, // 008: chrom percus
  147. &harmonica, &harmonica, &harmonica, &harmonica, &harmonica, &harmonica, &harmonica, &harmonica, // 016: organs
  148. &nylonstrgtr, &steelstrgtr, &nylonstrgtr, &nylonstrgtr, &mutedgtr, &overdrivegt, &distortiongt, &nylonstrgtr, // 024: guitars
  149. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 032: bass
  150. &strings, &strings, &strings, &strings, &strings, &strings, &harp, &timpani, // 040: strings
  151. &strings, &strings, &strings, &strings, &strings, &strings, &strings, &strings, // 048: ensemble
  152. &trumpet, &trombone, &tuba, &frenchhorn, &frenchhorn, &frenchhorn, &frenchhorn, &frenchhorn, // 056: brass
  153. &oboe, &oboe, &oboe, &oboe, &oboe, &oboe, &bassoon, &clarinet, // 064: reed
  154. &flute, &flute, &recorder, &flute, &flute, &flute, &flute, &flute, // 072: pipe
  155. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 080: synth lead
  156. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 088: synth pad
  157. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 096: synth effect
  158. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, // 104: ethnic
  159. &timpani, &timpani, &timpani, &timpani, &timpani, &timpani, &timpani, &timpani, // 112: percussive
  160. &gtfretnoise, &gtfretnoise, &gtfretnoise, &gtfretnoise, &gtfretnoise, &gtfretnoise, &gtfretnoise, &gtfretnoise, // 120: sound effects
  161. };
  162. const AudioSynthWavetable::instrument_data * channel_map[17] = {
  163. &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, &piano, &standard_DRUMS, &piano, &piano, &piano, &piano, &piano, &piano,
  164. };
  165. int channel_vol[] = {
  166. 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
  167. };
  168. void OnControlChange(byte channel, byte control, byte value)
  169. {
  170. switch (control) {
  171. case 7: //volume
  172. channel_vol[channel] = value;
  173. break;
  174. default:
  175. break;
  176. }
  177. Serial.print("Control Change, ch=");
  178. Serial.print(channel);
  179. Serial.print(", control=");
  180. Serial.print(control);
  181. Serial.print(", value=");
  182. Serial.print(value);
  183. Serial.println();
  184. }
  185. void OnProgramChange(byte channel, byte program) {
  186. channel_map[channel] = channel != 10 ? midi_map[program] : &standard_DRUMS;
  187. }
  188. void OnNoteOn(byte channel, byte note, byte velocity) {
  189. notes_played++;
  190. #ifdef DEBUG_ALLOC
  191. //Serial.printf("**** NoteOn: channel==%hhu,note==%hhu ****\n", channel, note);
  192. printVoices();
  193. #endif //DEBUG_ALLOC
  194. freeVoices();
  195. int wavetable_id = allocateVoice(channel, note);
  196. wavetable[wavetable_id].setInstrument(*channel_map[channel]);
  197. wavetable[wavetable_id].playNote(note, (velocity*channel_vol[channel] + 0x80) >> 7);
  198. #ifdef DEBUG_ALLOC
  199. printVoices();
  200. #endif //DEBUG_ALLOC
  201. }
  202. void OnNoteOff(byte channel, byte note, byte velocity) {
  203. #ifdef DEBUG_ALLOC
  204. //Serial.printf("\n**** NoteOff: channel==%hhu,note==%hhu ****", channel, note);
  205. printVoices();
  206. #endif //DEBUG_ALLOC
  207. int wavetable_id = findVoice(channel, note);
  208. if (wavetable_id != TOTAL_VOICES)
  209. wavetable[wavetable_id].stop();
  210. #ifdef DEBUG_ALLOC
  211. printVoices();
  212. #endif //DEBUG_ALLOC
  213. }
  214. int allocateVoice(byte channel, byte note) {
  215. int i;
  216. int nonfree_voices = stopped_voices + used_voices;
  217. if (nonfree_voices < TOTAL_VOICES) {
  218. for (i = nonfree_voices; i < TOTAL_VOICES && voices[i].channel != channel; ++i);
  219. if (i < TOTAL_VOICES) {
  220. voice_t temp = voices[i];
  221. voices[i] = voices[nonfree_voices];
  222. voices[nonfree_voices] = temp;
  223. }
  224. i = nonfree_voices;
  225. used_voices++;
  226. }
  227. else {
  228. if (stopped_voices) {
  229. i = evict_voice % stopped_voices;
  230. voice_t temp = voices[i];
  231. stopped_voices--;
  232. voices[i] = voices[stopped_voices];
  233. voices[stopped_voices] = temp;
  234. used_voices++;
  235. i = stopped_voices;
  236. }
  237. else
  238. i = evict_voice;
  239. }
  240. voices[i].channel = channel;
  241. voices[i].note = note;
  242. evict_voice++;
  243. evict_voice %= TOTAL_VOICES;
  244. return voices[i].wavetable_id;
  245. }
  246. int findVoice(byte channel, byte note) {
  247. int i;
  248. //find match
  249. int nonfree_voices = stopped_voices + used_voices;
  250. for (i = stopped_voices; i < nonfree_voices && !(voices[i].channel == channel && voices[i].note == note); ++i);
  251. //return TOTAL_VOICES if no match
  252. if (i == (nonfree_voices)) return TOTAL_VOICES;
  253. voice_t temp = voices[i];
  254. voices[i] = voices[stopped_voices];
  255. voices[stopped_voices] = temp;
  256. --used_voices;
  257. return voices[stopped_voices++].wavetable_id;
  258. }
  259. void freeVoices() {
  260. for (int i = 0; i < stopped_voices; i++)
  261. if (wavetable[voices[i].wavetable_id].isPlaying() == false) {
  262. voice_t temp = voices[i];
  263. --stopped_voices;
  264. voices[i] = voices[stopped_voices];
  265. int nonfree_voices = stopped_voices + used_voices;
  266. voices[stopped_voices] = voices[nonfree_voices];
  267. voices[nonfree_voices] = temp;
  268. }
  269. }
  270. void guitarHeroMode() { // now unicorn friendly
  271. const int RESET = 4;
  272. const int MIDI_NOTES = 128;
  273. static char line[MIDI_NOTES + 1] = { 0 };
  274. static int accumulated = 0;
  275. if (!accumulated) {
  276. for (int i = 0; i < MIDI_NOTES; ++i) line[i] = '-';
  277. ++accumulated;
  278. }
  279. for (int i = stopped_voices; i < used_voices + stopped_voices; ++i) line[voices[i].note] = '*';
  280. if (accumulated == RESET) {
  281. Serial.println(line);
  282. accumulated = 0;
  283. }
  284. else {
  285. ++accumulated;
  286. }
  287. }
  288. const char* note_map[] = {
  289. "C","C#","D","D#","E","F","F#","G","G#","A","A#","B"
  290. };
  291. void printVoices() {
  292. static int last_notes_played = notes_played;
  293. if (last_notes_played == notes_played)
  294. return;
  295. last_notes_played = notes_played;
  296. int usage = AudioProcessorUsage();
  297. Serial.printf("\nCPU:%03i voices:%02i CPU/Voice:%02i evict:%02i", usage, used_voices, usage / used_voices, evict_voice);
  298. for (int i = 0; i < used_voices; ++i)
  299. Serial.printf(" %02hhu %-2s", voices[i].channel, note_map[voices[i].note % 12]);
  300. }