Prepping oversampled processors (sample rate? block size?)

I’ve been trying to figure out how the Oversampling class works and have run into a few hiccups, especially regarding what to do with the sample rate and block size of oversampled processors.

The oversampling demos I saw in the JUCE codebase only use the WaveShaper class, which doesn’t seem to care about the sample rate at all (I assume they’re just a static waveshaper/lookup).

In my particular case, I’m trying to use other waveshaping/wavefolding techniques that use the sample rate as a parameter of the algorithm.

The question is, how should I prepare my processor for this kind of use? What should the ProcessSpec look like?

I tried prepping it like this in my plugin’s prepareToPlay:

void PluginProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
{
    lastSampleRate = sampleRate;

    dsp::ProcessSpec spec;
    spec.sampleRate = lastSampleRate;
    spec.maximumBlockSize = (unsigned int) samplesPerBlock;
    spec.numChannels = (unsigned int) getMainBusNumOutputChannels();

    oversampler.reset();
    oversampler.initProcessing (spec.maximumBlockSize);

    // Processors that run before oversampling
    gain.reset();
    gain.prepare(spec);

    // Oversampled processors
    auto oversamplingTimes = static_cast<uint32>(std::pow(2, oversampler.factorOversampling));
    // NOTICE scaled sample rate AND max block size
    saturator.prepare(
        { spec.sampleRate * oversamplingTimes, (uint32) spec.maximumBlockSize * oversamplingTimes, (uint32) spec.numChannels });

    // Processors that run after oversampling
    mixer.reset();
    mixer.prepare(spec);
}

The saturator processor has other things inside it (like a HP filter) and when that process is ran it fails assertions about hitting NaN samples. This leads me to think I’m not setting the block size correctly. Does the block size change when oversampling? I think I saw a larger block size in the debugger so I assumed it was multiplied by the same factor as the sample rate, but now I’m not sure at all.

I’ve also read in some posts that the block size can change block by block if my DAW decides to, which adds extra confusion. Wouldn’t that cause NaN samples passing through my processors also? Do I have to broadcast the block size to my processors on each processBlock call?

1 Like