# Advice needed on when and where to dynamically change the oversampling factor, is this code OK..?

**URL:** <https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162>\
**Category:** General JUCE discussion\
**Created:** [October 4, 2023, 3:03pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162 "2023-10-04T15:03:53Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 4, 2023, 3:03pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/1 "2023-10-04T15:03:53Z")

</div>

This is my first time implementing oversampling. I am dynamically changing the oversampling factor at the beginning of the `processBlock()`.  
I’m just looking for confirmation that I am doing things right.

`PluginProcessor.h `

```auto
private:
    std::unique_ptr<juce::dsp::Oversampling<float>> oversamplingmodule;

```

`preparetoplay()`

```auto
    if (oversamplingmodule) {  
        oversamplingmodule->initProcessing(samplesPerBlock); }

```

`processBlock()`

```auto
    juce::dsp::AudioBlock<float> block(buffer);
//if user has changed oversampling factor then
    oversamplingmodule.reset(new juce::dsp::Oversampling<float>(2, newOversamplingFactorValue, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));
    oversamplingmodule->processSamplesUp(block);
//rest of processing
    oversamplingmodule->processSamplesDown(block);

```

---

<div class="post-metadata">

**Author:** ![Fandusss](https://avatars.discourse-cdn.com/v4/letter/f/a4c791/32.png) [@Fandusss](https://forum.juce.com/u/Fandusss)\
**Post date:** [October 4, 2023, 3:29pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/2 "2023-10-04T15:29:42Z")

</div>

That’s an allocation in process block which is a no-no. The way I do it currently is call suspendProcessing(), then create the object, then resume processing. This also gives you an opportunity to set the latency to the new value.

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 4, 2023, 4:58pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/3 "2023-10-04T16:58:50Z")

</div>

@Fandusss So is this something close to what you do in the processBlock?

```auto
    juce::dsp::AudioBlock<float> block(buffer);

    suspendProcessing(true);

    // Re-initialize the oversampling module
    oversamplingmodule.reset(new juce::dsp::Oversampling<float>(2, newOversamplingValue, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));

    // Update latency
    auto newLatency = oversamplingmodule->getLatencyInSamples();
    setLatencySamples(newLatency);

    suspendProcessing(false);

```

---

<div class="post-metadata">

**Author:** ![Mrugalla](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/mrugalla/32/13092_2.png) [@Mrugalla](https://forum.juce.com/u/Mrugalla)\
**Post date:** [October 4, 2023, 5:23pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/4 "2023-10-04T17:23:55Z")

</div>

i personally prefer to let processor inherit from timer and check for oversampling parameter changes in timerCallback. if it changed this method, which is on the message thread, suspends the processing on the audio thread, manually calls prepareToPlay and then resumes processing. in prepareToPlay you simply give the oversampler its intended factor. in processBlock you just use the oversampler. this disrupts the audio stream but it’s safe

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 4, 2023, 8:28pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/5 "2023-10-04T20:28:39Z")

</div>

It is correct (at least to me) if you put this block of code within a listener callback (or something similar) instead of `processBlock()` (of course remove the first line).

---

<div class="post-metadata">

**Author:** ![Fandusss](https://avatars.discourse-cdn.com/v4/letter/f/a4c791/32.png) [@Fandusss](https://forum.juce.com/u/Fandusss)\
**Post date:** [October 5, 2023, 1:56am UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/6 "2023-10-05T01:56:23Z")

</div>

This is what I do too. As you say, you get a potential dropout, but I think it’s acceptable for something like oversampling, which changes infrequently and is not automated.

If you wanted to make it seamless while maintaining correct delay compensation, things get a bit complicated.

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 5, 2023, 5:59pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/7 "2023-10-05T17:59:43Z")

</div>

@Mrugalla I’ve gone for the `timercallback()` approach.  
Here’s my code below. I’ve got a couple of questions:

- Do I need to `suspendProcessing()` in the `timercallback()` or not?
- I have my timer set to 200 milliseconds, I assume this is an OK period of time.
- I’ve not called `preparetoplay()`, because I’ve got a lot of other DSP initialization going on there, but in `preparetoplay()` I’ve called the `initializeOversampling()` method, and in `timercallback()` too. I trust this is fine.

```auto
void myplugin::timerCallback()
{
    if (hasOversamplingChanged() == true)
    {
        suspendProcessing(true); 

        oversamplingmodule.reset(new juce::dsp::Oversampling<float>(2, newOversamplingFactor, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));

        initializeOversampling(getBlockSize());

        //set hasOversamplingChanged flag to false

        suspendProcessing(false); 
    }
}

```

```auto
void myplugin::initializeOversampling(int samplesPerBlock)
{
    if (oversamplingmodule) {  
        oversamplingmodule->initProcessing(samplesPerBlock);
    }
}

```

```auto
void myplugin::prepareToPlay (double sampleRate, int samplesPerBlock)
{

    //other dsp init code

    initializeOversampling(samplesPerBlock);

}

```

---

<div class="post-metadata">

**Author:** ![Mrugalla](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/mrugalla/32/13092_2.png) [@Mrugalla](https://forum.juce.com/u/Mrugalla)\
**Post date:** [October 6, 2023, 12:26pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/8 "2023-10-06T12:26:20Z")

</div>

yeah. seems pretty much the same. just make sure that all dsp objects that are in the oversampled part of processBlock also get prepared for the changed samplerate and blocksize and it should be alright

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 6, 2023, 6:14pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/9 "2023-10-06T18:14:41Z")

</div>

ok, so you suspendProcessing too… . Thanks for the tip about other DSP needing to know about the changes.

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 7, 2023, 6:29pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/10 "2023-10-07T18:29:50Z")

