Hello Emmanuel. Yes, handing voices to in-coming notes is something that took me a while to implement on TSynth until I just sat down and wrote a series of operations based on what should happen. It isn't the best way perhaps, but it's reliably worked. You need to record when voices are assigned to notes, so that in-coming notes can be assigned to either 'free', no longer active voices or active voices that were assigned at the oldest time. This is from my code:
Code:
#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;
This is partly why synths like the SCI Prophets were expensive, they had a Z80 CPU to control among other things the distribution of voices to notes.