| // Generated from Excel by =ROUND(2*440/32*(2^((x-9)/12)),0) for 0<x<128 | // Generated from Excel by =ROUND(2*440/32*(2^((x-9)/12)),0) for 0<x<128 | ||||
| // The lowest notes might not work, depending on the Arduino clock frequency | // The lowest notes might not work, depending on the Arduino clock frequency | ||||
| #ifdef ORIGINAL_TABLE | |||||
| const unsigned int tune_frequencies2_PGM[128] = | const unsigned int tune_frequencies2_PGM[128] = | ||||
| { | { | ||||
| 16,17,18,19,21,22,23,24,26,28,29,31,33,35,37,39,41, | 16,17,18,19,21,22,23,24,26,28,29,31,33,35,37,39,41, | ||||
| 13290,14080,14917,15804,16744,17740,18795,19912,21096, | 13290,14080,14917,15804,16744,17740,18795,19912,21096, | ||||
| 22351,23680,25088 | 22351,23680,25088 | ||||
| }; | }; | ||||
| #else | |||||
| // This is for the Teensy Audio library which specifies | |||||
| // frequencies as floating point. See make_notetab.xlsx | |||||
| const float tune_frequencies2_PGM[128] = | |||||
| { | |||||
| 8.1758, 8.6620, 9.1770, 9.7227, 10.3009, 10.9134, 11.5623, 12.2499, | |||||
| 12.9783, 13.7500, 14.5676, 15.4339, 16.3516, 17.3239, 18.3540, 19.4454, | |||||
| 20.6017, 21.8268, 23.1247, 24.4997, 25.9565, 27.5000, 29.1352, 30.8677, | |||||
| 32.7032, 34.6478, 36.7081, 38.8909, 41.2034, 43.6535, 46.2493, 48.9994, | |||||
| 51.9131, 55.0000, 58.2705, 61.7354, 65.4064, 69.2957, 73.4162, 77.7817, | |||||
| 82.4069, 87.3071, 92.4986, 97.9989, 103.8262, 110.0000, 116.5409, 123.4708, | |||||
| 130.8128, 138.5913, 146.8324, 155.5635, 164.8138, 174.6141, 184.9972, 195.9977, | |||||
| 207.6523, 220.0000, 233.0819, 246.9417, 261.6256, 277.1826, 293.6648, 311.1270, | |||||
| 329.6276, 349.2282, 369.9944, 391.9954, 415.3047, 440.0000, 466.1638, 493.8833, | |||||
| 523.2511, 554.3653, 587.3295, 622.2540, 659.2551, 698.4565, 739.9888, 783.9909, | |||||
| 830.6094, 880.0000, 932.3275, 987.7666, 1046.5023, 1108.7305, 1174.6591, 1244.5079, | |||||
| 1318.5102, 1396.9129, 1479.9777, 1567.9817, 1661.2188, 1760.0000, 1864.6550, 1975.5332, | |||||
| 2093.0045, 2217.4610, 2349.3181, 2489.0159, 2637.0205, 2793.8259, 2959.9554, 3135.9635, | |||||
| 3322.4376, 3520.0000, 3729.3101, 3951.0664, 4186.0090, 4434.9221, 4698.6363, 4978.0317, | |||||
| 5274.0409, 5587.6517, 5919.9108, 6271.9270, 6644.8752, 7040.0000, 7458.6202, 7902.1328, | |||||
| 8372.0181, 8869.8442, 9397.2726, 9956.0635, 10548.0818, 11175.3034, 11839.8215, 12543.8540 | |||||
| }; | |||||
| #endif | |||||
| #define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */ | #define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */ | ||||
| #define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */ | #define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */ |
| // Implement the midi player inside the Audio library. | // Implement the midi player inside the Audio library. | ||||
| // This uses the new version of the waveform generator code | // This uses the new version of the waveform generator code | ||||
| // See PlayMidiTones for code which uses the old version | // See PlayMidiTones for code which uses the old version | ||||
| #include <Audio.h> | #include <Audio.h> | ||||
| #include <Wire.h> | #include <Wire.h> | ||||
| &sine7, | &sine7, | ||||
| }; | }; | ||||
| // allocate a wave type to each channel. | |||||
| // The types used and their order is purely arbitrary. | |||||
| short wave_type[8] = { | |||||
| TONE_TYPE_SINE, | |||||
| TONE_TYPE_SQUARE, | |||||
| TONE_TYPE_SAWTOOTH, | |||||
| TONE_TYPE_TRIANGLE, | |||||
| TONE_TYPE_SINE, | |||||
| TONE_TYPE_SQUARE, | |||||
| TONE_TYPE_SAWTOOTH, | |||||
| TONE_TYPE_TRIANGLE, | |||||
| }; | |||||
| // Two mixers are needed to handle the 8 channels of music | |||||
| AudioMixer4 mixer1; | AudioMixer4 mixer1; | ||||
| AudioMixer4 mixer2; | AudioMixer4 mixer2; | ||||
| AudioOutputI2S audioOut; | AudioOutputI2S audioOut; | ||||
| // Mix the first four channels into mixer1 | |||||
| AudioConnection c0(sine0, 0, mixer1, 0); | AudioConnection c0(sine0, 0, mixer1, 0); | ||||
| AudioConnection c1(sine1, 0, mixer1, 1); | AudioConnection c1(sine1, 0, mixer1, 1); | ||||
| AudioConnection c2(sine2, 0, mixer1, 2); | AudioConnection c2(sine2, 0, mixer1, 2); | ||||
| AudioConnection c3(sine3, 0, mixer1, 3); | AudioConnection c3(sine3, 0, mixer1, 3); | ||||
| // and the last 4 channels into mixer2 | |||||
| AudioConnection c4(sine4, 0, mixer2, 0); | AudioConnection c4(sine4, 0, mixer2, 0); | ||||
| AudioConnection c5(sine5, 0, mixer2, 1); | AudioConnection c5(sine5, 0, mixer2, 1); | ||||
| AudioConnection c6(sine6, 0, mixer2, 2); | AudioConnection c6(sine6, 0, mixer2, 2); | ||||
| AudioConnection c7(sine7, 0, mixer2, 3); | AudioConnection c7(sine7, 0, mixer2, 3); | ||||
| // Output mixre1 to the left channel and mixer2 to the right | |||||
| AudioConnection c11(mixer1, 0, audioOut, 0); | AudioConnection c11(mixer1, 0, audioOut, 0); | ||||
| AudioConnection c12(mixer2, 0, audioOut, 1); | AudioConnection c12(mixer2, 0, audioOut, 1); | ||||
| //AudioControl_WM8731 codec; | //AudioControl_WM8731 codec; | ||||
| AudioControlSGTL5000 codec; | AudioControlSGTL5000 codec; | ||||
| // Initial value of the volume control | |||||
| int volume = 50; | int volume = 50; | ||||
| // allocate a wave type to each channel. | |||||
| // The types used and their order is purely arbitrary. | |||||
| short wave_type[8] = { | |||||
| TONE_TYPE_SINE, | |||||
| TONE_TYPE_SQUARE, | |||||
| TONE_TYPE_SAWTOOTH, | |||||
| TONE_TYPE_TRIANGLE, | |||||
| TONE_TYPE_SINE, | |||||
| TONE_TYPE_SQUARE, | |||||
| TONE_TYPE_SAWTOOTH, | |||||
| TONE_TYPE_TRIANGLE, | |||||
| }; | |||||
| void setup() | void setup() | ||||
| { | { | ||||
| Serial.begin(115200); | Serial.begin(115200); | ||||
| while (!Serial) ; | while (!Serial) ; | ||||
| delay(3000); | |||||
| delay(2000); | |||||
| // http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html | |||||
| Serial.print("Begin "); | |||||
| Serial.println(__FILE__); | |||||
| // Proc = 12 (13), Mem = 2 (8) | |||||
| // Audio connections require memory to work. | // Audio connections require memory to work. | ||||
| // The memory usage code indicates that 8 is the maximum | // The memory usage code indicates that 8 is the maximum | ||||
| // so give it 10 just to be sure. | // so give it 10 just to be sure. | ||||
| // Comment this if you don't it | // Comment this if you don't it | ||||
| codec.unmuteLineout(); | codec.unmuteLineout(); | ||||
| // Set the ramp time for each wave object | // Set the ramp time for each wave object | ||||
| for(int i = 0; i < 8;i++) { | for(int i = 0; i < 8;i++) { | ||||
| waves[i]->set_ramp_length(88); | waves[i]->set_ramp_length(88); | ||||
| } | } | ||||
| Serial.println("Begin PlayMidiTones"); | |||||
| Serial.println("setup done"); | Serial.println("setup done"); | ||||
| // Initialize processor and memory measurements | // Initialize processor and memory measurements | ||||
| unsigned char c,opcode,chan; | unsigned char c,opcode,chan; | ||||
| unsigned long d_time; | unsigned long d_time; | ||||
| // Change this to if(1) for measurement output | |||||
| if(0) { | |||||
| // Change this to if(1) for measurement output every 5 seconds | |||||
| if(1) { | |||||
| /* | /* | ||||
| For PlaySynthMusic this produces: | For PlaySynthMusic this produces: | ||||
| Proc = 20 (21), Mem = 2 (8) | Proc = 20 (21), Mem = 2 (8) | ||||
| codec.volume((float)n / 10.23); | codec.volume((float)n / 10.23); | ||||
| } | } | ||||
| // read the next note from the table | |||||
| c = *sp++; | c = *sp++; | ||||
| opcode = c & 0xf0; | opcode = c & 0xf0; | ||||
| // was 0x0f but I'm only handling 8 channels | // was 0x0f but I'm only handling 8 channels | ||||
| return; | return; | ||||
| } | } | ||||
| // Play the note on 'chan' | |||||
| // Play the note on 'chan' - divide the frequency by two because the | |||||
| // table of frequencies has been doubled. | |||||
| if(opcode == CMD_PLAYNOTE) { | if(opcode == CMD_PLAYNOTE) { | ||||
| waves[chan]->begin(AMPLITUDE,tune_frequencies2_PGM[*sp++], | waves[chan]->begin(AMPLITUDE,tune_frequencies2_PGM[*sp++], | ||||
| wave_type[chan]); | wave_type[chan]); |