JUCE 5.4.7: setLatencySamples() crashes Ableton when restoring session

Hey everyone,

I recently updated JUCE from 5.4.3 to 5.4.7 and I’m stuck on a problem with setLatencySamples() crashing Ableton Live 10 on both Mac and Windows.

In my project I’m calling setLatencySamples in the process loop because latency depends on a user parameter that can change runtime. This worked in 5.4.3 and it also works with the new 5.4.7 build when I insert a fresh instance of the plugin. I’m able to change latency repeatedly using the user parameter. However, when trying to restore a saved session Ableton crashes due to setLatencySamples().

I’ve created a clean project and the crash still happens there when using just a simple setLatencySamples(16) call in the process loop. If I add a condition to only call it after ~100 process calls then it doesn’t crash.

void SandboxNewAudioProcessor::process (dsp::ProcessContextReplacing<float> context)
{

    // get audio block
    dsp::AudioBlock<float> blockToProcess;
    blockToProcess = context.getOutputBlock();
    
    // Setting latency immediately crashes Ableton Live
    // setLatencySamples(16);

    // TEST: Setting latency after a while doesn't crash Ableton Live
    count++;
    if (count == 100) {
        setLatencySamples(16);
    }
    
    // per sample processing
    long totalNumSamples = blockToProcess.getNumSamples();
    for (int j = 0; j < totalNumSamples; ++j)
    {
        // get samples
        double inputLeft = blockToProcess.getSample(0,j);
        double inputRight = blockToProcess.getSample(1,j);
        
        // limit
        inputLeft = jlimit<float>(-0.1f, 0.1f, inputLeft);
        inputRight = jlimit<float>(-0.1f, 0.1f, inputRight);
        
        // set samples
        blockToProcess.setSample(0, j, inputLeft);
        blockToProcess.setSample(1, j, inputRight);
    }
}

As a test, if I call setLatencySamples() only in prepareToPlay() then it works, unless I make two repeated calls:

void SandboxNewAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // This will crash Ableton Live
    setLatencySamples(0);
    setLatencySamples(16);
}

I’m suspecting the restore session case might also change the latency more than once as it loads the default state and then the saved state, but as mentioned this is something that seems to have broken since 5.4.3.

Any ideas how to fix or work around it?

As far as I can see, this issue means that plugins built with JUCE 5.4.7 can’t change latency in Ableton Live because it would result in a crash when loading the session. This is a pretty significant problem, so I’m wondering if I’m the only one experiencing it?

Can’t you call it synchronous with the UI change, on the message thread? I’ve had a similar problem with old versions of Cubase -it didn’t crash but made a very long pause when latency was changed on the audio thread. I update derived parameters on the audio thread, but had to resort to an async call for latency changes.

1 Like

Thank you so much for your help!

I’m not sure if this is what you meant exactly, but it seems to work once the setLatencySamples() is moved to parameterChanged(). If I I do this then I do need to have the same logic and setLatencySamples calls in prepareToPlay as well in order for the default state to work properly. But still… no crashes.

However, I wonder if this is intended. The documentation doesn’t mention anything about setLatencySamples being problematic in the audio thread, and the “DSPModulePluginDemo.h” example also has it in the process loop.

Yep, I meant pretty much that. I think this is specific to each DAW -even between versions of Cubase the behavior is different. Cubase 10 reacts the same way to calls from both threads -with a rather short pause. Cubase 5 makes a tiny pause when it’s called from the message thread, but a very long pause when it’s called from the audio thread, and sometimes it freezes. Now if this changed from 5.4.3 to 5.4.7, that’s a bit disconcerting. I don’t have a clue what may have caused it though.