Changing number of voices in a synth


#1

Hello, first time noob (to c++, juce, DSP, etc) question here. I am writing a synthesizer AU plugin, and want to add a control to change the number of voices. I am calling this when I receive the comboBoxChanged: 

// Triggered by UI change
void MyAudioProcessor::initVoices()

{
    synth.clearVoices();
    for (int i = 0; i < numberOfVoices; i++)
        synth.addVoice(new MySynthVoice());
}

This is very naive, and the result is that the synth has the correct number of voices but they do not know what the sample rate is. I've tried calling synth.setCurrentPlaybackSampleRate() after the above loop, and I've tried calling it before calling synth.renderNextBlock() but neither of them hit my breakpoint in MySynthVoice::setCurrentPlaybackSampleRate().

I can get almost the correct behavior by calling getSampleRate() in MySynthVoice::renderNextBlock() but that seems pretty heavyweight for that loop. I say almost correct in that my note tails will get cut off until I have played and held a note for every voice that is currently active. I don't really understand that. 

What would be the proper way to do this?


#2

You should override SynthesiserVoice::setCurrentPlaybackSampleRate to be told the rate (and then store it in your voice if you need it), and then make sure that Synthesiser::setCurrentPlaybackSampleRate is called whenever the device changes.


#3

I had tried that, but seemingly unsuccessfully. I tried it again and it works, although it seems to take a few seconds before the voices behave properly. Maybe the reason for that will become apparent when I am more experienced with this. 

 

Thanks!


#4

So for the record, Synthesiser::setCurrentPlaybackSampleRate is a no-op if the sample rate doesn't change:

void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{
    if (sampleRate != newRate)
    {
        const ScopedLock sl (lock);
        allNotesOff (0, false);
        sampleRate = newRate;
        for (int i = voices.size(); --i >= 0;)
            voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate);
    }
}

That's why it wasn't working for me. I made a separate method which just does the following, and it works correctly now:

    for (int i = voices.size(); --i >= 0;)
        voices.getUnchecked (i)->setCurrentPlaybackSampleRate (sampleRate);