Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

349 Zeilen
11KB

  1. /* Play Zelda music.
  2. Requires Teensy 3.6 due to 520 kbytes of wavetable data
  3. Requires Audio Shield: https://www.pjrc.com/store/teensy3_audio.html
  4. */
  5. #include <Bounce.h>
  6. #include <Audio.h>
  7. #include <Wire.h>
  8. #include <SPI.h>
  9. #include <SD.h>
  10. #include <SerialFlash.h>
  11. #include "Pizzicato_samples.h"
  12. #include "FrenchHorns_samples.h"
  13. #include "Viola_samples.h"
  14. #include "BasicFlute1_samples.h"
  15. #include "PlaySynthMusic.h"
  16. //#define DEBUG_ALLOC
  17. unsigned char *sp = score;
  18. const int TOTAL_VOICES = 64;
  19. const int TOTAL_MIXERS = 21;
  20. const int SECONDARY_MIXERS = 4;
  21. AudioControlSGTL5000 sgtl5000_1;
  22. AudioSynthWavetable wavetable[TOTAL_VOICES];
  23. AudioMixer4 mixer[TOTAL_MIXERS];
  24. AudioOutputI2S i2s1;
  25. AudioConnection patchCord[] = {
  26. {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},
  27. {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},
  28. {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},
  29. {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},
  30. {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},
  31. {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},
  32. {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},
  33. {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},
  34. {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},
  35. {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},
  36. {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},
  37. {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},
  38. {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},
  39. {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},
  40. {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},
  41. {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},
  42. {mixer[TOTAL_MIXERS-2], 0, mixer[TOTAL_MIXERS-1], 0},
  43. {mixer[TOTAL_MIXERS-3], 0, mixer[TOTAL_MIXERS-1], 1},
  44. {mixer[TOTAL_MIXERS-4], 0, mixer[TOTAL_MIXERS-1], 2},
  45. {mixer[TOTAL_MIXERS-5], 0, mixer[TOTAL_MIXERS-1], 3},
  46. {mixer[TOTAL_MIXERS-1], 0, i2s1, 0},
  47. {mixer[TOTAL_MIXERS-1], 0, i2s1, 1},
  48. };
  49. Bounce buttons[] = { {0, 15}, {1, 15}, {2, 15}, };
  50. const int TOTAL_BUTTONS = sizeof(buttons) / sizeof(Bounce);
  51. void guitarHeroMode();
  52. void printVoices();
  53. void setVolume() {
  54. sgtl5000_1.volume(0.8*(analogRead(PIN_A2)-1)/1022.0);
  55. }
  56. struct voice_t {
  57. int wavetable_id;
  58. byte channel;
  59. byte note;
  60. };
  61. voice_t voices[TOTAL_VOICES];
  62. IntervalTimer midiMapTimer;
  63. IntervalTimer guitarHeroTimer;
  64. IntervalTimer volumeTimer;
  65. void setup() {
  66. Serial.begin(115200);
  67. pinMode(0, INPUT_PULLUP);
  68. pinMode(1, INPUT_PULLUP);
  69. pinMode(2, INPUT_PULLUP);
  70. AudioMemory(120);
  71. sgtl5000_1.enable();
  72. sgtl5000_1.volume(0.8);
  73. for (int i = 0; i < TOTAL_VOICES; ++i) {
  74. wavetable[i].setInstrument(Pizzicato);
  75. wavetable[i].amplitude(1);
  76. voices[i].wavetable_id = i;
  77. voices[i].channel = voices[i].note = 0xFF;
  78. }
  79. for (int i = 0; i < TOTAL_MIXERS-1; ++i)
  80. for (int j = 0; j < 4; ++j)
  81. mixer[i].gain(j, 0.25);
  82. for (int i = 0; i < 4; ++i)
  83. mixer[TOTAL_MIXERS - 1].gain(i, i < SECONDARY_MIXERS ? 1.0 / SECONDARY_MIXERS : 0.0);
  84. usbMIDI.setHandleNoteOn(OnNoteOn);
  85. usbMIDI.setHandleNoteOff(OnNoteOff);
  86. //volumeTimer.begin(setVolume, 100000);
  87. guitarHeroTimer.begin(guitarHeroMode, 1000000/120);
  88. //midiMapTimer.begin(printVoices, 5000);
  89. delay(2000);
  90. }
  91. void loop() {
  92. unsigned char c,opcode,chan;
  93. unsigned long d_time;
  94. // Volume control
  95. // uncomment if you have a volume pot soldered to your audio shield
  96. /*
  97. int n = analogRead(15);
  98. if (n != volume) {
  99. volume = n;
  100. codec.volume((float)n / 1023);
  101. }
  102. */
  103. // read the next note from the table
  104. c = *sp++;
  105. opcode = c & 0xF0;
  106. chan = c & 0x0F;
  107. if(c < 0x80) {
  108. // Delay
  109. d_time = (c << 8) | *sp++;
  110. delay(d_time);
  111. return;
  112. }
  113. if(*sp == CMD_STOP) {
  114. for (int i=0; i<TOTAL_VOICES; i++) {
  115. wavetable[chan].stop();
  116. }
  117. while(1);
  118. }
  119. // It is a command
  120. //Change the instrument for generator
  121. if(opcode == CMD_CHANGEINST) {
  122. unsigned char inst = *sp++;
  123. wavetable[chan].stop();
  124. switch(inst) {
  125. case 48:
  126. wavetable[chan].setInstrument(Viola);
  127. break;
  128. case 57:
  129. wavetable[chan].setInstrument(BasicFlute1);
  130. break;
  131. default:
  132. wavetable[chan].setInstrument(FrenchHorns);
  133. break;
  134. }
  135. return;
  136. }
  137. // Stop the note on 'chan'
  138. if(opcode == CMD_STOPNOTE) {
  139. wavetable[chan].stop();
  140. return;
  141. }
  142. // Play the note on 'chan'
  143. if(opcode == CMD_PLAYNOTE) {
  144. unsigned char note = *sp++;
  145. unsigned char velocity = *sp++;
  146. wavetable[chan].playNote((byte)note);
  147. //OnNoteOn(chan, (byte)note, (byte)velocity);
  148. return;
  149. }
  150. // replay the tune
  151. if(opcode == CMD_RESTART) {
  152. sp = score;
  153. return;
  154. }
  155. usbMIDI.read();
  156. //for (int i = 0; i < TOTAL_BUTTONS; ++i) buttons[i].update();
  157. //if (buttons[0].fallingEdge()) AudioSynthWavetable::print_performance();
  158. //if (buttons[1].risingEdge()) {
  159. // midiMapTimer.end();
  160. // Serial.print('\n');
  161. //}
  162. //if (buttons[1].fallingEdge()) midiMapTimer.begin(printVoices, 5000);
  163. //if (buttons[2].risingEdge()) guitarHeroTimer.end();
  164. //if (buttons[2].fallingEdge())
  165. // guitarHeroTimer.begin(guitarHeroMode, 1000000/60);
  166. }
  167. int allocateVoice(byte channel, byte note);
  168. int findVoice(byte channel, byte note);
  169. void freeVoices();
  170. int used_voices = 0;
  171. int stopped_voices = 0;
  172. int evict_voice = 0;
  173. int notes_played = 0;
  174. void OnNoteOn(byte channel, byte note, byte velocity) {
  175. notes_played++;
  176. #ifdef DEBUG_ALLOC
  177. //Serial.printf("**** NoteOn: channel==%hhu,note==%hhu ****\n", channel, note);
  178. printVoices();
  179. #endif //DEBUG_ALLOC
  180. freeVoices();
  181. int wavetable_id = allocateVoice(channel, note);
  182. switch (channel) {
  183. case 1:
  184. wavetable[wavetable_id].setInstrument(Pizzicato);
  185. break;
  186. case 2:
  187. wavetable[wavetable_id].setInstrument(Pizzicato);
  188. break;
  189. case 3:
  190. wavetable[wavetable_id].setInstrument(Pizzicato);
  191. break;
  192. case 4:
  193. wavetable[wavetable_id].setInstrument(Pizzicato);
  194. break;
  195. case 5:
  196. wavetable[wavetable_id].setInstrument(Pizzicato);
  197. break;
  198. default:
  199. wavetable[wavetable_id].setInstrument(Pizzicato);
  200. break;
  201. }
  202. wavetable[wavetable_id].playNote(note);
  203. #ifdef DEBUG_ALLOC
  204. printVoices();
  205. #endif //DEBUG_ALLOC
  206. }
  207. void OnNoteOff(byte channel, byte note, byte velocity) {
  208. #ifdef DEBUG_ALLOC
  209. //Serial.printf("\n**** NoteOff: channel==%hhu,note==%hhu ****", channel, note);
  210. printVoices();
  211. #endif //DEBUG_ALLOC
  212. int wavetable_id = findVoice(channel, note);
  213. if (wavetable_id != TOTAL_VOICES)
  214. wavetable[wavetable_id].stop();
  215. #ifdef DEBUG_ALLOC
  216. printVoices();
  217. #endif //DEBUG_ALLOC
  218. }
  219. int allocateVoice(byte channel, byte note) {
  220. int i;
  221. int nonfree_voices = stopped_voices + used_voices;
  222. if (nonfree_voices < TOTAL_VOICES) {
  223. for (i = nonfree_voices; i < TOTAL_VOICES && voices[i].channel != channel; ++i);
  224. if (i < TOTAL_VOICES) {
  225. voice_t temp = voices[i];
  226. voices[i] = voices[nonfree_voices];
  227. voices[nonfree_voices] = temp;
  228. }
  229. i = nonfree_voices;
  230. used_voices++;
  231. } else {
  232. if (stopped_voices) {
  233. i = evict_voice % stopped_voices;
  234. voice_t temp = voices[i];
  235. stopped_voices--;
  236. voices[i] = voices[stopped_voices];
  237. voices[stopped_voices] = temp;
  238. used_voices++;
  239. i = stopped_voices;
  240. }
  241. else
  242. i = evict_voice;
  243. }
  244. voices[i].channel = channel;
  245. voices[i].note = note;
  246. evict_voice++;
  247. evict_voice %= TOTAL_VOICES;
  248. return voices[i].wavetable_id;
  249. }
  250. int findVoice(byte channel, byte note) {
  251. int i;
  252. //find match
  253. int nonfree_voices = stopped_voices + used_voices;
  254. for (i = stopped_voices; i < nonfree_voices && !(voices[i].channel == channel && voices[i].note == note); ++i);
  255. //return TOTAL_VOICES if no match
  256. if (i == (nonfree_voices)) return TOTAL_VOICES;
  257. voice_t temp = voices[i];
  258. voices[i] = voices[stopped_voices];
  259. voices[stopped_voices] = temp;
  260. --used_voices;
  261. return voices[stopped_voices++].wavetable_id;
  262. }
  263. void freeVoices() {
  264. for (int i = 0; i < stopped_voices; i++)
  265. if (wavetable[voices[i].wavetable_id].isPlaying() == false) {
  266. voice_t temp = voices[i];
  267. --stopped_voices;
  268. voices[i] = voices[stopped_voices];
  269. int nonfree_voices = stopped_voices + used_voices;
  270. voices[stopped_voices] = voices[nonfree_voices];
  271. voices[nonfree_voices] = temp;
  272. }
  273. }
  274. void guitarHeroMode() { // now unicorn friendly
  275. const int RESET = 4;
  276. const int MIDI_NOTES = 128;
  277. static char line[MIDI_NOTES+1] = { 0 };
  278. static int accumulated = 0;
  279. if (!accumulated) {
  280. for (int i = 0; i < MIDI_NOTES; ++i) line[i] = '-';
  281. ++accumulated;
  282. }
  283. for (int i = stopped_voices; i < used_voices+stopped_voices; ++i) line[voices[i].note] = '*';
  284. if (accumulated == RESET) {
  285. Serial.println(line);
  286. accumulated = 0;
  287. } else {
  288. ++accumulated;
  289. }
  290. }
  291. const char* note_map[] = {
  292. "C","C#","D","D#","E","F","F#","G","G#","A","A#","B"
  293. };
  294. void printVoices() {
  295. static int last_notes_played = notes_played;
  296. if (last_notes_played == notes_played)
  297. return;
  298. last_notes_played = notes_played;
  299. int usage = AudioProcessorUsage();
  300. Serial.printf("\nCPU:%03i voices:%02i CPU/Voice:%02i evict:%02i", usage, used_voices, usage/used_voices, evict_voice);
  301. for (int i = 0; i < used_voices; ++i)
  302. Serial.printf(" %02hhu %-2s", voices[i].channel, note_map[voices[i].note%12]);
  303. }