Here's a modification of some code we use internally
- the DSP
decision can be done more optimally based on what
your code ends up
doing...
ComponentResult AUMatrixReverb::Render (
AudioUnitRenderActionFlags
&ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 framesToProcess)
{
AUOutputElement *theOutput = GetOutput(0);
AUInputElement *theInput = GetInput(0);
// get input source audio
AudioUnitRenderActionFlags xflags = 0;
ComponentResult result = PullInput(0, xflags,
inTimeStamp,
framesToProcess);
if (result) return result;
/*
this part uses an internal object to keep a track of
any silent
input, adjust for our
decay/tail time and determine if it will actually
produce data. If it
doesn't then we just return
a silent output buffer.
This is a nice optimisation, but can be bypassed
initially
bool silence = xflags &
kAudioUnitRenderAction_OutputIsSilence;
mSilentTimeout.Process(framesToProcess,
(SInt32)(GetTailTime() *
GetSampleRate() ), silence );
if(silence)
{
ioActionFlags |=
kAudioUnitRenderAction_OutputIsSilence;
// clear out the destination buffer to match
silent bit
return noErr; // silent output so tail should have
died down by
now; no need to process this time
}
else
{
// not silent output this time
ioActionFlags &=
~kAudioUnitRenderAction_OutputIsSilence;
}
*/
int nOutChannels =
theOutput->GetStreamFormat().mChannelsPerFrame;
int nInChannels =
theInput->GetStreamFormat().mChannelsPerFrame;
// call the DSP code - special case stereo->stereo
if (nInChannels == 2 && nOutChannels == 2)
{
mDSP->Process( theInput->GetChannelData(0),
theInput->GetChannelData(1),
theOutput->GetChannelData(0),
theOutput->GetChannelData(1),
framesToProcess );
}
else if (nInChannels != nOutChannels)
{ // if you want to do mono-stereo (or any N-M
channel processing
you need to take care of this
result = unimperr;
}
else
{
// N-N channel processing
for (unsigned int i = 0; i < nInChannels; ++i) {
float* inputChannel =
theInput->GetChannelData(i);
float* outputChannel =
theOutput->GetChannelData(i)
mDSP->Process( inputChannel, outputChannel,
framesToProcess );
}
return result;
}
Bill
On 18/03/2007, at 6:39 PM, paul Fultz wrote:
ok thanks for the information, so if i overide
AUBase
instead all I would need to do is overide Render()
and
Reset(), right? and how would i go about coding
the
Render() so that i can call Process()? i was
working
on some of the code here i dont know if this is
correct, i kind of just compiled it together from
looking at other code:
ComponentResult AUStereoBase::Render(
AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
bool ioSilence = IsInputSilent (ioActionFlags,
inFramesToProcess);
ioActionFlags |=
kAudioUnitRenderAction_OutputIsSilence;
AUInputElement *input = GetInput(0);
AUOutputElement *output = GetOutput(0);
AudioUnitRenderActionFlags xflags = 0;
ComponentResult result = PullInput(0, xflags,
inTimeStamp, inFramesToProcess);
if (result) return result;
Float32 *sourceLeftP = input->GetChannelData(0);
Float32 *sourceRightP = input->GetChannelData(1);
Float32 *destLeftP = output->GetChannelData(0);
Float32 *destRightP = output->GetChannelData(1);
Process(sourceLeftP,
sourceRightP,destLeftP,destRightP,
inNumberFrames,ioSilence);
return noErr;
}
also Process() is a virtual funcion in the class
AUStereroBase, which i will overide in my AU
class.
also how can read number of channels in? i want do
something different if the input is mono, like
call
Process() in this way:
Process(sourceLeftP,
sourceLeftP,destLeftP,destRightP,
inNumberFrames,ioSilence);
thanks,
Paul
--- William Stewart <email@hidden> wrote:
We generally overide AUBase and just implement
the
Render method -
then instead of working around all this stuff,
you
just implement
what you need. I think its clearer and easier
(but
many have ignored
me in the past!)
Bill
On 16/03/2007, at 6:47 AM, Christian Luther
wrote:
Hi Paul!
Unfortunately there is more work to do. You also
have to modify the
function that creates the kernels
(MaintainKernels()) so that you
have your stereo kernel set up correctly (it
usually creates one
kernel per I/O which is not what you want). If
you
want to support
stereo processing only you can just create one
instance of your
Stereokernel. If you want to support both mono
and
stereo
processing you will have to do some more work
there.
Then, you have to modify ProcessBufferLists()
which is the function
that finally calls the Process() functions of
the
kernels.
I can't really remember the details, but just
look
around the
methods I named and try to understand what they