PDA

View Full Version : Problem with IPlug bypassing in AU version


AHarker
07-19-2010, 05:22 AM
Hi,

Firstly Iplug seems great and is very straightforward to work with.

I've a plug-in up and running. It all behaves fine when running, but when I bypass the effect in Au Lab, or Sample Manager I don't get passthrough - in AU LAb I get nothing and in Sample Manager I get what sounds like the last output buffer looped...

Is there anything I should be doing here, or is this a bug in IPlug. I don't have an issue in DP 7, but I assume that it is handling the bypass in a different way.

As far as I can see from a glance at IPlugAU.cpp IPlug does nothing if the effect is bypassed. Looking in AUEFfectBase.cpp I see:


if (ShouldBypassEffect())
{
// leave silence bit alone
if(!ProcessesInPlace() )
{
theInput->CopyBufferContentsTo (theOutput->GetBufferList());
}
}

Which suggests that if the effect is bypassed and the inputs and outputs do not alias it is up to the effect to copy its inputs to its outputs.

I can probably recode the IPlugAU file, but if this is the case it'd be better for it to be fixed for everyone...

Thanks

Alex

olilarkin
11-04-2011, 08:04 AM
here is a fix for this... it probably could be more efficient (i.e. if you have a single precision host, then this will be copying the buffers to double precision and back again unnecessarily) but it seems OK for now

add these methods to IPlugBase


void IPlugBase::PassThroughBuffers(double sampleType, int nFrames)
{
IPlugBase::ProcessDoubleReplacing(mInData.Get(), mOutData.Get(), nFrames);
}

void IPlugBase::PassThroughBuffers(float sampleType, int nFrames)
{
IPlugBase::ProcessDoubleReplacing(mInData.Get(), mOutData.Get(), nFrames);
int i, n = NOutChannels();
OutChannel** ppOutChannel = mOutChannels.GetList();
for (i = 0; i < n; ++i, ++ppOutChannel) {
OutChannel* pOutChannel = *ppOutChannel;
if (pOutChannel->mConnected) {
CastCopy(pOutChannel->mFDest, *(pOutChannel->mDest), nFrames);
}
}
}


and in IPlugAU::RenderProc() remove the existing if (_this->mBypassed) code and replace the call to ProcessBuffers() with this...


if (_this->mBypassed)
{
_this->PassThroughBuffers((AudioSampleType) 0, nFrames);
}
else
{
_this->ProcessBuffers((AudioSampleType) 0, nFrames);
}

olilarkin
11-04-2011, 08:10 AM
one thing i'm not sure about is if the copied buffer should be delayed to match the latency of the plugin (when the plugin has latency of course). In RTAS you are meant to do this

Tale
11-12-2011, 06:29 AM
Thanks for this fix. :)

olilarkin
02-03-2012, 03:56 PM
an addition to this fix...

if you have more inputs than outputs (for example, you have a sidechain input), then the existing IPlugBase::ProcessDoubleReplacing method would access invalid memory when the plugin was bypassed. Here is a fix:

// Default passthrough.
void IPlugBase::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
// Mutex is already locked.
int i, nIn = mInChannels.GetSize(), nOut = mOutChannels.GetSize();
int j = 0;
for (i = 0; i < nOut; ++i) {
if (i < nIn) {
memcpy(outputs[i], inputs[i], nFrames * sizeof(double));
j++;
}
}
// zero remaining outs
for (/* same j */; j < nOut; ++j) {
memset(outputs[j], 0, nFrames * sizeof(double));
}
}