44 #include <TargetConditionals.h>
51 #error Unsupported Operating System
56 #include "ComponentBase.h"
57 #include "AUScopeElement.h"
58 #include "AUInputElement.h"
59 #include "AUOutputElement.h"
62 #include "CAThreadSafeList.h"
63 #include "CAVectorUnit.h"
68 #define CATRACE(code, a, b, c, d)
71 typedef AUElement AUGlobalElement;
73 typedef AUElement AUGroupElement;
74 typedef AUElement AUPartElement;
82 #define kAUDefaultSampleRate 44100.0
84 #define kAUDefaultMaxFramesPerSlice 1156
88 #define kAUDefaultMaxFramesPerSlice 2048
91 class AUDebugDispatcher;
96 class AUBase :
public ComponentBase,
public AUElementCreator {
100 AUBase( AudioComponentInstance inInstance,
101 UInt32 numInputElements,
102 UInt32 numOutputElements,
103 UInt32 numGroupElements = 0,
104 UInt32 numPartElements = 0);
109 virtual void PostConstructor() { CreateElements(); }
112 virtual void PreDestructor();
115 void CreateElements();
125 OSStatus DoInitialize();
130 virtual OSStatus Initialize();
135 bool IsInitialized()
const {
return mInitialized; }
137 bool HasBegunInitializing()
const {
return mHasBegunInitializing; }
144 virtual void Cleanup();
147 virtual OSStatus Reset( AudioUnitScope inScope,
148 AudioUnitElement inElement);
155 OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID,
156 AudioUnitScope inScope,
157 AudioUnitElement inElement,
158 UInt32 & outDataSize,
159 Boolean & outWritable);
162 OSStatus DispatchGetProperty( AudioUnitPropertyID inID,
163 AudioUnitScope inScope,
164 AudioUnitElement inElement,
168 OSStatus DispatchSetProperty( AudioUnitPropertyID inID,
169 AudioUnitScope inScope,
170 AudioUnitElement inElement,
174 OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID,
175 AudioUnitScope inScope,
176 AudioUnitElement inElement);
179 virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
180 AudioUnitScope inScope,
181 AudioUnitElement inElement,
182 UInt32 & outDataSize,
183 Boolean & outWritable);
186 virtual OSStatus GetProperty( AudioUnitPropertyID inID,
187 AudioUnitScope inScope,
188 AudioUnitElement inElement,
192 virtual OSStatus SetProperty( AudioUnitPropertyID inID,
193 AudioUnitScope inScope,
194 AudioUnitElement inElement,
199 virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID,
200 AudioUnitScope inScope,
201 AudioUnitElement inElement);
204 virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID,
205 AudioUnitPropertyListenerProc inProc,
206 void * inProcRefCon);
209 virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID,
210 AudioUnitPropertyListenerProc inProc,
212 bool refConSpecified);
215 virtual OSStatus SetRenderNotification( AURenderCallback inProc,
219 virtual OSStatus RemoveRenderNotification(
220 AURenderCallback inProc,
224 virtual OSStatus GetParameter( AudioUnitParameterID inID,
225 AudioUnitScope inScope,
226 AudioUnitElement inElement,
227 AudioUnitParameterValue & outValue);
230 virtual OSStatus SetParameter( AudioUnitParameterID inID,
231 AudioUnitScope inScope,
232 AudioUnitElement inElement,
233 AudioUnitParameterValue inValue,
234 UInt32 inBufferOffsetInFrames);
236 #if !TARGET_OS_IPHONE
238 virtual OSStatus SetGroupParameter( AudioUnitParameterID inID,
239 AudioUnitElement inElement,
240 AudioUnitParameterValue inValue,
241 UInt32 inBufferOffsetInFrames);
244 virtual OSStatus GetGroupParameter( AudioUnitParameterID inID,
245 AudioUnitElement inElement,
246 AudioUnitParameterValue & outValue);
250 virtual OSStatus ScheduleParameter (
const AudioUnitParameterEvent *inParameterEvent,
255 OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags,
256 const AudioTimeStamp & inTimeStamp,
258 UInt32 inNumberFrames,
259 AudioBufferList & ioData);
271 virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags,
272 const AudioTimeStamp & inTimeStamp,
274 UInt32 inNumberFrames)
276 if (NeedsToRender(inTimeStamp.mSampleTime))
277 return Render(ioActionFlags, inTimeStamp, inNumberFrames);
286 virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
287 const AudioTimeStamp & inTimeStamp,
288 UInt32 inNumberFrames)
294 static const Float64 kNoLastRenderedSampleTime;
300 virtual bool BusCountWritable( AudioUnitScope inScope)
304 virtual OSStatus SetBusCount( AudioUnitScope inScope,
308 virtual OSStatus SetConnection(
const AudioUnitConnection & inConnection);
311 virtual OSStatus SetInputCallback( UInt32 inPropertyID,
312 AudioUnitElement inElement,
313 AURenderCallback inProc,
317 virtual OSStatus GetParameterList( AudioUnitScope inScope,
318 AudioUnitParameterID * outParameterList,
319 UInt32 & outNumParameters);
323 virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
324 AudioUnitParameterID inParameterID,
325 AudioUnitParameterInfo & outParameterInfo);
328 virtual OSStatus SaveState( CFPropertyListRef * outData);
331 virtual OSStatus RestoreState( CFPropertyListRef inData);
334 virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope,
335 AudioUnitParameterID inParameterID,
336 CFArrayRef * outStrings);
339 virtual OSStatus CopyClumpName( AudioUnitScope inScope,
341 UInt32 inDesiredNameLength,
342 CFStringRef * outClumpName);
345 virtual OSStatus GetPresets ( CFArrayRef * outData)
const;
350 bool SetAFactoryPresetAsCurrent (
const AUPreset & inPreset);
357 virtual OSStatus NewFactoryPresetSet (
const AUPreset & inNewFactoryPreset);
360 virtual int GetNumCustomUIComponents ();
361 #if !TARGET_OS_IPHONE
363 virtual void GetUIComponentDescs (ComponentDescription* inDescArray);
367 virtual CFURLRef CopyIconLocation ();
371 virtual Float64 GetLatency() {
return 0.0;}
373 virtual Float64 GetTailTime() {
return 0;}
375 virtual bool SupportsTail () {
return false; }
378 bool IsStreamFormatWritable( AudioUnitScope scope,
379 AudioUnitElement element);
382 virtual bool StreamFormatWritable( AudioUnitScope scope,
383 AudioUnitElement element) = 0;
390 virtual UInt32 SupportedNumChannels (
const AUChannelInfo** outInfo);
393 virtual bool ValidFormat( AudioUnitScope inScope,
394 AudioUnitElement inElement,
395 const CAStreamBasicDescription & inNewFormat);
407 bool FormatIsCanonical(
const CAStreamBasicDescription &format);
410 void MakeCanonicalFormat( CAStreamBasicDescription & outDesc,
411 int numChannels = 2);
414 virtual const CAStreamBasicDescription &
415 GetStreamFormat( AudioUnitScope inScope,
416 AudioUnitElement inElement);
419 virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope,
420 AudioUnitElement inElement,
421 const CAStreamBasicDescription & inPrevFormat,
422 const CAStreamBasicDescription & inNewFormat);
428 #if !TARGET_OS_IPHONE
430 static OSStatus ComponentEntryDispatch( ComponentParameters * params,
438 AUScope & GetScope( AudioUnitScope inScope)
440 if (inScope >= kNumScopes) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
441 return mScopes[inScope];
445 AUScope & GlobalScope() {
return mScopes[kAudioUnitScope_Global]; }
447 AUScope & Inputs() {
return mScopes[kAudioUnitScope_Input]; }
449 AUScope & Outputs() {
return mScopes[kAudioUnitScope_Output]; }
451 #if !TARGET_OS_IPHONE
452 AUScope & Groups() {
return mScopes[kAudioUnitScope_Group]; }
454 AUScope & Parts() {
return mScopes[kAudioUnitScope_Part]; }
457 AUElement * Globals() {
return mScopes[kAudioUnitScope_Global].GetElement(0); }
460 void SetNumberOfElements( AudioUnitScope inScope,
464 AUElement * GetElement( AudioUnitScope inScope,
465 AudioUnitElement inElement)
467 return GetScope(inScope).GetElement(inElement);
471 AUIOElement * GetIOElement( AudioUnitScope inScope,
472 AudioUnitElement inElement)
474 return GetScope(inScope).GetIOElement(inElement);
478 AUElement * SafeGetElement( AudioUnitScope inScope,
479 AudioUnitElement inElement)
481 return GetScope(inScope).SafeGetElement(inElement);
485 AUInputElement * GetInput( AudioUnitElement inElement)
487 return static_cast<AUInputElement *
>(Inputs().SafeGetElement(inElement));
491 AUOutputElement * GetOutput( AudioUnitElement inElement)
493 return static_cast<AUOutputElement *
>(Outputs().SafeGetElement(inElement));
496 #if !TARGET_OS_IPHONE
498 AUGroupElement * GetGroup( AudioUnitElement inElement)
500 return static_cast<AUGroupElement *
>(Groups().SafeGetElement(inElement));
505 OSStatus PullInput( UInt32 inBusNumber,
506 AudioUnitRenderActionFlags &ioActionFlags,
507 const AudioTimeStamp & inTimeStamp,
508 UInt32 inNumberFrames)
510 AUInputElement *input = GetInput(inBusNumber);
511 return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
515 UInt32 GetMaxFramesPerSlice()
const {
return mMaxFramesPerSlice; }
518 static SInt32 GetVectorUnitType() {
return sVectorUnitType; }
520 static bool HasVectorUnit() {
return sVectorUnitType > 0; }
522 static bool HasAltivec() {
return sVectorUnitType == kVecAltivec; }
524 static bool HasSSE2() {
return sVectorUnitType >= kVecSSE2; }
526 static bool HasSSE3() {
return sVectorUnitType == kVecSSE3; }
529 UInt8 AudioUnitAPIVersion()
const {
return mAudioUnitAPIVersion; }
532 bool InRenderThread ()
const
535 return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) :
false);
536 #elif TARGET_OS_WIN32
537 return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() :
false);
542 bool HasInput( AudioUnitElement inElement) {
543 AUInputElement *in =
static_cast<AUInputElement *
>(Inputs().GetElement(inElement));
544 return in != NULL && in->IsActive();
549 void PropertyChanged( AudioUnitPropertyID inID,
550 AudioUnitScope inScope,
551 AudioUnitElement inElement);
553 #if !TARGET_OS_IPHONE
561 OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat,
562 Float64 *outCurrentTempo)
564 return (mHostCallbackInfo.beatAndTempoProc
565 ? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
572 OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat,
573 Float32 *outTimeSig_Numerator,
574 UInt32 *outTimeSig_Denominator,
575 Float64 *outCurrentMeasureDownBeat)
577 return (mHostCallbackInfo.musicalTimeLocationProc
578 ? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
579 outDeltaSampleOffsetToNextBeat,
580 outTimeSig_Numerator,
581 outTimeSig_Denominator,
582 outCurrentMeasureDownBeat)
587 OSStatus CallHostTransportState (Boolean *outIsPlaying,
588 Boolean *outTransportStateChanged,
589 Float64 *outCurrentSampleInTimeLine,
590 Boolean *outIsCycling,
591 Float64 *outCycleStartBeat,
592 Float64 *outCycleEndBeat)
594 return (mHostCallbackInfo.transportStateProc
595 ? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
597 outTransportStateChanged,
598 outCurrentSampleInTimeLine,
606 char* GetLoggingString ()
const;
612 virtual AUElement * CreateElement( AudioUnitScope scope,
613 AudioUnitElement element);
616 virtual void ReallocateBuffers();
620 static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName,
bool inShouldRelease)
622 ioInfo.cfNameString = inName;
623 ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
625 ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
626 CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
629 static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
631 ioInfo.clumpID = inClumpID;
632 ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
636 virtual void SetMaxFramesPerSlice(UInt32 nFrames);
639 virtual OSStatus CanSetMaxFrames()
const;
642 bool WantsRenderThreadID ()
const {
return mWantsRenderThreadID; }
645 void SetWantsRenderThreadID (
bool inFlag);
648 OSStatus SetRenderError (OSStatus inErr)
650 if (inErr && mLastRenderError == 0) {
651 mLastRenderError = inErr;
652 PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
660 OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
661 const AudioTimeStamp & inTimeStamp,
663 AUOutputElement * theOutput,
664 UInt32 inNumberFrames,
665 AudioBufferList & ioData)
667 if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
669 theOutput->PrepareBuffer(inNumberFrames);
672 theOutput->SetBufferList(ioData);
673 OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
674 if (result == noErr) {
675 if (ioData.mBuffers[0].mData == NULL) {
676 theOutput->CopyBufferListTo(ioData);
677 CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (
int)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
679 theOutput->CopyBufferContentsTo(ioData);
680 CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (
int)theOutput->GetBufferList().mBuffers[0].mData, (int)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
681 theOutput->InvalidateBufferList();
692 virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope,
693 AudioUnitElement element,
694 AudioChannelLayoutTag * outLayoutTags);
697 virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope,
698 AudioUnitElement element,
699 AudioChannelLayout * outLayoutPtr,
700 Boolean & outWritable);
703 virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope,
704 AudioUnitElement element,
705 const AudioChannelLayout * inLayout);
708 virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
711 bool NeedsToRender( Float64 inSampleTime)
713 bool needsToRender = fnotequal(inSampleTime, mLastRenderedSampleTime);
714 mLastRenderedSampleTime = inSampleTime;
715 return needsToRender;
720 typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
732 virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
733 UInt32 inFramesToProcess,
744 virtual OSStatus ProcessScheduledSlice(
void *inUserData,
745 UInt32 inStartFrameInBuffer,
746 UInt32 inSliceFramesToProcess,
747 UInt32 inTotalBufferFrames ) {
return noErr;};
752 struct RenderCallback {
753 RenderCallback(AURenderCallback proc,
void *ref) :
755 mRenderNotifyRefCon(ref)
758 AURenderCallback mRenderNotify;
759 void * mRenderNotifyRefCon;
762 return this->mRenderNotify == other.mRenderNotify &&
763 this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
766 typedef TThreadSafeList<RenderCallback> RenderCallbackList;
769 enum { kNumScopes = 3 };
771 enum { kNumScopes = 5 };
775 bool mElementsCreated;
780 bool mHasBegunInitializing;
783 UInt8 mAudioUnitAPIVersion;
786 UInt32 mInitNumInputEls;
788 UInt32 mInitNumOutputEls;
789 #if !TARGET_OS_IPHONE
791 UInt32 mInitNumGroupEls;
793 UInt32 mInitNumPartEls;
796 AUScope mScopes[kNumScopes];
799 RenderCallbackList mRenderCallbacks;
800 bool mRenderCallbacksTouched;
804 pthread_t mRenderThreadID;
805 #elif TARGET_OS_WIN32
806 UInt32 mRenderThreadID;
810 bool mWantsRenderThreadID;
813 Float64 mLastRenderedSampleTime;
816 UInt32 mMaxFramesPerSlice;
819 OSStatus mLastRenderError;
821 AUPreset mCurrentPreset;
824 struct PropertyListener {
825 AudioUnitPropertyID propertyID;
826 AudioUnitPropertyListenerProc listenerProc;
827 void * listenerRefCon;
829 typedef std::vector<PropertyListener> PropertyListeners;
832 ParameterEventList mParamList;
834 PropertyListeners mPropertyListeners;
837 bool mBuffersAllocated;
845 static SInt32 sVectorUnitType;
847 #if !TARGET_OS_IPHONE
850 HostCallbackInfo mHostCallbackInfo;
853 CFStringRef mContextName;
856 AUDebugDispatcher* mDebugDispatcher;
860 inline OSStatus AUInputElement::PullInputWithBufferList(
861 AudioUnitRenderActionFlags & ioActionFlags,
862 const AudioTimeStamp & inTimeStamp,
863 AudioUnitElement inElement,
865 AudioBufferList * inBufferList)
869 if (HasConnection()) {
871 #if !TARGET_OS_IPHONE
872 if (mConnRenderProc != NULL)
873 theResult =
reinterpret_cast<AudioUnitRenderProc
>(mConnRenderProc)(
874 mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
877 theResult = AudioUnitRender(
878 mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
881 theResult = (mInputProc)(
882 mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
885 if (mInputType == kNoInput)
887 return kAudioUnitErr_NoConnection;
893 #endif // __AUBase_h__
bool TTFOUNDATION_EXPORT operator==(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for equality.