#define NO_OF_VOICES 12
long earliestTime = millis(); //For voice allocation - initialise to now
struct VoiceAndNote {
uint32_t note;
long timeOn;
uint32_t voiceOn;//just a boolean 0 off / 1 on
};
struct VoiceAndNote voices[NO_OF_VOICES] = {{ -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}, { -1, 0, 0}};
//This returns the number of the voice you are assigning the note to
// note = -1 means you want to be assigned a voice for note on
// note= 0 - 127 is returning the voice that was previously assigned to that note, for note off
//voices are numbered from 1 not 0
int getVoiceNo(int note) {
uint32_t voiceToReturn = -1; //Initialise
earliestTime = millis(); //Initialise to now
if (note == -1) {
//NoteOn() - Get the oldest free voice (recent voices may be still on release stage)
for (int i = 0; i < NO_OF_VOICES; i++) {
if (voices[i].voiceOn == 0) {
if (voices[i].timeOn < earliestTime) {
earliestTime = voices[i].timeOn;
voiceToReturn = i;
}
}
}
if (voiceToReturn == -1) {
//No free voices, need to steal oldest sounding voice
earliestTime = millis(); //Reinitialise
for (int i = 0; i < NO_OF_VOICES; i++) {
if (voices[i].timeOn < earliestTime) {
earliestTime = voices[i].timeOn;
voiceToReturn = i;
}
}
}
return voiceToReturn + 1;
} else {
//NoteOff() - Get voice number from note
for (int i = 0; i < NO_OF_VOICES; i++) {
if (voices[i].note == note && voices[i].voiceOn == 1) {
return i + 1;
}
}
}
//Shouldn't get here, return voice 1
return 1;
}
//Then set the voices[].note in the code where the voice is sounded:
voices[0].note = note;
voices[0].timeOn = millis();
voices[0].voiceOn= 1;
//And set this for note off
voices[0].voiceOn= 0;