Avoiding clicks while switching impulse responses

Are you sure it’s not just blockwise changing coloration due to the HRTF switching? Depending on the HRTF set you are using, the crossfade of the convolution engines can completly attenuate specific frequencies when they are out of phase in both HRTFs

I wouldn’t expect that to be the issue. The call to get, which happens on the audio thread, uses a try-lock rather than a lock. If the mutex is already locked, this should return immediately, rather than waiting for the mutex to become available.

Hi Joaquin! Sorry from bringing an old thread to you, but I’m struggling with the same problem (binaural convolution) and I can’t make the final mix without breaking some audio hosts. Could you clarify how you did “outBuffer = inBuffer2;”? Thanks!

Hi @pauloassis ! No problem.

I’ll tell you what I ended up doing. I’m using a juce::dsp::ProcessorChain in which I included as one of the processes, a struct that I defined. That struct is the one that has insider two convolvers and the mixer.

The struct should have the necessary methods so that ProcessorChain can use it as a processor (prepare, reset, getLatency, process).

So in the process function of that struct, that receives a context, I process both contexts with each convolver and then mix them.

Is something like this:

in the .h

struct myConvolverStruct
{
myConvolverStruct();
void prepare (const juce::dsp::ProcessSpec& spec);
void reset();
float getLatency() const;
void process (const juce::dsp::ProcessContextReplacing& context);
private:
juce::dsp::DryWetMixer mixer;
juce::dsp::Convolution convolverA;
juce::dsp::Convolution convolverB;
juce::AudioBuffer AuxBufferA;
juce::AudioBuffer AuxBufferB;
};

in the .cpp

void myConvolverStruct::process (const juce::dsp::ProcessContextReplacing& context)
{
if(! context.isBypassed)
{

    context.getOutputBlock().copyTo(AuxBufferA);
    juce::dsp::AudioBlock<float> inBlockA (AuxBufferA);
    juce::dsp::ProcessContextReplacing<float> contextA (inBlockA);
  
    context.getOutputBlock().copyTo(AuxBufferB);
    juce::dsp::AudioBlock<float> inBlockB (AuxBufferB);
    juce::dsp::ProcessContextReplacing<float> contextB (inBlockB);
    
    convolverA.process(contextA);
    convolverB.process(contextB);

    mixer.pushDrySamples(contextA.getOutputBlock());
    mixer.setWetMixProportion(MixerProportion);
    mixer.mixWetSamples(contextB.getOutputBlock());
                        
    context.getOutputBlock().copyFrom(contextB.getOutputBlock());

}
}

Hope that helps.

Best,

Joaquin.

2 Likes

Hi! This is a GREAT help to me, I’ll try a ProcessorChain, hope it works - my code was already sounding good inside Reaper, but crashing in SoundSource.
Many many thanks!
Best, Paulo