Hi,
I’ve been lucky enough to get my code working as well as it does already, but a minor detail is proving to be difficult to debug. I have a program that filters audio until a change in the UI is detected (I have a face tracker that makes the command for the filter to change based on my location on the screen). It then crossfades from filter to another using the .state variable. The pop happens after I update the filter with the state change, so I suspect this is why it happens. But I have no idea what to do as the solution.
Here are the relevant pieces of code. Let me know if you need to see something else, too.
void MainComponent::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
transport.prepareToPlay(samplesPerBlockExpected, sampleRate);
lastSampleRate = sampleRate;CF_FLAG = false; dsp::ProcessSpec spec; spec.sampleRate = sampleRate; spec.maximumBlockSize = samplesPerBlockExpected; spec.numChannels = otherDeviceManager.getCurrentAudioDevice()->getActiveOutputChannels().countNumberOfSetBits(); currentFilterState = 1; lastFilterState = 1; crossfadeLength = 2; smoothedGain.reset(sampleRate, crossfadeLength); smoothedGain.setTargetValue(1); CFBuffer.setSize(otherDeviceManager.getCurrentAudioDevice()->getActiveOutputChannels().countNumberOfSetBits(), samplesPerBlockExpected); filter1.reset(); filterCF1.reset(); updateFilter(1); filter1.prepare(spec); filterCF1.prepare(spec);
}
void MainComponent::updateFilter(int state_filter)
{
if (state_filter == 1)
{
*filter1.state = *coeffs1;
*filterCF1.state = *coeffs2;
}
else
{
*filter1.state = *coeffs2;
*filterCF1.state = *coeffs1;
}
}
void MainComponent::getNextAudioBlock (const juce::AudioSourceChannelInfo& bufferToFill)
{
// Check if UI wants filter to change
if (currentFilterState != lastFilterState && CF_FLAG == false)
{
CF_FLAG = true; // Crossfade
}bufferToFill.clearActiveBufferRegion(); CFBuffer.clear(); transport.getNextAudioBlock(bufferToFill); dsp::AudioBlock<float> block(*bufferToFill.buffer, (size_t)bufferToFill.startSample); for (int j = 0; j < 2; j++) { CFBuffer.copyFrom(j, 0, bufferToFill.buffer->getReadPointer(j), bufferToFill.numSamples); } dsp::AudioBlock<float> block_CF(CFBuffer, 0); // Process the outgoing audio with the corresponding filter filter1.process(dsp::ProcessContextReplacing <float>(block)); // Begin crossfading if the flag is on if (CF_FLAG == true) { float sampleCF = 0; filterCF1.process(dsp::ProcessContextReplacing <float>(block_CF)); lastFilterState = currentFilterState; for (int i = 0; i < bufferToFill.numSamples; i++) { const auto gain = smoothedGain.getNextValue(); sampleCF = block.getSample(0, i) * (1.0 - gain) + block_CF.getSample(0, i) * gain; block.setSample(0, i, sampleCF); sampleCF = block.getSample(1, i) * (1.0 - gain) + block_CF.getSample(1, i) * gain; block.setSample(1, i, sampleCF); } // Reset the crossfade if previous crossfading event has ended if (smoothedGain.getCurrentValue() == 1) { smoothedGain.setTargetValue(0); smoothedGain.skip(crossfadeLength * lastSampleRate); CF_FLAG = false; smoothedGain.setTargetValue(1); updateFilter(currentFilterState); // Change filter } }
}
I hope it’s nothing too obvious. I’m still new to JUCE and C++ so I appreciate any help I can get. Thank you!