ProcessContextNonReplacing assertion 5.4.4

Is this one really necessary? I have a couple of processors which can handle both replacing and non replacing context, simply by forwarding the replacing to the non-replacing by creating a context with the same in and out AudioBlock. Did not want to create the same code, as there has to be done an internal copy of the data anyhow.
Or is there a more elegant way to avoid having two methods with the same dsp code inside?

That one was a request from the software team at ROLI who had suffered a bit from ProcessContextNonReplacing not doing what they expected it to, so there’s certainly some merit for having a check in there. That being said, I’m not sure there’s a nice way around your use-case either…

Hi @danielrudrich,
Maybe just try to do it the other way around :slight_smile: Forward non-replacing to replacing one. The disadvantage is that the additional temporary output buffer is needed in this case. Which may not make sense to have it in some processors.

Some time ago I was trying to write ProcessorParallel (like there is a juce::dsp::ProcessorChain). Unfortunately I was disturbed by other tasks and it is not tested well. But I used there this trick with temporary buffer.

Btw. Is ProcessContextNonReplacing used in other scenarios than parallel processing of a signal?

greetings :smiley:

Thanks for your reply!
Yea the additional buffer is indeed a disadvantage, especially if the signal might get buffered in the non-replacing again.

Not really :slight_smile:

@t0m I see the reason for the check, might make things easier in most of the cases. I guess I’ll consider writing inline code of the processing and put it into both methods, replacing and non-replacing.

Rethinking the check, shouldn’t there actually be an assertion that the AudioBlocks don’t overlap to assure that the content is not replaced during that call? I mean, just adding one sample would be a very dirty hack to circumvent the assertion, right? :slight_smile:

1 Like

Better solution for that: as the process (const ProcessContextNonReplacing<float>& context) is not required when inheriting from ProcessorBase, I’ll just write a method like process (const AudioBlock<float>& input, AudioBlock<float>& output) and forward both replacing and non replacing to it, or simply call that one directly to avoid that additional call.

Edit to sum up:
That’s my processor’s methods:

void prepare (const ProcessSpec& specs);
void process (const ProcessContextReplacing<float>& replacingContext);
void process (const ProcessContextNonReplacing<float>& nonReplacingContext);
void process (const AudioBlock<const float>& input, AudioBlock<float>& output);
void reset();

and here’s the implementation for the Context calls:

void MatrixConvolution::process (const ProcessContextReplacing<float>& replacingContext)
{
    process (replacingContext.getInputBlock(), replacingContext.getOutputBlock());
};

void MatrixConvolution::process (const ProcessContextNonReplacing<float>& nonReplacingContext)
{
    process (nonReplacingContext.getInputBlock(), nonReplacingContext.getOutputBlock());
}