Hi, I’m designing a plugin in which I want to add oversampling using the juce::dsp::oversampling class. What I want to do is allow the user to switch between different oversampling factors (x2, x4, x8) and also choose the type of filter (FIR or IIR).
In the constructor I created two objects that perform oversampling with FIR and IIR filters as follows:
//
overSamplingModule(2,1,juce::dsp::Oversampling::FilterType::filterHalfBandFIREquiripple,true),
overSamplingModuleIIR(2,1,juce::dsp::Oversampling::FilterType::filterHalfBandPolyphaseIIR,true),
Additionally, I have a method that changes the oversampling type according to the user’s preference. However, when I call it, I encounter an error when changing the factor or filter, which is as follows:
AudioBlock getSubBlock (size_t newOffset, size_t newLength) const noexcept
{
jassert (newOffset < numSamples);
jassert (newOffset + newLength <= numSamples);
}
A breakpoint instruction (__debugbreak() or similar) was executed in NebulaAudioCompressor.exe.
It seems that the number of samples and the offset are 0, as I see in the code. How can I switch between oversampling blocks depending on the desired filter and factor?
//This is the processblock
if (OStoggle) // OVERSAMPLING ON//////////////////////////////////////////////////////////////////////////////////
{
if (TypeFilter == 1)
{
//Upsampling FIR
overSamplingModule.processSamplesUp(UpSampledblock);
}
else if (TypeFilter == 2)
{
//Upsampling IIR
overSamplingModuleIIR.processSamplesUp(UpSampledblock);
}
for (int sample = 0; sample < UpSampledblock.getNumSamples(); ++sample)
{
Thanks for the post, it helped me implement a lot of what I needed.
However, I’m not entirely clear on how the oversampling class processes an audio block. I need two audio blocks:
juce::dsp::AudioBlock UpSampledblock(buffer); //buffer for Upsampling
juce::dsp::AudioBlock block(buffer); //Original Buffer
if (oversamplingState)
{
UpSampledblock = Oversampling->processSamplesUp(UpSampledblock);
for (int sample = 0; sample < UpSampledblock.getNumSamples(); ++sample)
{
for (int channel = 0; channel < UpSampledblock.getNumChannels(); ++channel)
{
float* channelData = UpSampledblock.getChannelPointer(channel);
}
{
}
Oversampling->processSamplesDown(block);
Is this the correct approach? My understanding is that UpSampledBlock takes the original block and applies the oversampling with the desired oversampling factor, then Block is downsampled back to the plugin’s original sampling rate.
That looks correct. After initialization, each juce::dsp::Oversampling holds an internal buffer which stores the upsampling results. When you do something like UpSampledblock = Oversampling->processSamplesUp(UpSampledblock), you let UpSampledblock refer to that internal oversampled buffer.
If you want to verify whether the over-sampling actually works, you can load your plugin into PluginDoctor (with over-sampling only). You will see a low-pass filter around Nyquist.