42 #include "AUDispatch.h"
43 #include "AUInputElement.h"
44 #include "AUOutputElement.h"
46 #include "CAAudioChannelLayout.h"
47 #include "CAHostTimeBase.h"
48 #include "CAVectorUnit.h"
49 #include "CAXException.h"
53 #if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64)
55 inline int GETCSR () {
int _result;
asm volatile (
"stmxcsr %0" :
"=m" (*&_result) );
return _result; }
56 inline void SETCSR (
int a) {
int _temp = a;
asm volatile(
"ldmxcsr %0" : :
"m" (*&_temp ) ); }
58 #define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
59 #define RESTORE_DENORMALS SETCSR(_savemxcsr);
61 #define DISABLE_DENORMALS
62 #define RESTORE_DENORMALS
65 static bool sAUBaseCFStringsInitialized =
false;
67 static CFStringRef kUntitledString = NULL;
69 static CFStringRef kVersionString = NULL;
71 static CFStringRef kSubtypeString = NULL;
72 static CFStringRef kManufacturerString = NULL;
73 static CFStringRef kDataString = NULL;
74 static CFStringRef kNameString = NULL;
75 static CFStringRef kRenderQualityString = NULL;
76 static CFStringRef kCPULoadString = NULL;
77 static CFStringRef kElementNameString = NULL;
78 static CFStringRef kPartString = NULL;
80 SInt32 AUBase::sVectorUnitType = kVecUninitialized;
84 AUBase::AUBase( AudioComponentInstance inInstance,
85 UInt32 numInputElements,
86 UInt32 numOutputElements,
87 UInt32 numGroupElements,
88 UInt32 numPartElements) :
89 ComponentBase(inInstance),
90 mElementsCreated(false),
92 mHasBegunInitializing(false),
93 mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements),
95 mInitNumGroupEls(numGroupElements), mInitNumPartEls(numPartElements),
97 mRenderCallbacksTouched(false),
98 mRenderThreadID (NULL),
99 mWantsRenderThreadID (false),
100 mLastRenderedSampleTime(kNoLastRenderedSampleTime),
102 mBuffersAllocated(false),
104 #if !TARGET_OS_IPHONE
107 mDebugDispatcher (NULL)
110 if(!sAUBaseCFStringsInitialized)
112 kUntitledString = CFSTR(
"Untitled");
113 kVersionString = CFSTR(kAUPresetVersionKey);
115 kSubtypeString = CFSTR(kAUPresetSubtypeKey);
116 kManufacturerString = CFSTR(kAUPresetManufacturerKey);
117 kDataString = CFSTR(kAUPresetDataKey);
118 kNameString = CFSTR(kAUPresetNameKey);
119 kRenderQualityString = CFSTR(kAUPresetRenderQualityKey);
120 kCPULoadString = CFSTR(kAUPresetCPULoadKey);
121 kElementNameString = CFSTR(kAUPresetElementNameKey);
122 kPartString = CFSTR(kAUPresetPartKey);
123 sAUBaseCFStringsInitialized =
true;
126 if (sVectorUnitType == kVecUninitialized) {
127 sVectorUnitType = CAVectorUnit::GetVectorUnitType() ;
130 mAudioUnitAPIVersion = 2;
132 SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice);
134 GlobalScope().Initialize(
this, kAudioUnitScope_Global, 1);
136 if (mAudioUnitAPIVersion > 1)
137 mParamList.reserve (24);
139 #if !TARGET_OS_IPHONE
140 memset (&mHostCallbackInfo, 0,
sizeof (mHostCallbackInfo));
144 mCurrentPreset.presetNumber = -1;
145 mCurrentPreset.presetName = kUntitledString;
146 CFRetain (mCurrentPreset.presetName);
153 if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
154 #if !TARGET_OS_IPHONE
155 if (mContextName) CFRelease (mContextName);
157 if (mLogString)
delete [] mLogString;
162 void AUBase::CreateElements()
164 if (!mElementsCreated) {
165 Inputs().Initialize(
this, kAudioUnitScope_Input, mInitNumInputEls);
166 Outputs().Initialize(
this, kAudioUnitScope_Output, mInitNumOutputEls);
167 #if !TARGET_OS_IPHONE
168 Groups().Initialize(
this, kAudioUnitScope_Group, mInitNumGroupEls);
169 Parts().Initialize(
this, kAudioUnitScope_Part, mInitNumPartEls);
171 mElementsCreated =
true;
177 void AUBase::SetMaxFramesPerSlice(UInt32 nFrames)
179 mMaxFramesPerSlice = nFrames;
180 if (mBuffersAllocated)
182 PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0);
187 OSStatus AUBase::CanSetMaxFrames()
const
189 return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr);
194 void AUBase::ReallocateBuffers()
199 int nOutputs = Outputs().GetNumberOfElements();
200 for (i = 0; i < nOutputs; ++i) {
201 AUOutputElement *output = GetOutput(i);
202 output->AllocateBuffer();
204 int nInputs = Inputs().GetNumberOfElements();
205 for (i = 0; i < nInputs; ++i) {
206 AUInputElement *input = GetInput(i);
207 input->AllocateBuffer();
209 mBuffersAllocated =
true;
214 OSStatus AUBase::DoInitialize()
216 OSStatus result = noErr;
219 result = Initialize();
220 if (result == noErr) {
221 mHasBegunInitializing =
true;
237 OSStatus AUBase::Initialize()
244 void AUBase::PreDestructor()
251 void AUBase::DoCleanup()
255 mInitialized =
false;
256 mHasBegunInitializing =
false;
261 void AUBase::Cleanup()
267 OSStatus AUBase::Reset( AudioUnitScope inScope,
268 AudioUnitElement inElement)
270 mLastRenderedSampleTime = kNoLastRenderedSampleTime;
276 OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID,
277 AudioUnitScope inScope,
278 AudioUnitElement inElement,
279 UInt32 & outDataSize,
280 Boolean & outWritable)
282 OSStatus result = noErr;
283 bool validateElement =
true;
286 case kAudioUnitProperty_MakeConnection:
287 ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
288 outDataSize =
sizeof(AudioUnitConnection);
293 case kAudioUnitProperty_SetRenderCallback:
294 ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
295 ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
296 outDataSize =
sizeof(AURenderCallbackStruct);
300 case kAudioUnitProperty_StreamFormat:
301 outDataSize =
sizeof(CAStreamBasicDescription);
302 outWritable = IsStreamFormatWritable(inScope, inElement);
305 case kAudioUnitProperty_SampleRate:
306 outDataSize =
sizeof(Float64);
307 outWritable = IsStreamFormatWritable(inScope, inElement);
310 case kAudioUnitProperty_ClassInfo:
311 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
312 outDataSize =
sizeof(CFPropertyListRef);
316 case kAudioUnitProperty_FactoryPresets:
317 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
318 result = GetPresets(NULL);
320 outDataSize =
sizeof(CFArrayRef);
325 case kAudioUnitProperty_PresentPreset:
326 #if !TARGET_OS_IPHONE
328 case kAudioUnitProperty_CurrentPreset:
331 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
332 outDataSize =
sizeof(AUPreset);
336 case kAudioUnitProperty_ElementName:
337 outDataSize =
sizeof (CFStringRef);
341 case kAudioUnitProperty_ParameterList:
344 result = GetParameterList(inScope, NULL, nparams);
346 outDataSize =
sizeof(AudioUnitParameterID) * nparams;
348 validateElement =
false;
352 case kAudioUnitProperty_ParameterInfo:
353 outDataSize =
sizeof(AudioUnitParameterInfo);
355 validateElement =
false;
358 case kAudioUnitProperty_ElementCount:
359 outDataSize =
sizeof(UInt32);
360 outWritable = BusCountWritable(inScope);
361 validateElement =
false;
364 case kAudioUnitProperty_Latency:
365 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
366 outDataSize =
sizeof(Float64);
370 case kAudioUnitProperty_TailTime:
371 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
372 if (SupportsTail()) {
373 outDataSize =
sizeof(Float64);
376 goto InvalidProperty;
379 case kAudioUnitProperty_MaximumFramesPerSlice:
380 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
381 outDataSize =
sizeof(UInt32);
385 case kAudioUnitProperty_LastRenderError:
386 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
387 outDataSize =
sizeof(OSStatus);
391 case kAudioUnitProperty_SupportedNumChannels:
393 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
394 UInt32 num = SupportedNumChannels (NULL);
396 outDataSize =
sizeof (AUChannelInfo) * num;
399 goto InvalidProperty;
404 case kAudioUnitProperty_SupportedChannelLayoutTags:
406 UInt32 numLayouts = GetChannelLayoutTags(inScope, inElement, NULL);
408 outDataSize = numLayouts *
sizeof(AudioChannelLayoutTag);
411 goto InvalidProperty;
413 validateElement =
false;
417 case kAudioUnitProperty_AudioChannelLayout:
420 outDataSize = GetAudioChannelLayout(inScope, inElement, NULL, outWritable);
424 if (GetChannelLayoutTags(inScope, inElement, NULL) == 0)
425 goto InvalidProperty;
427 result = kAudioUnitErr_InvalidPropertyValue;
429 validateElement =
false;
433 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
434 case kAudioUnitProperty_ShouldAllocateBuffer:
435 ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
437 outDataSize =
sizeof(UInt32);
441 #if !CA_AU_IS_ONLY_PLUGIN
442 case kAudioUnitProperty_FastDispatch:
443 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
444 outDataSize =
sizeof(
void *);
446 validateElement =
false;
450 #if !TARGET_OS_IPHONE
451 case kAudioUnitProperty_ContextName:
452 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
453 outDataSize =
sizeof(CFStringRef);
457 case kAudioUnitProperty_GetUIComponentList:
458 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
459 outDataSize = GetNumCustomUIComponents();
460 if (outDataSize == 0)
461 goto InvalidProperty;
462 outDataSize *=
sizeof (AudioComponentDescription);
467 case kAudioUnitProperty_ParameterValueStrings:
468 result = GetParameterValueStrings(inScope, inElement, NULL);
469 if (result == noErr) {
470 outDataSize =
sizeof(CFArrayRef);
472 validateElement =
false;
476 case kAudioUnitProperty_HostCallbacks:
477 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
478 outDataSize =
sizeof (HostCallbackInfo);
482 case kAudioUnitProperty_IconLocation:
483 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
486 goto InvalidProperty;
487 outDataSize =
sizeof(CFURLRef);
490 case kAudioUnitProperty_ParameterClumpName:
491 outDataSize =
sizeof(AudioUnitParameterNameInfo );
495 #endif // !TARGET_OS_IPHONE
498 outDataSize =
sizeof(Float64);
503 result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
504 validateElement =
false;
508 if (result == noErr && validateElement) {
509 ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
514 return kAudioUnitErr_InvalidProperty;
516 return kAudioUnitErr_InvalidScope;
518 return kAudioUnitErr_InvalidElement;
523 OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID,
524 AudioUnitScope inScope,
525 AudioUnitElement inElement,
531 OSStatus result = noErr;
534 case kAudioUnitProperty_StreamFormat:
535 *(CAStreamBasicDescription *)outData = GetStreamFormat(inScope, inElement);
538 case kAudioUnitProperty_SampleRate:
539 *(Float64 *)outData = GetStreamFormat(inScope, inElement).mSampleRate;
542 case kAudioUnitProperty_ParameterList:
545 result = GetParameterList(inScope, (AudioUnitParameterID *)outData, nparams);
549 case kAudioUnitProperty_ParameterInfo:
550 result = GetParameterInfo(inScope, inElement, *(AudioUnitParameterInfo *)outData);
553 case kAudioUnitProperty_ClassInfo:
555 *(CFPropertyListRef *)outData = NULL;
556 result = SaveState((CFPropertyListRef *)outData);
560 case kAudioUnitProperty_FactoryPresets:
562 *(CFArrayRef *)outData = NULL;
563 result = GetPresets ((CFArrayRef *)outData);
567 case kAudioUnitProperty_PresentPreset:
568 #if !TARGET_OS_IPHONE
570 case kAudioUnitProperty_CurrentPreset:
574 *(AUPreset *)outData = mCurrentPreset;
577 if (inID == kAudioUnitProperty_PresentPreset && mCurrentPreset.presetName)
578 CFRetain (mCurrentPreset.presetName);
584 case kAudioUnitProperty_ElementName:
586 AUElement * element = GetElement(inScope, inElement);
587 if (element->HasName()) {
588 *(CFStringRef *)outData = element->GetName();
589 CFRetain (element->GetName());
592 result = kAudioUnitErr_InvalidPropertyValue;
596 case kAudioUnitProperty_ElementCount:
597 *(UInt32 *)outData = GetScope(inScope).GetNumberOfElements();
600 case kAudioUnitProperty_Latency:
601 *(Float64 *)outData = GetLatency();
604 case kAudioUnitProperty_TailTime:
606 *(Float64 *)outData = GetTailTime();
608 result = kAudioUnitErr_InvalidProperty;
611 case kAudioUnitProperty_MaximumFramesPerSlice:
612 *(UInt32 *)outData = mMaxFramesPerSlice;
615 case kAudioUnitProperty_LastRenderError:
616 *(OSStatus *)outData = mLastRenderError;
617 mLastRenderError = 0;
620 case kAudioUnitProperty_SupportedNumChannels:
622 const AUChannelInfo* infoPtr;
623 UInt32 num = SupportedNumChannels (&infoPtr);
624 memcpy (outData, infoPtr, num *
sizeof (AUChannelInfo));
628 case kAudioUnitProperty_SupportedChannelLayoutTags:
630 AudioChannelLayoutTag* ptr = outData ?
static_cast<AudioChannelLayoutTag*
>(outData) : NULL;
631 UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr);
633 result = kAudioUnitErr_InvalidProperty;
637 case kAudioUnitProperty_AudioChannelLayout:
639 AudioChannelLayout* ptr = outData ?
static_cast<AudioChannelLayout*
>(outData) : NULL;
641 UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable);
643 result = kAudioUnitErr_InvalidProperty;
648 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
649 case kAudioUnitProperty_ShouldAllocateBuffer:
651 AUIOElement * element = GetIOElement(inScope, inElement);
652 *(UInt32*)outData = element->WillAllocateBuffer();
658 #if !CA_AU_IS_ONLY_PLUGIN
659 case kAudioUnitProperty_FastDispatch:
661 case kAudioUnitGetParameterSelect:
662 *(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)AudioUnitBaseGetParameter;
664 case kAudioUnitSetParameterSelect:
665 *(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)AudioUnitBaseSetParameter;
667 case kAudioUnitRenderSelect:
668 if (AudioUnitAPIVersion() > 1)
669 *(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)AudioUnitBaseRender;
670 else result = kAudioUnitErr_InvalidElement;
673 result = GetProperty(inID, inScope, inElement, outData);
679 #if !TARGET_OS_IPHONE
680 case kAudioUnitProperty_ParameterValueStrings:
681 result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData);
684 case kAudioUnitProperty_IconLocation:
686 CFURLRef iconLocation = CopyIconLocation();
688 *(CFURLRef*)outData = iconLocation;
690 result = kAudioUnitErr_InvalidProperty;
694 case kAudioUnitProperty_HostCallbacks:
695 *(HostCallbackInfo *)outData = mHostCallbackInfo;
698 case kAudioUnitProperty_GetUIComponentList:
699 GetUIComponentDescs ((ComponentDescription*)outData);
702 case kAudioUnitProperty_ContextName:
703 *(CFStringRef *)outData = mContextName;
705 CFRetain(mContextName);
709 result = kAudioUnitErr_InvalidPropertyValue;
713 case kAudioUnitProperty_ParameterClumpName:
715 AudioUnitParameterNameInfo * ioClumpInfo = (AudioUnitParameterNameInfo*) outData;
716 if (ioClumpInfo->inID == kAudioUnitClumpID_System)
717 result = kAudioUnitErr_InvalidPropertyValue;
720 result = CopyClumpName(inScope, ioClumpInfo->inID, ioClumpInfo->inDesiredLength, &ioClumpInfo->outName);
724 if (result == kAudioUnitErr_InvalidProperty)
725 result = GetProperty (inID, inScope, inElement, outData);
730 #endif // !TARGET_OS_IPHONE
733 *(Float64*)outData = mLastRenderedSampleTime;
737 result = GetProperty(inID, inScope, inElement, outData);
746 OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID,
747 AudioUnitScope inScope,
748 AudioUnitElement inElement,
752 OSStatus result = noErr;
755 case kAudioUnitProperty_MakeConnection:
756 ca_require(inDataSize >=
sizeof(AudioUnitConnection), InvalidPropertyValue);
758 AudioUnitConnection &connection = *(AudioUnitConnection *)inData;
759 result = SetConnection(connection);
764 case kAudioUnitProperty_SetRenderCallback:
766 ca_require(inDataSize >=
sizeof(AURenderCallbackStruct), InvalidPropertyValue);
767 ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
768 AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData;
769 result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon);
773 case kAudioUnitProperty_ElementCount:
774 ca_require(inDataSize ==
sizeof(UInt32), InvalidPropertyValue);
775 ca_require(BusCountWritable(inScope), NotWritable);
776 result = SetBusCount(inScope, *(UInt32*)inData);
777 if (result == noErr) {
778 PropertyChanged(inID, inScope, inElement);
782 case kAudioUnitProperty_MaximumFramesPerSlice:
783 ca_require(inDataSize ==
sizeof(UInt32), InvalidPropertyValue);
784 result = CanSetMaxFrames();
785 if (result)
return result;
786 SetMaxFramesPerSlice(*(UInt32 *)inData);
789 case kAudioUnitProperty_StreamFormat:
791 if (inDataSize < 36)
goto InvalidPropertyValue;
792 ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
794 CAStreamBasicDescription newDesc;
797 memset (&newDesc, 0,
sizeof(newDesc));
798 memcpy (&newDesc, inData, 36);
800 ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
802 const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
804 if ( !curDesc.IsEqual(newDesc,
false) ) {
805 ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
806 result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
811 case kAudioUnitProperty_SampleRate:
813 ca_require(inDataSize ==
sizeof(Float64), InvalidPropertyValue);
814 ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
816 const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
817 CAStreamBasicDescription newDesc = curDesc;
818 newDesc.mSampleRate = *(Float64 *)inData;
820 ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
822 if ( !curDesc.IsEqual(newDesc,
false) ) {
823 ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
824 result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
829 case kAudioUnitProperty_AudioChannelLayout:
831 const AudioChannelLayout *layout =
static_cast<const AudioChannelLayout *
>(inData);
832 ca_require(inDataSize >= offsetof(AudioChannelLayout, mChannelDescriptions) + layout->mNumberChannelDescriptions *
sizeof(AudioChannelDescription), InvalidPropertyValue);
833 result = SetAudioChannelLayout(inScope, inElement, layout);
835 PropertyChanged(inID, inScope, inElement);
839 case kAudioUnitProperty_ClassInfo:
840 ca_require(inDataSize ==
sizeof(CFPropertyListRef *), InvalidPropertyValue);
841 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
842 result = RestoreState(*(CFPropertyListRef *)inData);
845 case kAudioUnitProperty_PresentPreset:
846 #if !TARGET_OS_IPHONE
848 case kAudioUnitProperty_CurrentPreset:
852 ca_require(inDataSize ==
sizeof(AUPreset), InvalidPropertyValue);
853 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
854 AUPreset & newPreset = *(AUPreset *)inData;
856 if (newPreset.presetNumber >= 0)
858 result = NewFactoryPresetSet(newPreset);
862 PropertyChanged(inID, inScope, inElement);
864 else if (newPreset.presetName)
866 CFRelease (mCurrentPreset.presetName);
867 mCurrentPreset = newPreset;
868 CFRetain (mCurrentPreset.presetName);
869 PropertyChanged(inID, inScope, inElement);
872 result = kAudioUnitErr_InvalidPropertyValue;
876 case kAudioUnitProperty_ElementName:
878 ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
879 ca_require(inDataSize ==
sizeof(CFStringRef), InvalidPropertyValue);
880 AUElement * element = GetScope(inScope).GetElement (inElement);
881 element->SetName (*(CFStringRef *)inData);
882 PropertyChanged(inID, inScope, inElement);
886 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
887 case kAudioUnitProperty_ShouldAllocateBuffer:
889 ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
890 ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
891 ca_require(inDataSize ==
sizeof(UInt32), InvalidPropertyValue);
892 ca_require(!IsInitialized(), Initialized);
894 AUIOElement * element = GetIOElement(inScope, inElement);
895 element->SetWillAllocateBuffer(*(UInt32 *)inData != 0);
900 #if !TARGET_OS_IPHONE
901 case kAudioUnitProperty_SetExternalBuffer:
902 ca_require(inDataSize >=
sizeof(AudioUnitExternalBuffer), InvalidPropertyValue);
903 ca_require(IsInitialized(), Uninitialized);
905 AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData;
906 if (intptr_t(buf.buffer) & 0x0F) result = paramErr;
907 else if (inScope == kAudioUnitScope_Input) {
908 AUInputElement *input = GetInput(inElement);
909 input->UseExternalBuffer(buf);
911 AUOutputElement *output = GetOutput(inElement);
912 output->UseExternalBuffer(buf);
917 case kAudioUnitProperty_ContextName:
919 ca_require(inDataSize ==
sizeof(CFStringRef), InvalidPropertyValue);
920 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
921 CFStringRef inStr = *(CFStringRef *)inData;
922 if (mContextName) CFRelease(mContextName);
923 if (inStr) CFRetain(inStr);
924 mContextName = inStr;
925 PropertyChanged(inID, inScope, inElement);
929 case kAudioUnitProperty_HostCallbacks:
931 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
932 UInt32 availSize = (inDataSize <
sizeof (mHostCallbackInfo) ? inDataSize :
sizeof (mHostCallbackInfo));
933 bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize);
934 memset (&mHostCallbackInfo, 0,
sizeof (mHostCallbackInfo));
935 memcpy (&mHostCallbackInfo, inData, availSize);
937 PropertyChanged(inID, inScope, inElement);
940 #endif // !TARGET_OS_IPHONE
943 result = SetProperty(inID, inScope, inElement, inData, inDataSize);
945 PropertyChanged(inID, inScope, inElement);
951 return kAudioUnitErr_PropertyNotWritable;
953 return kAudioUnitErr_FormatNotSupported;
954 #if !TARGET_OS_IPHONE
956 return kAudioUnitErr_Uninitialized;
958 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
960 return kAudioUnitErr_Initialized;
963 return kAudioUnitErr_InvalidScope;
965 return kAudioUnitErr_InvalidProperty;
966 InvalidPropertyValue:
967 return kAudioUnitErr_InvalidPropertyValue;
969 return kAudioUnitErr_InvalidElement;
974 OSStatus AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID inID,
975 AudioUnitScope inScope,
976 AudioUnitElement inElement)
978 OSStatus result = noErr;
981 case kAudioUnitProperty_AudioChannelLayout:
983 result = RemoveAudioChannelLayout(inScope, inElement);
985 PropertyChanged(inID, inScope, inElement);
989 #if !TARGET_OS_IPHONE
990 case kAudioUnitProperty_ContextName:
991 if (mContextName) CFRelease(mContextName);
996 case kAudioUnitProperty_HostCallbacks:
998 ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
999 bool hasValue =
false;
1000 void* ptr = &mHostCallbackInfo;
1001 for (
unsigned int i = 0; i <
sizeof (HostCallbackInfo); ++i) {
1002 if (static_cast<char*>(ptr)[i]) {
1008 memset (&mHostCallbackInfo, 0,
sizeof (HostCallbackInfo));
1009 PropertyChanged(inID, inScope, inElement);
1013 #endif // !TARGET_OS_IPHONE
1016 result = RemovePropertyValue (inID, inScope, inElement);
1021 #if !TARGET_OS_IPHONE
1023 return kAudioUnitErr_InvalidScope;
1029 OSStatus AUBase::GetPropertyInfo( AudioUnitPropertyID inID,
1030 AudioUnitScope inScope,
1031 AudioUnitElement inElement,
1032 UInt32 & outDataSize,
1033 Boolean & outWritable)
1035 return kAudioUnitErr_InvalidProperty;
1041 OSStatus AUBase::GetProperty( AudioUnitPropertyID inID,
1042 AudioUnitScope inScope,
1043 AudioUnitElement inElement,
1046 return kAudioUnitErr_InvalidProperty;
1052 OSStatus AUBase::SetProperty( AudioUnitPropertyID inID,
1053 AudioUnitScope inScope,
1054 AudioUnitElement inElement,
1055 const void * inData,
1058 return kAudioUnitErr_InvalidProperty;
1063 OSStatus AUBase::RemovePropertyValue ( AudioUnitPropertyID inID,
1064 AudioUnitScope inScope,
1065 AudioUnitElement inElement)
1067 return kAudioUnitErr_InvalidPropertyValue;
1072 OSStatus AUBase::AddPropertyListener( AudioUnitPropertyID inID,
1073 AudioUnitPropertyListenerProc inProc,
1074 void * inProcRefCon)
1076 PropertyListener pl;
1078 pl.propertyID = inID;
1079 pl.listenerProc = inProc;
1080 pl.listenerRefCon = inProcRefCon;
1082 if (mPropertyListeners.empty())
1083 mPropertyListeners.reserve(32);
1084 mPropertyListeners.push_back(pl);
1091 OSStatus AUBase::RemovePropertyListener( AudioUnitPropertyID inID,
1092 AudioUnitPropertyListenerProc inProc,
1093 void * inProcRefCon,
1094 bool refConSpecified)
1097 for (
int i = mPropertyListeners.size(); --i >=0; ) {
1098 PropertyListeners::iterator it = mPropertyListeners.begin() + i;
1099 if ((*it).propertyID == inID && (*it).listenerProc == inProc && (!refConSpecified || (*it).listenerRefCon == inProcRefCon))
1100 mPropertyListeners.erase(it);
1107 void AUBase::PropertyChanged( AudioUnitPropertyID inID,
1108 AudioUnitScope inScope,
1109 AudioUnitElement inElement)
1111 for (PropertyListeners::iterator it = mPropertyListeners.begin(); it != mPropertyListeners.end(); ++it)
1112 if ((*it).propertyID == inID)
1113 ((*it).listenerProc)((*it).listenerRefCon, mComponentInstance, inID, inScope, inElement);
1118 OSStatus AUBase::SetRenderNotification( AURenderCallback inProc,
1124 mRenderCallbacksTouched =
true;
1125 mRenderCallbacks.deferred_add(RenderCallback(inProc, inRefCon));
1132 OSStatus AUBase::RemoveRenderNotification( AURenderCallback inProc,
1135 mRenderCallbacks.deferred_remove(RenderCallback(inProc, inRefCon));
1141 OSStatus AUBase::GetParameter( AudioUnitParameterID inID,
1142 AudioUnitScope inScope,
1143 AudioUnitElement inElement,
1144 AudioUnitParameterValue & outValue)
1146 #if !TARGET_OS_IPHONE
1147 if (inScope == kAudioUnitScope_Group) {
1148 return GetGroupParameter (inID, inElement, outValue);
1152 AUElement *elem = SafeGetElement(inScope, inElement);
1153 outValue = elem->GetParameter(inID);
1160 OSStatus AUBase::SetParameter( AudioUnitParameterID inID,
1161 AudioUnitScope inScope,
1162 AudioUnitElement inElement,
1163 AudioUnitParameterValue inValue,
1164 UInt32 inBufferOffsetInFrames)
1166 #if !TARGET_OS_IPHONE
1167 if (inScope == kAudioUnitScope_Group) {
1168 return SetGroupParameter (inID, inElement, inValue, inBufferOffsetInFrames);
1172 AUElement *elem = SafeGetElement(inScope, inElement);
1173 elem->SetParameter(inID, inValue);
1177 #if !TARGET_OS_IPHONE
1180 OSStatus AUBase::SetGroupParameter( AudioUnitParameterID inID,
1181 AudioUnitElement inElement,
1182 AudioUnitParameterValue inValue,
1183 UInt32 inBufferOffsetInFrames)
1185 return kAudioUnitErr_InvalidScope;
1190 OSStatus AUBase::GetGroupParameter( AudioUnitParameterID inID,
1191 AudioUnitElement inElement,
1192 AudioUnitParameterValue & outValue)
1194 return kAudioUnitErr_InvalidScope;
1200 OSStatus AUBase::ScheduleParameter (
const AudioUnitParameterEvent *inParameterEvent,
1203 for (UInt32 i = 0; i < inNumEvents; ++i)
1205 if (inParameterEvent[i].eventType == kParameterEvent_Immediate)
1207 SetParameter (inParameterEvent[i].parameter,
1208 inParameterEvent[i].scope,
1209 inParameterEvent[i].element,
1210 inParameterEvent[i].eventValues.immediate.value,
1211 inParameterEvent[i].eventValues.immediate.bufferOffset);
1213 mParamList.push_back (inParameterEvent[i]);
1221 static bool SortParameterEventList(
const AudioUnitParameterEvent &ev1,
const AudioUnitParameterEvent &ev2 )
1223 int offset1 = ev1.eventType == kParameterEvent_Immediate ? ev1.eventValues.immediate.bufferOffset : ev1.eventValues.ramp.startBufferOffset;
1224 int offset2 = ev2.eventType == kParameterEvent_Immediate ? ev2.eventValues.immediate.bufferOffset : ev2.eventValues.ramp.startBufferOffset;
1226 if(offset1 < offset2)
return true;
1233 OSStatus AUBase::ProcessForScheduledParams( ParameterEventList &inParamList,
1234 UInt32 inFramesToProcess,
1237 OSStatus result = noErr;
1239 int totalFramesToProcess = inFramesToProcess;
1241 int framesRemaining = totalFramesToProcess;
1243 unsigned int currentStartFrame = 0;
1248 std::sort(inParamList.begin(), inParamList.end(), SortParameterEventList);
1250 ParameterEventList::iterator iter = inParamList.begin();
1253 while(framesRemaining > 0 )
1258 int currentEndFrame = totalFramesToProcess;
1261 iter = inParamList.begin();
1264 while(iter != inParamList.end() )
1266 AudioUnitParameterEvent &
event = *iter;
1268 int offset =
event.eventType == kParameterEvent_Immediate ?
event.eventValues.immediate.bufferOffset :
event.eventValues.ramp.startBufferOffset;
1270 if(offset > (
int)currentStartFrame && offset < currentEndFrame )
1272 currentEndFrame = offset;
1277 if(event.eventType == kParameterEvent_Ramped )
1279 offset =
event.eventValues.ramp.startBufferOffset +
event.eventValues.ramp.durationInFrames;
1281 if(offset > (
int)currentStartFrame && offset < currentEndFrame )
1283 currentEndFrame = offset;
1290 int framesThisTime = currentEndFrame - currentStartFrame;
1295 for(ParameterEventList::iterator iter2 = inParamList.begin(); iter2 != inParamList.end(); iter2++ )
1297 AudioUnitParameterEvent &
event = *iter2;
1299 bool eventFallsInSlice;
1302 if(event.eventType == kParameterEvent_Ramped)
1303 eventFallsInSlice =
event.eventValues.ramp.startBufferOffset < currentEndFrame
1304 &&
event.eventValues.ramp.startBufferOffset +
event.eventValues.ramp.durationInFrames > currentStartFrame;
1308 eventFallsInSlice =
event.eventValues.immediate.bufferOffset <= currentStartFrame;
1310 if(eventFallsInSlice)
1312 AUElement *element = GetElement(event.scope, event.element );
1314 if(element) element->SetScheduledEvent( event.parameter,
1317 currentEndFrame - currentStartFrame );
1325 result = ProcessScheduledSlice( inUserData,
1328 inFramesToProcess );
1330 if(result != noErr)
break;
1332 framesRemaining -= framesThisTime;
1333 currentStartFrame = currentEndFrame;
1341 void AUBase::SetWantsRenderThreadID (
bool inFlag)
1343 if (inFlag == mWantsRenderThreadID)
1346 mWantsRenderThreadID = inFlag;
1347 if (!mWantsRenderThreadID)
1348 mRenderThreadID = NULL;
1356 OSStatus AUBase::DoRender( AudioUnitRenderActionFlags & ioActionFlags,
1357 const AudioTimeStamp & inTimeStamp,
1359 UInt32 inFramesToProcess,
1360 AudioBufferList & ioData)
1363 RenderCallbackList::iterator rcit;
1365 CATRACE(kCATrace_AUBaseRenderStart, (
int)
this, inBusNumber, inFramesToProcess, 0);
1369 ca_require(IsInitialized(), Uninitialized);
1370 ca_require(mAudioUnitAPIVersion >= 2, ParamErr);
1371 ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
1373 AUOutputElement *output = GetOutput(inBusNumber);
1374 if (output->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
1375 DebugMessageN4(
"%s:%d ioData.mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; paramErr",
1376 __FILE__, __LINE__, (
unsigned)ioData.mNumberBuffers, (
unsigned)output->GetStreamFormat().NumberChannelStreams());
1380 unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
1381 for (
unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
1382 AudioBuffer &buf = ioData.mBuffers[ibuf];
1383 if (buf.mData != NULL) {
1385 if (buf.mDataByteSize < expectedBufferByteSize) {
1387 DebugMessageN7(
"%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; paramErr",
1388 __FILE__, __LINE__, (
unsigned)inFramesToProcess, (
unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
1396 buf.mDataByteSize = expectedBufferByteSize;
1400 if (WantsRenderThreadID())
1403 mRenderThreadID = pthread_self();
1404 #elif TARGET_OS_WIN32
1405 mRenderThreadID = GetCurrentThreadId();
1409 AudioUnitRenderActionFlags flags;
1410 if (mRenderCallbacksTouched) {
1411 mRenderCallbacks.update();
1412 flags = ioActionFlags | kAudioUnitRenderAction_PreRender;
1413 for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
1414 RenderCallback &rc = *rcit;
1415 CATRACE(kCATrace_AUBaseRenderCallbackStart, (
int)
this, (
int)rc.mRenderNotify, 1, 0);
1416 (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
1418 &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
1419 CATRACE(kCATrace_AUBaseRenderCallbackEnd, (
int)
this, (
int)rc.mRenderNotify, 1, 0);
1423 theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData);
1425 flags = ioActionFlags | kAudioUnitRenderAction_PostRender;
1427 if (SetRenderError (theError)) {
1428 flags |= kAudioUnitRenderAction_PostRenderError;
1431 if (mRenderCallbacksTouched) {
1432 for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
1433 RenderCallback &rc = *rcit;
1434 CATRACE(kCATrace_AUBaseRenderCallbackStart, (
int)
this, (
int)rc.mRenderNotify, 2, 0);
1435 (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
1437 &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
1438 CATRACE(kCATrace_AUBaseRenderCallbackEnd, (
int)
this, (
int)rc.mRenderNotify, 2, 0);
1446 if (!mParamList.empty())
1450 catch (OSStatus err) {
1460 CATRACE(kCATrace_AUBaseRenderEnd, (
int)
this, theError, 0, 0);
1464 Uninitialized: theError = kAudioUnitErr_Uninitialized;
goto errexit;
1465 ParamErr: theError = paramErr;
goto errexit;
1466 TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess;
goto errexit;
1468 DebugMessageN2 (
" from %s, render err: %d", GetLoggingString(), (
int)theError);
1469 SetRenderError(theError);
1475 OSStatus AUBase::SetInputCallback( UInt32 inPropertyID,
1476 AudioUnitElement inElement,
1477 AURenderCallback inProc,
1480 AUInputElement *input = GetInput(inElement);
1482 input->SetInputCallback(inProc, inRefCon);
1483 PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement);
1490 OSStatus AUBase::SetConnection(
const AudioUnitConnection & inConnection)
1494 AUInputElement *input = GetInput(inConnection.destInputNumber);
1496 if (inConnection.sourceAudioUnit) {
1498 CAStreamBasicDescription sourceDesc;
1499 UInt32 size =
sizeof(CAStreamBasicDescription);
1500 ca_require_noerr(err = AudioUnitGetProperty(
1501 inConnection.sourceAudioUnit,
1502 kAudioUnitProperty_StreamFormat,
1503 kAudioUnitScope_Output,
1504 inConnection.sourceOutputNumber,
1507 ca_require_noerr(err = DispatchSetProperty (kAudioUnitProperty_StreamFormat,
1508 kAudioUnitScope_Input, inConnection.destInputNumber,
1509 &sourceDesc,
sizeof(CAStreamBasicDescription)), errexit);
1511 input->SetConnection(inConnection);
1513 PropertyChanged(kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber);
1522 UInt32 AUBase::SupportedNumChannels (
const AUChannelInfo** outInfo)
1529 bool AUBase::ValidFormat( AudioUnitScope inScope,
1530 AudioUnitElement inElement,
1531 const CAStreamBasicDescription & inNewFormat)
1533 return FormatIsCanonical(inNewFormat);
1538 bool AUBase::IsStreamFormatWritable( AudioUnitScope scope,
1539 AudioUnitElement element)
1542 case kAudioUnitScope_Input:
1544 AUInputElement *input = GetInput(element);
1545 if (input->HasConnection())
return false;
1548 case kAudioUnitScope_Output:
1549 return StreamFormatWritable(scope, element);
1552 case kAudioUnitScope_Global:
1553 return StreamFormatWritable(kAudioUnitScope_Output, 0);
1560 const CAStreamBasicDescription &
1561 AUBase::GetStreamFormat( AudioUnitScope inScope,
1562 AudioUnitElement inElement)
1565 AUIOElement *element;
1568 case kAudioUnitScope_Input:
1569 element = Inputs().GetIOElement(inElement);
1571 case kAudioUnitScope_Output:
1572 element = Outputs().GetIOElement(inElement);
1574 case kAudioUnitScope_Global:
1575 element = Outputs().GetIOElement(0);
1578 COMPONENT_THROW(kAudioUnitErr_InvalidScope);
1580 return element->GetStreamFormat();
1583 OSStatus AUBase::SetBusCount( AudioUnitScope inScope,
1586 if (IsInitialized())
1587 return kAudioUnitErr_Initialized;
1589 GetScope(inScope).SetNumberOfElements(inCount);
1595 OSStatus AUBase::ChangeStreamFormat( AudioUnitScope inScope,
1596 AudioUnitElement inElement,
1597 const CAStreamBasicDescription & inPrevFormat,
1598 const CAStreamBasicDescription & inNewFormat)
1601 AUIOElement *element;
1604 case kAudioUnitScope_Input:
1605 element = Inputs().GetIOElement(inElement);
1607 case kAudioUnitScope_Output:
1608 element = Outputs().GetIOElement(inElement);
1610 case kAudioUnitScope_Global:
1611 element = Outputs().GetIOElement(0);
1614 COMPONENT_THROW(kAudioUnitErr_InvalidScope);
1616 element->SetStreamFormat(inNewFormat);
1617 PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement);
1621 UInt32 AUBase::GetChannelLayoutTags( AudioUnitScope inScope,
1622 AudioUnitElement inElement,
1623 AudioChannelLayoutTag * outLayoutTags)
1625 return GetIOElement(inScope, inElement)->GetChannelLayoutTags(outLayoutTags);
1628 UInt32 AUBase::GetAudioChannelLayout( AudioUnitScope scope,
1629 AudioUnitElement element,
1630 AudioChannelLayout * outLayoutPtr,
1631 Boolean & outWritable)
1633 AUIOElement * el = GetIOElement(scope, element);
1634 return el->GetAudioChannelLayout(outLayoutPtr, outWritable);
1637 OSStatus AUBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
1638 AudioUnitElement inElement)
1640 OSStatus result = noErr;
1641 AUIOElement * el = GetIOElement(inScope, inElement);
1643 if (el->GetAudioChannelLayout(NULL, writable)) {
1644 result = el->RemoveAudioChannelLayout();
1649 OSStatus AUBase::SetAudioChannelLayout( AudioUnitScope inScope,
1650 AudioUnitElement inElement,
1651 const AudioChannelLayout * inLayout)
1653 AUIOElement* ioEl = GetIOElement (inScope, inElement);
1656 UInt32 currentChannels = ioEl->GetStreamFormat().NumberChannels();
1657 UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
1658 if (currentChannels != numChannelsInLayout)
1659 return kAudioUnitErr_InvalidPropertyValue;
1661 UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, NULL);
1662 if (numLayouts == 0)
1663 return kAudioUnitErr_InvalidProperty;
1664 AudioChannelLayoutTag *tags = (AudioChannelLayoutTag *)CA_malloc (numLayouts *
sizeof (AudioChannelLayoutTag));
1665 GetChannelLayoutTags (inScope, inElement, tags);
1666 bool foundTag =
false;
1667 for (
unsigned int i = 0; i < numLayouts; ++i) {
1668 if (tags[i] == inLayout->mChannelLayoutTag || tags[i] == kAudioChannelLayoutTag_UseChannelDescriptions) {
1675 if (foundTag ==
false)
1676 return kAudioUnitErr_InvalidPropertyValue;
1678 return ioEl->SetAudioChannelLayout(*inLayout);
1681 static void AddNumToDictionary (CFMutableDictionaryRef dict, CFStringRef key, SInt32 value)
1683 CFNumberRef num = CFNumberCreate (NULL, kCFNumberSInt32Type, &value);
1684 CFDictionarySetValue (dict, key, num);
1688 #define kCurrentSavedStateVersion 0
1690 OSStatus AUBase::SaveState( CFPropertyListRef * outData)
1692 AudioComponentDescription desc = GetComponentDescription();
1694 CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 0,
1695 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1698 SInt32 value = kCurrentSavedStateVersion;
1699 AddNumToDictionary (dict, kVersionString, value);
1702 value = desc.componentType;
1705 value = desc.componentSubType;
1706 AddNumToDictionary (dict, kSubtypeString, value);
1708 value = desc.componentManufacturer;
1709 AddNumToDictionary (dict, kManufacturerString, value);
1712 CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
1713 for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) {
1714 AUScope &scope = GetScope(iscope);
1715 AudioUnitElement nElems = scope.GetNumberOfElements();
1716 for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
1717 AUElement *element = scope.GetElement(ielem);
1718 UInt32 nparams = element->GetNumberOfParameters();
1725 hdr.scope = CFSwapInt32HostToBig(iscope);
1726 hdr.element = CFSwapInt32HostToBig(ielem);
1727 CFDataAppendBytes(data, (UInt8 *)&hdr,
sizeof(hdr));
1729 element->SaveState(data);
1735 CFDictionarySetValue(dict, kDataString, data);
1740 CFDictionarySetValue (dict, kNameString, mCurrentPreset.presetName);
1744 OSStatus result = DispatchGetProperty (kAudioUnitProperty_RenderQuality,
1745 kAudioUnitScope_Global,
1749 if (result == noErr) {
1750 AddNumToDictionary (dict, kRenderQualityString, value);
1753 #if !TARGET_OS_IPHONE
1756 result = DispatchGetProperty (kAudioUnitProperty_CPULoad,
1757 kAudioUnitScope_Global,
1761 if (result == noErr) {
1762 CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad);
1763 CFDictionarySetValue (dict, kCPULoadString, num);
1770 bool foundName =
false;
1771 for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
1772 foundName = GetScope (i).HasElementWithName();
1778 CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0,
1779 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1780 for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
1781 GetScope (i).AddElementNamesToDict (nameDict);
1784 CFDictionarySetValue (dict, kElementNameString, nameDict);
1785 CFRelease (nameDict);
1796 OSStatus AUBase::RestoreState( CFPropertyListRef plist)
1798 if (CFGetTypeID(plist) != CFDictionaryGetTypeID())
return kAudioUnitErr_InvalidPropertyValue;
1800 AudioComponentDescription desc = GetComponentDescription();
1802 CFDictionaryRef dict =
static_cast<CFDictionaryRef
>(plist);
1806 if (CFDictionaryContainsKey (dict, kPartString))
1807 return kAudioUnitErr_InvalidPropertyValue;
1811 CFNumberRef cfnum =
reinterpret_cast<CFNumberRef
>(CFDictionaryGetValue (dict, kVersionString));
1812 if (cfnum == NULL)
return kAudioUnitErr_InvalidPropertyValue;
1814 CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
1815 if (value != kCurrentSavedStateVersion)
return kAudioUnitErr_InvalidPropertyValue;
1821 cfnum =
reinterpret_cast<CFNumberRef
>(CFDictionaryGetValue (dict, kSubtypeString));
1822 if (cfnum == NULL)
return kAudioUnitErr_InvalidPropertyValue;
1823 CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
1824 if (UInt32(value) != desc.componentSubType)
return kAudioUnitErr_InvalidPropertyValue;
1826 cfnum =
reinterpret_cast<CFNumberRef
>(CFDictionaryGetValue (dict, kManufacturerString));
1827 if (cfnum == NULL)
return kAudioUnitErr_InvalidPropertyValue;
1828 CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
1829 if (UInt32(value) != desc.componentManufacturer)
return kAudioUnitErr_InvalidPropertyValue;
1832 CFDataRef data =
reinterpret_cast<CFDataRef
>(CFDictionaryGetValue (dict, kDataString));
1835 const UInt8 *p, *pend;
1837 p = CFDataGetBytePtr(data);
1838 pend = p + CFDataGetLength(data);
1849 hdr.scope = CFSwapInt32BigToHost(*(UInt32 *)p); p +=
sizeof(UInt32);
1850 hdr.element = CFSwapInt32BigToHost(*(UInt32 *)p); p +=
sizeof(UInt32);
1852 AUScope &scope = GetScope(hdr.scope);
1853 AUElement *element = scope.GetElement(hdr.element);
1858 p = element->RestoreState(p);
1864 CFStringRef name =
reinterpret_cast<CFStringRef
>(CFDictionaryGetValue (dict, kNameString));
1865 if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
1868 mCurrentPreset.presetName = name;
1869 mCurrentPreset.presetNumber = -1;
1872 mCurrentPreset.presetName = kUntitledString;
1873 mCurrentPreset.presetNumber = -1;
1876 CFRetain (mCurrentPreset.presetName);
1877 #if !TARGET_OS_IPHONE
1879 PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0);
1882 PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
1885 if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum)))
1887 CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
1888 DispatchSetProperty (kAudioUnitProperty_RenderQuality,
1889 kAudioUnitScope_Global,
1895 #if !TARGET_OS_IPHONE
1897 if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum)))
1900 CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue);
1901 DispatchSetProperty (kAudioUnitProperty_CPULoad,
1902 kAudioUnitScope_Global,
1905 sizeof(floatValue));
1910 CFDictionaryRef nameDict;
1911 if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast<const void**>(&nameDict)))
1914 for (
int i = 0; i < kNumScopes; ++i)
1916 sprintf (
string,
"%d", i);
1917 CFStringRef key = CFStringCreateWithCString (NULL,
string, kCFStringEncodingASCII);
1918 CFDictionaryRef elementDict;
1919 if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast<const void**>(&elementDict)))
1921 bool didAddElements = GetScope (i).RestoreElementNames (elementDict);
1923 PropertyChanged (kAudioUnitProperty_ElementCount, i, 0);
1932 OSStatus AUBase::GetPresets ( CFArrayRef * outData)
const
1934 return kAudioUnitErr_InvalidProperty;
1937 OSStatus AUBase::NewFactoryPresetSet (
const AUPreset & inNewFactoryPreset)
1939 return kAudioUnitErr_InvalidProperty;
1944 bool AUBase::SetAFactoryPresetAsCurrent (
const AUPreset & inPreset)
1946 if (inPreset.presetNumber < 0 || inPreset.presetName == NULL)
return false;
1947 CFRelease (mCurrentPreset.presetName);
1948 mCurrentPreset = inPreset;
1949 CFRetain (mCurrentPreset.presetName);
1953 int AUBase::GetNumCustomUIComponents ()
1958 #if !TARGET_OS_IPHONE
1959 void AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {}
1962 bool AUBase::HasIcon ()
1964 CFURLRef url = CopyIconLocation();
1972 CFURLRef AUBase::CopyIconLocation ()
1979 OSStatus AUBase::GetParameterList( AudioUnitScope inScope,
1980 AudioUnitParameterID * outParameterList,
1981 UInt32 & outNumParameters)
1983 AUScope &scope = GetScope(inScope);
1984 AUElement *elementWithMostParameters = NULL;
1985 UInt32 maxNumParams = 0;
1987 int nElems = scope.GetNumberOfElements();
1988 for (
int ielem = 0; ielem < nElems; ++ielem) {
1989 AUElement *element = scope.GetElement(ielem);
1990 UInt32 nParams = element->GetNumberOfParameters();
1991 if (nParams > maxNumParams) {
1992 maxNumParams = nParams;
1993 elementWithMostParameters = element;
1997 if (outParameterList != NULL && elementWithMostParameters != NULL)
1998 elementWithMostParameters->GetParameterList(outParameterList);
2000 outNumParameters = maxNumParams;
2006 OSStatus AUBase::GetParameterInfo( AudioUnitScope inScope,
2007 AudioUnitParameterID inParameterID,
2008 AudioUnitParameterInfo &outParameterInfo )
2010 return kAudioUnitErr_InvalidParameter;
2015 OSStatus AUBase::GetParameterValueStrings(AudioUnitScope inScope,
2016 AudioUnitParameterID inParameterID,
2017 CFArrayRef * outStrings)
2019 return kAudioUnitErr_InvalidProperty;
2024 OSStatus AUBase::CopyClumpName( AudioUnitScope inScope,
2026 UInt32 inDesiredNameLength,
2027 CFStringRef * outClumpName)
2029 return kAudioUnitErr_InvalidProperty;
2034 void AUBase::SetNumberOfElements( AudioUnitScope inScope,
2037 if (inScope == kAudioUnitScope_Global && numElements != 1)
2038 COMPONENT_THROW(kAudioUnitErr_InvalidScope);
2040 GetScope(inScope).SetNumberOfElements(numElements);
2045 AUElement * AUBase::CreateElement( AudioUnitScope scope,
2046 AudioUnitElement element)
2049 case kAudioUnitScope_Global:
2050 return new AUGlobalElement(
this);
2051 case kAudioUnitScope_Input:
2052 return new AUInputElement(
this);
2053 case kAudioUnitScope_Output:
2054 return new AUOutputElement(
this);
2055 #if !TARGET_OS_IPHONE
2056 case kAudioUnitScope_Group:
2057 return new AUGroupElement(
this);
2058 case kAudioUnitScope_Part:
2059 return new AUPartElement(
this);
2062 COMPONENT_THROW(kAudioUnitErr_InvalidScope);
2069 bool AUBase::FormatIsCanonical(
const CAStreamBasicDescription &f)
2071 return (f.mFormatID == kAudioFormatLinearPCM
2072 && f.mFramesPerPacket == 1
2073 && f.mBytesPerPacket == f.mBytesPerFrame
2076 #
if CA_PREFER_FIXED_POINT
2077 && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) == 0
2078 && (((f.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift) == kAudioUnitSampleFractionBits)
2080 && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0
2082 && ((f.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0) == (mAudioUnitAPIVersion == 1)
2083 #
if TARGET_RT_BIG_ENDIAN
2084 && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) != 0
2086 && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == 0
2088 && f.mBitsPerChannel == 8 *
sizeof(AudioUnitSampleType)
2089 && f.mBytesPerFrame == f.NumberInterleavedChannels() *
sizeof(AudioUnitSampleType)
2095 void AUBase::MakeCanonicalFormat( CAStreamBasicDescription & f,
2098 f.SetAUCanonical(nChannels, mAudioUnitAPIVersion < 2);
2099 f.mSampleRate = 0.0;
2102 const Float64 AUBase::kNoLastRenderedSampleTime = -1.;
2104 #include "AUBaseHelper.h"
2106 char* AUBase::GetLoggingString ()
const
2108 if (mLogString)
return mLogString;
2110 AudioComponentDescription desc = GetComponentDescription();
2112 const_cast<AUBase*
>(
this)->mLogString =
new char[256];
2116 sprintf (const_cast<AUBase*>(
this)->mLogString,
"AU (%p): %s %s %s",
2117 GetComponentInstance(),
2118 CAStringForOSType(desc.componentType, str),
2119 CAStringForOSType(desc.componentSubType, str1),
2120 CAStringForOSType(desc.componentManufacturer, str2));