Pluginval / Allocations during process

Hello jucey people,
I just ran pluginval against an au plugin and on strictness level 9 I get a bunch of failed tests.

Allocations occurred in audio thread: 2 

Any wild guesses, what I might have done wrong?

Thanks a lot!

I guess, you are allocating in the audio thread? :upside_down_face:

Impossible to know without seeing code.
If you post your processBlock() (that is the only one called on the audio thread), someone might be able to make a more educated guess…

Haha thanks for the clarification Daniel :smiley:

This is the code:

void PluginProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    ignoreUnused (midiMessages);
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();
    const int numSamples = buffer.getNumSamples();

    int delayInSamples = jmin (static_cast<int> (roundf (*parameters.getRawParameterValue (Globals::Parameters::IDs::delaySamples))), 
    static_cast<int> (round (getSampleRate() * 2)));

    delayReadPosition = (int) (delayWritePosition - (round (delayInSamples)) + delayBufferLength) % delayBufferLength;

    int dpr = 0;
    int dpw = 0;

    // In case we have more outputs than inputs, this code clears any output

    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {

        float* channelData = buffer.getWritePointer (channel);
        float* delayData = delayBuffer.getWritePointer (jmin (channel, delayBuffer.getNumChannels() - 1));

        dpr = delayReadPosition;
        dpw = delayWritePosition;
        // ..do something to the data...

        for (int i = 0; i < numSamples; ++i)
        {
            const float in = channelData[i];
            float out = 0.0;

            if (delayInSamples <= 0.02)
                out = in;

            else
                out = delayData[dpr];

            delayData[dpw] = in;

            if (++dpr >= delayBufferLength)
                dpr = 0;

            if (++dpw >= delayBufferLength)
                dpw = 0;

            channelData[i] = out;
        }
    }

    delayReadPosition = dpr;
    delayWritePosition = dpw;

    // In case we have more outputs than inputs, this code clears any output

    for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
       buffer.clear (i, 0, buffer.getNumSamples());
}

Well, I don’t see anything potentially allocating.

Unless you left something out…

The only thing I noticed is, that you have the clear command twice, one is superfluous.
But that is unrelated.

Maybe someone else spots something…

Thanks for taking a look!

Nothing left out there…

Maybe an allocation in the audio thread due to a parameter change…? (Parameter changes can happen in the audio thread.)

Also to expand on this, certain callbacks like AudioProcessorParameter::Listener::parameterValueChanged() will happen in the audio thread

You’ll need to be wary of those kinds of situations, but even using something like AsyncUpdater from the audio thread will require some allocation and cause those warnings

I’ll check that tomorrow…

Interestingly, pluginval only fails when using the AU version of the plugin. VST3 passes all the tests even in level 10

Maybe my ScopedAllocationDetector class might be helpful here? I created it some weeks ago for some academical research purposes and currently the documentations and implementation is only halfway done, but it should allow you to set a breakpoint in the allocation callback and inspect the call stack to spot the source of the allocation.

Will do some cleanup of the code next week!

An additional idea @dave96, wouldn‘t it be a great feature for pluginval to optionally print a call stack in case of allocation on the audio thread?

1 Like

I could add call-stack printing, it’s just when these things happen in the audio thread they tend to happen a lot, at audio rate which will really spam the log.

The general idea is that once you’ve found an issue running the CLI version of pluginval you run it in the debugger so you can set a breakpoint during the allocation (it can also throw if enabled). See the docs here for instructions on that: https://github.com/Tracktion/pluginval/blob/master/docs/Debugging%20a%20failed%20validation.md