Code:
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
AudioPlaySdWav wav0;
AudioPlaySdWav wav1;
AudioPlaySdWav wav2;
AudioPlaySdWav wav3;
AudioPlaySdWav wav4;
AudioPlaySdWav wav5;
AudioPlaySdWav wav6;
AudioPlaySdWav wav7;
AudioPlaySdWav *waves[7] = {
&wav0,
&wav1,
&wav2,
&wav3,
&wav4,
&wav5,
&wav6,
};
// AudioPlayMemory sound0; // vestigial notification tone, perhaps useful
AudioMixer4 mix1; // two 4-channel mixers are needed in
AudioMixer4 mix2; // tandem to combine 7 audio sources
AudioOutputAnalog dac; // play to on-chip DAC
// Create Audio connections between the components
//
AudioConnection c1(wav0, 0, mix1, 0);
AudioConnection c2(wav1, 0, mix1, 1);
AudioConnection c3(wav2, 0, mix1, 2);
AudioConnection c4(wav3, 0, mix1, 3);
AudioConnection c5(mix1, 0, mix2, 0); // output of mix1 into 1st input on mix2
AudioConnection c6(wav4, 0, mix2, 1);
AudioConnection c7(wav5, 0, mix2, 2);
AudioConnection c8(wav6, 0, mix2, 3); // for compiled-in sound, comment out
//AudioConnection c8(sound0, 0, mix2, 3); // and uncomment this line
AudioConnection c9(mix2, 0, dac, 0);
char* notefile[]={"G2.wav", "G#2.wav", "A2.wav","A#2.wav","B2.wav",
"C3.wav","C#3.wav","D3.wav","D#3.wav","E3.wav","F3.wav","F#3.wav","G3.wav", "G#3.wav", "A3.wav","A#3.wav","B3.wav",
"C4.wav","C#4.wav","D4.wav","D#4.wav","E4.wav","F4.wav","F#4.wav","G4.wav", "G#4.wav", "A4.wav","A#4.wav","B4.wav",
"C5.wav","C#5.wav","D5.wav","D#5.wav","E5.wav","F5.wav"};
// Array to hold which note is in which mixer channel
// (needed for voice allocation and note off)
byte notenum [7]={99,99,99,99,99,99,99};
byte i; //index for note on counter (channels)
byte t; //index for note off counter (searches)
float ggain = 0.25; //global gain
void setup() {
AudioMemory(10); // see the MemoryAndCpuUsage example
analogWriteResolution(12);
dac.analogReference(INTERNAL); // internal 1.2V reference by default
// reduce the gain on mixer channels, so more than 1
// sound can play simultaneously without clipping
mix1.gain(0, ggain);
mix1.gain(1, ggain);
mix1.gain(2, ggain);
mix1.gain(3, ggain);
mix2.gain(1, ggain);
mix2.gain(2, ggain);
mix2.gain(3, ggain);
Serial.begin(115200);
usbMIDI.setHandleNoteOff(OnNoteOff);
usbMIDI.setHandleNoteOn(OnNoteOn);
delay(2000); // little wait to get the serial screen up
SPI.setMOSI(7);
SPI.setSCK(14);
if (SD.begin(10)) {
waves[5]->play("E3.wav"); // it lives! Gratuitous beepage
waves[6]->play("C3.wav"); // it lives! Gratuitous beepage
Serial.print("SD is a go.");
}
}
void loop() {
usbMIDI.read(); // Using callbacks; this is all we need for the magic
}
void OnNoteOn(byte channel, byte note, byte velocity) {
if (note<43 && velocity > 0) {
Serial.print(note, DEC);
Serial.print("Below G2"); // sample set has limited range
note = 0; // so we'll play lowest/highest note
} // if it's below/above range
else if (note>77 && velocity > 0) {
Serial.print(note, DEC);
Serial.print("Above F5");
note = 34;
}
else if (velocity > 0) { // checking to make sure it is not a note off
Serial.print("Note=");
Serial.print(note, DEC);
note = note - 43;
}
// Above code adjusts note number
// Below code plays note
waves[i]->play(notefile[note]);
Serial.print(" Channel: ");
Serial.println(i, DEC);
i++;
if (i>6) {
Serial.print(" <channel wrap> ");
i=0;}
}
void OnNoteOff(byte channel, byte note, byte velocity) {
for (t = 0; t < 7; t++) { // search for same note already playing
if (notenum[t] = note) {
waves[t]->stop(); // note found and terminated
notenum[t] = 99;
break;
}
}
}