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.

180 lines
3.7KB

  1. // Implement the midi player inside the Audio library.
  2. // This uses the new version of the waveform generator code
  3. // See PlayMidiTones for code which uses the old version
  4. #include <Audio.h>
  5. #include <Wire.h>
  6. //#include <WM8731.h>
  7. #include <SD.h>
  8. #include <SPI.h>
  9. #include "audiotest.h"
  10. #include "arm_math.h"
  11. #include "PlaySynthMusic.h"
  12. unsigned char *sp = score;
  13. #define AMPLITUDE (0.4)
  14. // The midi file has more than 8 channels
  15. // Those above 7 will be mapped to 0, 1 etc.
  16. AudioSynthWaveform sine0;
  17. AudioSynthWaveform sine1;
  18. AudioSynthWaveform sine2;
  19. AudioSynthWaveform sine3;
  20. AudioSynthWaveform sine4;
  21. AudioSynthWaveform sine5;
  22. AudioSynthWaveform sine6;
  23. AudioSynthWaveform sine7;
  24. AudioSynthWaveform *waves[8] = {
  25. &sine0,
  26. &sine1,
  27. &sine2,
  28. &sine3,
  29. &sine4,
  30. &sine5,
  31. &sine6,
  32. &sine7,
  33. };
  34. AudioMixer4 mixer1;
  35. AudioMixer4 mixer2;
  36. AudioOutputI2S audioOut;
  37. AudioConnection c0(sine0, 0, mixer1, 0);
  38. AudioConnection c1(sine1, 0, mixer1, 1);
  39. AudioConnection c2(sine2, 0, mixer1, 2);
  40. AudioConnection c3(sine3, 0, mixer1, 3);
  41. AudioConnection c4(sine4, 0, mixer2, 0);
  42. AudioConnection c5(sine5, 0, mixer2, 1);
  43. AudioConnection c6(sine6, 0, mixer2, 2);
  44. AudioConnection c7(sine7, 0, mixer2, 3);
  45. AudioConnection c11(mixer1, 0, audioOut, 0);
  46. AudioConnection c12(mixer2, 0, audioOut, 1);
  47. //AudioControl_WM8731 codec;
  48. AudioControlSGTL5000 codec;
  49. int volume = 50;
  50. // allocate a wave type to each channel.
  51. // The types used and their order is purely arbitrary.
  52. short wave_type[8] = {
  53. TONE_TYPE_SINE,
  54. TONE_TYPE_SQUARE,
  55. TONE_TYPE_SAWTOOTH,
  56. TONE_TYPE_TRIANGLE,
  57. TONE_TYPE_SINE,
  58. TONE_TYPE_SQUARE,
  59. TONE_TYPE_SAWTOOTH,
  60. TONE_TYPE_TRIANGLE,
  61. };
  62. void setup()
  63. {
  64. Serial.begin(115200);
  65. while (!Serial) ;
  66. delay(3000);
  67. // Audio connections require memory to work.
  68. // The memory usage code indicates that 8 is the maximum
  69. // so give it 10 just to be sure.
  70. AudioMemory(10);
  71. codec.enable();
  72. codec.volume(volume);
  73. // I want output on the line out too
  74. // Comment this if you don't it
  75. codec.unmuteLineout();
  76. // Set the ramp time for each wave object
  77. for(int i = 0; i < 8;i++) {
  78. waves[i]->set_ramp_length(88);
  79. }
  80. Serial.println("Begin PlayMidiTones");
  81. Serial.println("setup done");
  82. // Initialize processor and memory measurements
  83. AudioProcessorUsageMaxReset();
  84. AudioMemoryUsageMaxReset();
  85. }
  86. unsigned long last_time = millis();
  87. void loop()
  88. {
  89. unsigned char c,opcode,chan;
  90. unsigned long d_time;
  91. // Change this to if(1) for measurement output
  92. if(0) {
  93. /*
  94. For PlaySynthMusic this produces:
  95. Proc = 20 (21), Mem = 2 (8)
  96. */
  97. if(millis() - last_time >= 5000) {
  98. Serial.print("Proc = ");
  99. Serial.print(AudioProcessorUsage());
  100. Serial.print(" (");
  101. Serial.print(AudioProcessorUsageMax());
  102. Serial.print("), Mem = ");
  103. Serial.print(AudioMemoryUsage());
  104. Serial.print(" (");
  105. Serial.print(AudioMemoryUsageMax());
  106. Serial.println(")");
  107. last_time = millis();
  108. }
  109. }
  110. // Volume control
  111. int n = analogRead(15);
  112. if (n != volume) {
  113. volume = n;
  114. codec.volume((float)n / 10.23);
  115. }
  116. c = *sp++;
  117. opcode = c & 0xf0;
  118. // was 0x0f but I'm only handling 8 channels
  119. // This will map Ch 8->Ch 0, Ch 9->Ch 1, etc.
  120. chan = c & 0x07;
  121. if(c < 0x80) {
  122. // Delay
  123. d_time = (c << 8) | *sp++;
  124. delay(d_time);
  125. return;
  126. }
  127. if(*sp == CMD_STOP) {
  128. Serial.println("DONE");
  129. while(1);
  130. }
  131. // It is a command
  132. // Stop the note on 'chan'
  133. if(opcode == CMD_STOPNOTE) {
  134. waves[chan]->amplitude(0);
  135. return;
  136. }
  137. // Play the note on 'chan'
  138. if(opcode == CMD_PLAYNOTE) {
  139. waves[chan]->begin(AMPLITUDE,tune_frequencies2_PGM[*sp++],
  140. wave_type[chan]);
  141. return;
  142. }
  143. // replay the tune
  144. if(opcode == CMD_RESTART) {
  145. sp = score;
  146. return;
  147. }
  148. }