To implement polyphony, it may be a good idea to have a class to define a voice.
class Voice {
public:
float frequency;
float phase;
float deltaAngle;
bool active;
float volume;
};
//-------------
//processor.h
#define MAX_VOICES 16
//MAX_VOICES can be anything but i chose to have 16
public:
int activeVoices = 0;
Voice voices[MAX_VOICES];
And we can modify our noteOn and noteOff to account for these
//processor.cpp
#define float_pi 3.14159
//...
case noteOn: //psuedo code for the note event switch
for (int j = 0; j < MAX_VOICES; j++) { //loop through voices array
if (!voices[j].active) { //if voice.active == false
voices[j].frequency = calcFreq(event.noteOn.pitch);
voices[j].phase = 0.f;
voices[j].deltaAngle = (2.f * float_pi * voices[j].frequency) / data.processContext->sampleRate;
voices[j].active = true;
voices[j].volume = event.noteOn.velocity; //allows for velocity changes, not needed
activeVoices++;
break;//stop loop once a voice is assigned
}
}
break;
case noteOff:
for (int j = 0; j < MAX_VOICES; j++) {
if (voices[j].frequency == calcFreq(event.noteOff.pitch)) { //check if the voice is the correct one
voices[j].active = false;
activeVoices--;
break;
}
}
break;
//...
//processor.cpp
//process function
//...
for (int i = 0; i < data.numSamples; i++) {
for (int j = 0; j < MAX_VOICES; j++) {
if (voices[j].active) {
OutL[i] += OSC(voices[j].phase) * voices[j].volume; //sum all voices to one bus with the oscillator OSC()
voices[j].phase += voices[j].deltaAngle; //update phase
}
OutR[i] = OutL[i]; //stereo implementation
}
return kResultOk
}
//...