So I implemented @daniel’s wrapped/templated Engine class suggestion, and it works great! Not only can I now support float & double precision, but another major advantage is that it becomes a breeze to avoid pops & clicks when bypassing/unbypassing.
For example, I added a couple of bool arguments to my Engine class’s internal “process” method:
template<typename SampleType>
void ImogenEngine<SampleType>::process (AudioBuffer<SampleType>& inBus, AudioBuffer<SampleType>& output, MidiBuffer& midiMessages,
const bool applyFadeIn, const bool applyFadeOut)
{
const ScopedLock sl (lock);
// do a bunch of fancy stuff here
if (applyFadeIn)
output.applyGainRamp(0, totalNumSamples, 0.0f, 1.0f);
if (applyFadeOut)
output.applyGainRamp(0, totalNumSamples, 1.0f, 0.0f);
};
and now, in my templated processblock & processBlockBypassed, I can now do this:
template <typename SampleType>
void ImogenAudioProcessor::processBlockWrapped (AudioBuffer<SampleType>& buffer, MidiBuffer& midiMessages, ImogenEngine<SampleType>& engine)
{
AudioBuffer<SampleType> inBus = AudioProcessor::getBusBuffer(buffer, true, (host.isLogic() || host.isGarageBand()));
AudioBuffer<SampleType> outBus = AudioProcessor::getBusBuffer(buffer, false, 0); // out bus must be configured to stereo
engine.process (inBus, outBus, midiMessages, wasBypassedLastCallback, false);
wasBypassedLastCallback = false;
};
template <typename SampleType>
void ImogenAudioProcessor::processBlockBypassedWrapped (AudioBuffer<SampleType>& buffer, MidiBuffer& midiMessages, ImogenEngine<SampleType>& engine)
{
AudioBuffer<SampleType> inBus = AudioProcessor::getBusBuffer(buffer, true, (host.isLogic() || host.isGarageBand()));
AudioBuffer<SampleType> outBus = AudioProcessor::getBusBuffer(buffer, false, 0); // out bus must be configured to stereo
if (! wasBypassedLastCallback)
{
// this is the first callback of processBlockBypassed() after the bypass has been activated.
// Process one more chunk and ramp the sound to 0 instead of killing the sound instantly
engine.process (inBus, outBus, midiMessages, false, true);
wasBypassedLastCallback = true;
return;
}
engine.processBypassed (inBus, outBus, midiMessages);
wasBypassedLastCallback = true;
};
works like a charm 