</div>

I’m trying to confirm the range of values that `oversamplingmodule.reset()` takes.

Are they `0=off, 1=2x, 2=4x, 3=8x and 4=16x` for `newOversamplingFactor` ??

`oversamplingmodule.reset(new juce::dsp::Oversampling<float>(2, newOversamplingFactor, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));`

I looked here, but it wasn’t defined as far as I can see:  
[https://docs.juce.com/master/classdsp\_1\_1Oversampling.html](https://docs.juce.com/master/classdsp_1_1Oversampling.html)

**edit** : and I find when I engage oversampling, I find my filters and processing, the audio seems muffled and slightly lower volume even when I comment out the filters. I think I am updating the spec in `preparetoplay()` when oversampling is engaged:

```auto
    juce::dsp::ProcessSpec spec;
    spec.numChannels = getNumOutputChannels();  
    spec.maximumBlockSize = samplesPerBlock * realOversamplingRate; // 1,2,4,8 or 16
    spec.sampleRate = sampleRate * realOversamplingRate; 

// my filter prep here...

```

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 8, 2023, 12:04am UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/11 "2023-10-08T00:04:13Z")

</div>

> I looked here, but it wasn’t defined as far as I can see

IIRC, `reset()` on a `unique_ptr` is similar to re-assign by `make_unique`. Therefore the `factor` is defined in the constructor:

> factor: the processing will perform 2 ^ factor times oversampling

* * *

> the audio seems muffled and slightly lower volume

That sounds like a filter effect. Could you please confirm that you process the oversampled audio block instead of the original block? The code should be something like this:

```c++
auto oversampled_block = overSamplers[idxSampler]->processSamplesUp(context.getInputBlock());
// do something on the oversampled_block
overSamplers[idxSampler]->processSamplesDown(context.getOutputBlock());

```

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 9, 2023, 1:21pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/12 "2023-10-09T13:21:15Z")

</div>

I think my processBlock() logic is OK and I am processing on a sample-by-sample basis the upsampled audio block.

```auto

    juce::dsp::AudioBlock<float> block(buffer); 

        if (//oversampling is on)             
        {
            oversamplingmodule->processSamplesUp(block);     
            numSamplesToProcess = block.getNumSamples();     
        }

        for (int channel = 0; channel < totalNumInputChannels; ++channel)
        {
            auto* channelData = block.getChannelPointer(channel);      

            for (auto sample = 0; sample < numSamplesToProcess; sample++)
            {

                 channelData[sample] = my_highpass_filter.processSample(channel, channelData[sample]);

		//more processing
            }
        }
        if (//oversampling is on) {                               
            oversamplingmodule->processSamplesDown(block);
        }

```

`preparetoplay()`

```auto
    juce::dsp::ProcessSpec spec;
    spec.numChannels = getNumOutputChannels();
    spec.maximumBlockSize = samplesPerBlock * realOversamplingRate; // 1,2,4,8 or 16
    spec.sampleRate = sampleRate * realOversamplingRate;

    my_highpass_filter.prepare(spec);
    my_highpass_filter.reset();  
    my_highpass_filter.setType(juce::dsp::StateVariableTPTFilterType::highpass);
    my_highpass_filter.setResonance(1.0); //default values, changed in processBlock()
    my_highpass_filter.setCutoffFrequency(20.0);

```

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 9, 2023, 1:55pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/13 "2023-10-09T13:55:51Z")

