Plugin immediately crashing FL Studio

Hey! I am very new to developing audio plugins and essentially directly followed a YouTube tutorial to create the plugin. It’s super bare-bones, but the idea is that the plugin takes a sidechain input and uses the buffer as a convolution impulse for the input signal. The tutorial loaded an impulse response from a file, which is obviously different, so I needed to use some different techniques to create the plugin. After building the debug version, trying to open the plugin in the juce plugin host would immediately crash the host, which obviously wasn’t a good sign. Similarly, opening in FL Studio immediately closes the program, without a Not Responding window. Some other posts here said that FL Studio was the only thing causing their issues, so I have sent the plugin to my Ableton friends to see if it does the same for them. I can post whatever code you need here if I can figure out how to work that. Thanks for your help!

My prepareToPlay function:

void MultiplyTestAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // Use this method as the place to do any pre-playback
    // initialisation that you need..

    spec.maximumBlockSize = samplesPerBlock;
    spec.sampleRate = sampleRate;
    spec.numChannels = getTotalNumOutputChannels();

    convolver.reset();
    convolver.prepare(spec);
}

my processBlock function:

void MultiplyTestAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::AudioBuffer inputBuffer = getBusBuffer(buffer, true, 0);
    juce::AudioBuffer sidechainBuffer= getBusBuffer(buffer, true, 1);

    juce::dsp::AudioBlock<float> inputBlock{ inputBuffer };

    convolver.loadImpulseResponse(&sidechainBuffer, getSampleRate(), juce::dsp::Convolution::Stereo::yes, juce::dsp::Convolution::Trim::yes, 0);
    convolver.process(juce::dsp::ProcessContextReplacing<float>(inputBlock));
    convolver.reset();
}

I deleted some stuff that was commented out and things that VS was telling me were useless. If there’s any other code you need me to share let me know.

    convolver.loadImpulseResponse(&sidechainBuffer, getSampleRate(), juce::dsp::Convolution::Stereo::yes, juce::dsp::Convolution::Trim::yes, 0);

This line isn’t doing what you think. This is calling the overload taking a const void* and a size_t as the first two arguments, which is probably where the crash is coming from.

You almost certainly don’t need to call loadImpulseResponse and reset during each processBlock. It’s more normal to call loadImpulseResponse in AudioProcessor::prepareToPlay, and reset inside AudioProcessor::reset and/or AudioProcessor::releaseResources.

I recommend taking a look at how the Convolution is used in examples/DSP/ConvolutionDemo.h and examples/Plugins/DSPModulePluginDemo.h.

I intentionally load the impulse response within the processBlock function because I want the impulse response to be the current sidechain buffer and change each time a new buffer is loaded. I’ll reorganize the other things but I feel like that line should be in the processBlock function. How could I write that line to make that work how I expect it to? Is it possible?

The Juce convolution class isn’t meant for that kind of dynamic convolution you are attempting, the intended use case for that is that the IR will be the same for a long time.

I was able to make it work by replacing

convolver.loadImpulseResponse(&sidechainBuffer, ... );

with

convolver.loadImpulseResponse(std::move(sidechainBuffer), ... );

Doesn’t sound how I thought it would though :(( but surprisingly low cpu usage for constantly changing the impulse response. I think if I can make a buffer that hold a bigger chunk of the sidechain audio then it might work, but i think I will try and figure that out another day. Thanks for your help!

Alright, I came back to this project and there is a different issue. I know this is likely an inefficient or intensive process but I am just trying to see a proof of concept. I have edited the code to accept an impulse size, which is how many full buffers compose the impulse. As the audio plays, the sidechain buffers are added to the impulse, and once they reach a certain limit, I have set 30, the impulse is then loaded into the convolver and cleared to be refilled with the next incoming sidechain audio. If there is a more efficient way of doing this, let me know, but as i mentioned before this is only a proof of concept so if i am committing any heinous programmer crimes i don’t mean to.

i added code to create the impulse buffer, size, and position trackers:

    juce::AudioBuffer<float> impulse;
    int impulseSize = 30;
    int impulseSamplePos = 0;

I run impulse.setSize(2, impulseSize * samplesPerBlock); in prepareToPlay() to set the size of the impulse, and then temporarily load the impulse into the convolver.

lastly, my processBlock() function looks like this:

    juce::AudioBuffer inputBuffer = getBusBuffer(buffer, true, 0);
    juce::AudioBuffer sidechainBuffer= getBusBuffer(buffer, true, 1);

    juce::dsp::AudioBlock<float> inputBlock {inputBuffer};

    if (impulseSamplePos < impulseSize) {
        for (int channel = 0; channel < impulse.getNumChannels(); channel++) {
            impulse.addFrom(channel, impulseSamplePos * sidechainBuffer.getNumSamples(), sidechainBuffer, channel, 0, sidechainBuffer.getNumSamples());
        }
    }
    else {
        convolver.loadImpulseResponse(std::move(impulse), spec.sampleRate, juce::dsp::Convolution::Stereo::yes, juce::dsp::Convolution::Trim::no, juce::dsp::Convolution::Normalise::no);
        impulse.clear();
    }

    impulseSamplePos = (impulseSamplePos + 1) % impulseSize;

    convolver.process(juce::dsp::ProcessContextReplacing<float>(inputBlock));

After loading the plugin in FL Studio, the plugin does not send any audio through. I originally thought it was because the impulse is cleared after the convolver loads it as its impulse response, but i assumed that the convolver would store the information about its impulse somewhere within. I am confident I am misunderstanding something.