I am working on a synthesizer plugin which includes an option to oversample, and I’m noticing that white noise generated at the higher sample rate is quieter after its downsampled to the desired output sample rate.
And the higher the oversampling factor, the quieter the white noise after being downsampled. Each increase in the oversampling factor decreases the output volume by about -3dB.
For example at an oversampling factor of 1 (2x oversampling), the resulting white noise peaks at about 5dB. At a factor of 2 (4x oversampling) the noise peaks at about 2dB. At a factor of 3, -1dB. And at a factor of 4, -4dB.
Here’s a reduced example where I upsample an (empty) buffer, fill it with white noise, then downsample it:
#ifndef JucePlugin_PreferredChannelConfigurations
: AudioProcessor (BusesProperties()
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
.withInput ("Input", AudioChannelSet::stereo(), true)
#endif
.withOutput ("Output", AudioChannelSet::stereo(), true)
#endif
)
#endif
{
oversampling.reset(new dsp::Oversampling<float> (2, 1, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, false));
// This would result in noise that's -3dB quieter:
//oversampling.reset(new dsp::Oversampling<float> (2, 2, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, false));
}
void OversamplednoiseAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
oversampling->initProcessing(static_cast<size_t> (samplesPerBlock));
oversampling->reset();
}
void OversamplednoiseAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
int numChannels = buffer.getNumChannels();
int numSamples = buffer.getNumSamples();
// Upsampling
dsp::AudioBlock<float> inputBlock (buffer);
dsp::AudioBlock<float> oversampledBlock = oversampling->processSamplesUp (inputBlock);
// Read/write pointers to oversampled AudioBlock
auto osL = oversampledBlock.getChannelPointer(0);
auto osR = oversampledBlock.getChannelPointer(1);
// Fill oversampled buffer with white noise
for ( size_t i = 0; i < oversampledBlock.getNumSamples(); i++ ) {
osL[i] = ((float)rand()/RAND_MAX) * 2.0f - 1.0f;
osR[i] = osL[i];
}
// Downsampling
oversampling->processSamplesDown (inputBlock);
}
Is this just what happens when you downsample white noise?
What I would like is for the output to be a consistent volume regardless of the oversampling factor.