</div>

```c++
oversamplingmodule->processSamplesUp(block);

```

You didn’t store the returned reference to the up-sampled block. You are processing the original block.

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 9, 2023, 4:03pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/14 "2023-10-09T16:03:55Z")

</div>

> [@zsliu98](#):
>
> `oversamplingmodule->processSamplesUp(block);`

I inserted `block = oversamplingmodule->processSamplesUp(block);`  
and it crashed on me. Am I getting the types right, … what am I missing ?

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 11, 2023, 12:17pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/15 "2023-10-11T12:17:25Z")

</div>

I think I’m getting closer to the cause of the crash.  
Its when I come to `downsample` at the end of my `processblock()`. I checked numsamples after I upsampled, and its reporting the correct amount. e.g. 256 samples becomes 512 when I am on 2x etc.

it asserts here: juce\_oversampling.cpp, line 374

```auto
jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));

```

in context

```auto
void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
    {
        jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
        jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));

        // Initialization

```

processblock()

```auto
        if (//oversampling is on) {   
            oversamplingmodule->processSamplesDown(block);
        }

```

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 11, 2023, 9:37pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/16 "2023-10-11T21:37:00Z")

</div>

> [processSamplesDown](https://docs.juce.com/master/classdsp_1_1Oversampling.html#a848d3c7871fee7e0a1d4849b38d7f35d) ([AudioBlock](https://docs.juce.com/master/classdsp_1_1AudioBlock.html)\< SampleType \> &outputBlock) noexcept

Could you please confirm that you pass the **original** block (or the outputblock of the original context) to the function above? It seems that you pass the up-sampled block instead (after inserting the code you provided).

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 11, 2023, 10:01pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/17 "2023-10-11T22:01:28Z")

</div>

This is the block I am passing to downsample. Its pointing to the upsampled buffer, not the original buffer.  
processblock()

```auto
juce::dsp::AudioBlock<float> block(buffer); //block assigned to original non-upsampled buffer at start of processblock()
...
        if (//oversampling is on)   
        {
            block = oversamplingmodule->processSamplesUp(block); //enlarge block of samples to process by the oversampling factor, and assign `block` to point to that upsampled block
        }
        int numSamplesToProcess = block.getNumSamples();
...
        for (int channel = 0; channel < totalNumInputChannels; ++channel)
        {
            auto* channelData = block.getChannelPointer(channel);     

            for (auto sample = 0; sample < numSamplesToProcess; sample++)
            {
... //processing
...
        if (//oversampling is on) { //downsample if we've upsampled
            oversamplingmodule->processSamplesDown(block);
        }
...

```

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 11, 2023, 10:05pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/18 "2023-10-11T22:05:11Z")

</div>

That’s the problem. You should pass the reference to the **original** buffer to `processSamplesDown()`.

---

<div class="post-metadata">

**Author:** ![TrustedSteed](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/trustedsteed/32/13862_2.png) [@TrustedSteed](https://forum.juce.com/u/TrustedSteed)\
**Post date:** [October 11, 2023, 10:40pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/19 "2023-10-11T22:40:44Z")

</div>

So is this now correct logic? (It doesn’t crash now).  
I think I can make it more elegant than this but here’s how I altered it so far.

```auto
    juce::dsp::AudioBlock<float> originalBlock(buffer); //assigned to original non-upsampled buffer
    juce::dsp::AudioBlock<float> block(buffer); //block assigned to original non-upsampled buffer at start of processblock()
...
        if (//oversampling is on)   
        {
            block = oversamplingmodule->processSamplesUp(block); //enlarge block of samples to process by the oversampling factor, and assign `block` to point to that upsampled block
        }
        int numSamplesToProcess = block.getNumSamples();
...
        for (int channel = 0; channel < totalNumInputChannels; ++channel)
        {
            auto* channelData = block.getChannelPointer(channel);     

            for (auto sample = 0; sample < numSamplesToProcess; sample++)
            {
... //processing
...
        if (//oversampling is on) { //downsample if we've upsampled
            oversamplingmodule->processSamplesDown(originalBlock); //block changed to originalblock
        }
...

```

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 11, 2023, 10:52pm UTC](https://forum.juce.com/t/advice-needed-on-when-and-where-to-dynamically-change-the-oversampling-factor-is-this-code-ok/58162/20 "2023-10-11T22:52:41Z")

</div>

It looks correct.
