Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

306 lines
10KB

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