46 #include "AUEffectBase.h"
60 AUEffectBase::AUEffectBase( AudioUnit audioUnit,
61 bool inProcessesInPlace ) :
62 AUBase(audioUnit, 1, 1),
65 mProcessesInPlace(inProcessesInPlace)
71 AUEffectBase::~AUEffectBase()
78 void AUEffectBase::Cleanup()
80 for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
89 ComponentResult AUEffectBase::Initialize()
92 SInt16 auNumInputs = (SInt16) GetInput(0)->GetStreamFormat().mChannelsPerFrame;
93 SInt16 auNumOutputs = (SInt16) GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
96 const AUChannelInfo *auChannelConfigs = NULL;
97 UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);
99 if ((numIOconfigs > 0) && (auChannelConfigs != NULL))
101 bool foundMatch =
false;
102 for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i)
104 SInt16 configNumInputs = auChannelConfigs[i].inChannels;
105 SInt16 configNumOutputs = auChannelConfigs[i].outChannels;
106 if ((configNumInputs < 0) && (configNumOutputs < 0))
109 if (((configNumInputs == -1) && (configNumOutputs == -2))
110 || ((configNumInputs == -2) && (configNumOutputs == -1)))
115 else if (((configNumInputs == -1) && (configNumOutputs == -1)) && (auNumInputs == auNumOutputs))
127 bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
128 bool outputMatch = (auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
129 if (inputMatch && outputMatch)
134 return kAudioUnitErr_FormatNotSupported;
141 if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0))
143 return kAudioUnitErr_FormatNotSupported;
151 ComponentResult AUEffectBase::Reset( AudioUnitScope inScope,
152 AudioUnitElement inElement)
154 for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it) {
155 AUKernelBase *kernel = *it;
163 ComponentResult AUEffectBase::GetPropertyInfo (AudioUnitPropertyID inID,
164 AudioUnitScope inScope,
165 AudioUnitElement inElement,
166 UInt32 & outDataSize,
167 Boolean & outWritable)
169 if (inScope == kAudioUnitScope_Global) {
171 case kAudioUnitProperty_BypassEffect:
173 outDataSize =
sizeof (UInt32);
175 case kAudioUnitProperty_InPlaceProcessing:
177 outDataSize =
sizeof (UInt32);
181 return AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
185 ComponentResult AUEffectBase::GetProperty (AudioUnitPropertyID inID,
186 AudioUnitScope inScope,
187 AudioUnitElement inElement,
190 if (inScope == kAudioUnitScope_Global) {
192 case kAudioUnitProperty_BypassEffect:
193 *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
195 case kAudioUnitProperty_InPlaceProcessing:
196 *((UInt32*)outData) = (mProcessesInPlace ? 1 : 0);
200 return AUBase::GetProperty (inID, inScope, inElement, outData);
204 ComponentResult AUEffectBase::SetProperty( AudioUnitPropertyID inID,
205 AudioUnitScope inScope,
206 AudioUnitElement inElement,
210 if (inScope == kAudioUnitScope_Global) {
212 case kAudioUnitProperty_BypassEffect:
214 if (inDataSize <
sizeof(UInt32))
215 return kAudioUnitErr_InvalidPropertyValue;
217 bool tempNewSetting = *((UInt32*)inData) != 0;
219 if (tempNewSetting != IsBypassEffect())
221 if (!tempNewSetting && IsBypassEffect() && IsInitialized())
223 SetBypassEffect (tempNewSetting);
227 case kAudioUnitProperty_InPlaceProcessing:
228 mProcessesInPlace = (*((UInt32*)inData) != 0);
232 return AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
236 void AUEffectBase::MaintainKernels()
238 UInt32 nChannels = GetNumberOfChannels();
240 if (mKernelList.size() < nChannels) {
241 mKernelList.reserve(nChannels);
242 for (UInt32 i = mKernelList.size(); i < nChannels; ++i)
243 mKernelList.push_back(NewKernel());
245 while (mKernelList.size() > nChannels) {
246 AUKernelBase *kernel = mKernelList.back();
248 mKernelList.pop_back();
251 for(
unsigned int i = 0; i < nChannels; i++ )
254 mKernelList[i]->SetLastKernel(i == nChannels-1 );
255 mKernelList[i]->SetChannelNum (i);
260 bool AUEffectBase::StreamFormatWritable( AudioUnitScope scope,
261 AudioUnitElement element)
263 return IsInitialized() ?
false :
true;
266 ComponentResult AUEffectBase::ChangeStreamFormat( AudioUnitScope inScope,
267 AudioUnitElement inElement,
268 const CAStreamBasicDescription & inPrevFormat,
269 const CAStreamBasicDescription & inNewFormat)
271 ComponentResult result = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
277 if (GetParamHasSampleRateDependency() && fnotequal(inPrevFormat.mSampleRate, inNewFormat.mSampleRate))
278 PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
292 ComponentResult AUEffectBase::ProcessScheduledSlice(
void *inUserData,
293 UInt32 inStartFrameInBuffer,
294 UInt32 inSliceFramesToProcess,
295 UInt32 inTotalBufferFrames )
297 ScheduledProcessParams &sliceParams = *((ScheduledProcessParams*)inUserData);
299 AudioUnitRenderActionFlags &actionFlags = *sliceParams.actionFlags;
300 AudioBufferList &inputBufferList = *sliceParams.inputBufferList;
301 AudioBufferList &outputBufferList = *sliceParams.outputBufferList;
304 for(
unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
305 inputBufferList.mBuffers[i].mDataByteSize =
306 (inputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess *
sizeof(AudioSampleType));
309 for(
unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
310 outputBufferList.mBuffers[i].mDataByteSize =
311 (outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess *
sizeof(AudioSampleType));
314 ComponentResult result = ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess );
317 for(
unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
318 inputBufferList.mBuffers[i].mData =
319 (AudioSampleType *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
322 for(
unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
323 outputBufferList.mBuffers[i].mData =
324 (AudioSampleType *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
333 ComponentResult AUEffectBase::Render( AudioUnitRenderActionFlags &ioActionFlags,
334 const AudioTimeStamp & inTimeStamp,
338 return kAudioUnitErr_NoConnection;
340 ComponentResult result = noErr;
341 AUOutputElement *theOutput = GetOutput(0);
343 AUInputElement *theInput = GetInput(0);
344 result = theInput->PullInput(ioActionFlags, inTimeStamp, 0 , nFrames);
348 if(ProcessesInPlace() )
350 theOutput->SetBufferList(theInput->GetBufferList() );
353 if (ShouldBypassEffect())
357 if(!ProcessesInPlace() )
359 theInput->CopyBufferContentsTo (theOutput->GetBufferList());
364 if(mParamList.size() == 0 )
367 result = ProcessBufferLists(ioActionFlags, theInput->GetBufferList(), theOutput->GetBufferList(), nFrames);
373 AudioBufferList &inputBufferList = theInput->GetBufferList();
374 AudioBufferList &outputBufferList = theOutput->GetBufferList();
376 ScheduledProcessParams processParams;
377 processParams.actionFlags = &ioActionFlags;
378 processParams.inputBufferList = &inputBufferList;
379 processParams.outputBufferList = &outputBufferList;
383 result = ProcessForScheduledParams( mParamList,
389 for(
unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
390 inputBufferList.mBuffers[i].mData =
391 (AudioSampleType *)inputBufferList.mBuffers[i].mData - inputBufferList.mBuffers[i].mNumberChannels * nFrames;
392 inputBufferList.mBuffers[i].mDataByteSize =
393 (inputBufferList.mBuffers[i].mNumberChannels * nFrames *
sizeof(AudioSampleType));
396 for(
unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
397 outputBufferList.mBuffers[i].mData =
398 (AudioSampleType *)outputBufferList.mBuffers[i].mData - outputBufferList.mBuffers[i].mNumberChannels * nFrames;
399 outputBufferList.mBuffers[i].mDataByteSize =
400 (outputBufferList.mBuffers[i].mNumberChannels * nFrames *
sizeof(AudioSampleType));
405 if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
407 AUBufferList::ZeroBuffer(theOutput->GetBufferList() );
414 OSStatus AUEffectBase::ProcessBufferLists(
415 AudioUnitRenderActionFlags & ioActionFlags,
416 const AudioBufferList & inBuffer,
417 AudioBufferList & outBuffer,
418 UInt32 inFramesToProcess )
422 bool silentInput = IsInputSilent (ioActionFlags, inFramesToProcess);
423 ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
427 if (inBuffer.mNumberBuffers == 1) {
431 for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it, ++channel) {
432 AUKernelBase *kernel = *it;
434 if (kernel != NULL) {
435 ioSilence = silentInput;
439 (
const AudioSampleType *)inBuffer.mBuffers[0].mData + channel,
440 (AudioSampleType *)outBuffer.mBuffers[0].mData + channel,
442 inBuffer.mBuffers[0].mNumberChannels,
446 ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
451 const AudioBuffer *srcBuffer = inBuffer.mBuffers;
452 AudioBuffer *destBuffer = outBuffer.mBuffers;
454 for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end();
455 ++it, ++srcBuffer, ++destBuffer) {
456 AUKernelBase *kernel = *it;
458 if (kernel != NULL) {
459 ioSilence = silentInput;
462 (
const AudioSampleType *)srcBuffer->mData,
463 (AudioSampleType *)destBuffer->mData,
469 ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
477 Float64 AUEffectBase::GetSampleRate()
479 return GetOutput(0)->GetStreamFormat().mSampleRate;
482 UInt32 AUEffectBase::GetNumberOfChannels()
484 return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;