Re: Custom AudioUnit PROCESS function
Re: Custom AudioUnit PROCESS function
- Subject: Re: Custom AudioUnit PROCESS function
- From: Chandrasekhar Ramakrishnan <email@hidden>
- Date: Tue, 25 Jan 2005 09:00:16 -0800
Felipe Baytelman schrieb:
> I want to make a really simple AudioUnit that flattens the stereo
> signal in two symmetric mono signals, and control the volume of each
> channel independently (I don't know if I can do that without an AU).
I needed almost exactly this same processing a couple of weeks ago!
Here is the AU I threw together for this purpose (note, however, it is
only intended to be used internally in the app -- if you want to
actually package it as an AU that can be loaded into another host,
you'll need to make some changes). You'll need to add the capability
of controlling the volume of the channels.
/*
* ZKMORFormatUtilitiesCPP.h
* zkmsfutils
*
* Created by Chandrasekhar Ramakrishnan on 05.01.05.
* Copyright 2005 C. Ramakrishnan/ZKM. All rights reserved.
*
* CPP code for the format utilities
*/
#include "AUBase.h"
#include <AudioUnit/AudioUnitProperties.h>
#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"
#endif
/*
* ZKMORStreamSplitterAU
*
* The Audio Unit implementation of the Stream Splitter
*
* This is a very simple AudioUnit -- it has no parameters and no
* additional properties. It just takes input from bus 0 and distributes
* it over N buses (where N == num channels in input bus 0).
*/
#ifdef DEBUG
#define kZKMORFormatUtilitiesVersion 0xFFFFFFFF
#else
#define kZKMORFormatUtilitiesVersion 0x00000001
#endif
#define RES_ID 10000
#define COMP_TYPE kAudioUnitType_FormatConverter
#define COMP_SUBTYPE 'BSpl' // this AU splits an N-channel stream over 1 bus into 1-channel streams over N buses
#define COMP_MANUF 'ZKMk' // we are the ZKM in Karlsruhe
#define VERSION kZKMORFormatUtilitiesVersion
#define NAME "ZKM: Audio Bus Splitter"
#define DESCRIPTION "Splits an N-channel stream over 1 bus into 1-channel streams over N buses"
#define ENTRY_POINT "ZKMORStreamSplitterAUEntry" // don't think this is actually used
class ZKMORStreamSplitterAU : public AUBase
{
public:
ZKMORStreamSplitterAU(AudioUnit component) : AUBase(component, 1, 1) { };
virtual bool SupportsTail () { return true; }
virtual ComponentResult Version() { return kZKMORFormatUtilitiesVersion; }
// can change the stream format only for the input, output stream format is
// governed by the input stream format
virtual bool StreamFormatWritable (AudioUnitScope scope,
AudioUnitElement element)
{
return (kAudioUnitScope_Input == scope) && !IsInitialized();
}
// we process all buses simultaneously, so override this method
virtual ComponentResult Render(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames);
// when the input format changes, set the number of buses and update the output formats
virtual ComponentResult ChangeStreamFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat);
virtual void PostConstructor() { AUBase::PostConstructor(); SynchronizeOutputBusesToInputStreamFormat(); }
#if AU_DEBUG_DISPATCHER
virtual ~ZKMORStreamSplitterAU () { delete mDebugDispatcher; }
#endif
protected:
ComponentResult SynchronizeOutputBusesToInputStreamFormat();
// IVARs
unsigned mOutputBusCount;
};
/*
* ZKMORFormatUtilitiesCPP.mm
* zkmsfutils
*
* Created by Chandrasekhar Ramakrishnan on 05.01.05.
* Copyright 2005 C. Ramakrishnan/ZKM. All rights reserved.
*
*/
#include "ZKMORFormatUtilitiesCPP.h"
// register this component for internal use in this executable
COMPONENT_REGISTER(ZKMORStreamSplitterAU, COMP_TYPE, COMP_SUBTYPE, COMP_MANUF);
ComponentResult ZKMORStreamSplitterAU::Render( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
if (!HasInput(0))
return kAudioUnitErr_NoConnection;
ComponentResult result = noErr;
// suck down the input
AUInputElement *theInput = GetInput(0);
result = theInput->PullInput(ioActionFlags, inTimeStamp, 0, inNumberFrames);
if (result) return result;
AudioBufferList &inputBufferList = theInput->GetBufferList();
bool inputIsSilence = ioActionFlags & kAudioUnitRenderAction_OutputIsSilence;
unsigned numOutputs = mOutputBusCount;
unsigned dataByteSize = inputBufferList.mBuffers[0].mDataByteSize;
// copy the data from channel i of the input buffer into output bus i
for (unsigned i = 0; i < numOutputs; i++)
{
AUOutputElement *theOutput = GetOutput(i); // throws if error
// Apparently, I can't use the next line, I have to use PrepareBuffer instead.
// AudioBufferList &outputBufferList = theOutput->GetBufferList();
AudioBufferList &outputBufferList = theOutput->PrepareBuffer(inNumberFrames);
if (inputIsSilence)
{
AUBufferList::ZeroBuffer(outputBufferList);
} else {
memcpy(outputBufferList.mBuffers[0].mData, inputBufferList.mBuffers[i].mData, dataByteSize);
}
}
return result;
}
ComponentResult ZKMORStreamSplitterAU::ChangeStreamFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat)
{
ComponentResult err = noErr;
err = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
if (err) return err;
// if the input format just changed, we need to go and change the buses
if (kAudioUnitScope_Input == inScope) {
return SynchronizeOutputBusesToInputStreamFormat();
}
return noErr;
}
ComponentResult ZKMORStreamSplitterAU::SynchronizeOutputBusesToInputStreamFormat()
{
ComponentResult err = noErr;
const CAStreamBasicDescription &inNewFormat = GetStreamFormat(kAudioUnitScope_Input, 0);
// set the new bus count
mOutputBusCount = inNewFormat.mChannelsPerFrame;
err = SetBusCount(kAudioUnitScope_Output, mOutputBusCount);
if (err) return err;
// change the formats for the output buses
CAStreamBasicDescription outputFormat = inNewFormat;
outputFormat.ChangeNumberChannels(1, false);
for (unsigned i = 0; i < mOutputBusCount; i++) {
const CAStreamBasicDescription
&oldOutputFormat = GetStreamFormat(kAudioUnitScope_Output, i);
err = AUBase::ChangeStreamFormat(kAudioUnitScope_Output, i, oldOutputFormat, outputFormat);
if (err) return err;
}
return noErr;
}
--
C. Ramakrishnan email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden