41 #include "CAAudioUnit.h"
44 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
45 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
46 #include <AudioUnit/MusicDevice.h>
49 #include <Components.h>
50 #include <MusicDevice.h>
54 #include "CAXException.h"
55 #include "CAReferenceCounted.h"
56 #include "AUOutputBL.h"
58 struct StackAUChannelInfo {
59 StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
60 ~StackAUChannelInfo() { free (mChanInfo); }
62 AUChannelInfo* mChanInfo;
67 #ifndef CA_AU_USE_FAST_DISPATCH
68 #define CA_AU_USE_FAST_DISPATCH !TARGET_OS_IPHONE
71 class CAAudioUnit::AUState :
public CAReferenceCounted {
73 AUState (AudioComponent inComp)
76 OSStatus result = ::AudioComponentInstanceNew (inComp, &mUnit);
82 AUState (
const AUNode &inNode,
const AudioUnit& inUnit)
83 : mUnit (inUnit), mNode (inNode)
93 OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
94 Float32 &outValue)
const
96 #if CA_AU_USE_FAST_DISPATCH
97 if (mGetParamProc != NULL) {
98 return (mGetParamProc) (mConnInstanceStorage, inID, scope, element, &outValue);
101 return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue);
104 OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
105 Float32 value, UInt32 bufferOffsetFrames)
107 #if CA_AU_USE_FAST_DISPATCH
108 if (mSetParamProc != NULL) {
109 return (mSetParamProc) (mConnInstanceStorage, inID, scope, element, value, bufferOffsetFrames);
112 return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames);
115 OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags,
116 const AudioTimeStamp * inTimeStamp,
117 UInt32 inOutputBusNumber,
118 UInt32 inNumberFrames,
119 AudioBufferList * ioData)
121 #if CA_AU_USE_FAST_DISPATCH
122 if (mRenderProc != NULL) {
123 return (mRenderProc) (mConnInstanceStorage, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
126 return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
129 #if !TARGET_OS_IPHONE
130 OSStatus MIDIEvent (UInt32 inStatus,
133 UInt32 inOffsetSampleFrame)
136 #if CA_AU_USE_FAST_DISPATCH
137 if (mMIDIEventProc != NULL) {
138 return (mMIDIEventProc) (mConnInstanceStorage, inStatus, inData1, inData2, inOffsetSampleFrame);
141 return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame);
142 #else // ON WINDOWS _ NO MIDI EVENT dispatch
147 OSStatus StartNote (MusicDeviceInstrumentID inInstrument,
148 MusicDeviceGroupID inGroupID,
149 NoteInstanceID * outNoteInstanceID,
150 UInt32 inOffsetSampleFrame,
151 const MusicDeviceNoteParams * inParams)
154 #if CA_AU_USE_FAST_DISPATCH
155 if (mStartNoteProc != NULL) {
156 return (mStartNoteProc) (mConnInstanceStorage, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
159 return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
164 OSStatus StopNote (MusicDeviceGroupID inGroupID,
165 NoteInstanceID inNoteInstanceID,
166 UInt32 inOffsetSampleFrame)
169 #if CA_AU_USE_FAST_DISPATCH
170 if (mStopNoteProc != NULL) {
171 return (mStopNoteProc) (mConnInstanceStorage, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
174 return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
179 #endif// !TARGET_OS_IPHONE
185 #if CA_AU_USE_FAST_DISPATCH
186 UInt32 size =
sizeof(AudioUnitRenderProc);
187 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
188 kAudioUnitScope_Global, kAudioUnitRenderSelect,
189 &mRenderProc, &size) != noErr)
192 size =
sizeof(AudioUnitGetParameterProc);
193 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
194 kAudioUnitScope_Global, kAudioUnitGetParameterSelect,
195 &mGetParamProc, &size) != noErr)
196 mGetParamProc = NULL;
198 size =
sizeof(AudioUnitSetParameterProc);
199 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
200 kAudioUnitScope_Global, kAudioUnitSetParameterSelect,
201 &mSetParamProc, &size) != noErr)
202 mSetParamProc = NULL;
204 size =
sizeof(MusicDeviceMIDIEventProc);
205 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
206 kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect,
207 &mMIDIEventProc, &size) != noErr)
208 mMIDIEventProc = NULL;
210 size =
sizeof(MusicDeviceStartNoteProc);
211 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
212 kAudioUnitScope_Global, kMusicDeviceStartNoteSelect,
213 &mStartNoteProc, &size) != noErr)
214 mStartNoteProc = NULL;
216 size =
sizeof(MusicDeviceStopNoteProc);
217 if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
218 kAudioUnitScope_Global, kMusicDeviceStopNoteSelect,
219 &mStopNoteProc, &size) != noErr)
220 mStopNoteProc = NULL;
222 if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc || mStartNoteProc || mStopNoteProc) {
223 mConnInstanceStorage = GetComponentInstanceStorage ( mUnit );
225 mConnInstanceStorage = NULL;
227 mConnInstanceStorage = NULL;
231 #if CA_AU_USE_FAST_DISPATCH
232 AudioUnitRenderProc mRenderProc;
233 AudioUnitGetParameterProc mGetParamProc;
234 AudioUnitSetParameterProc mSetParamProc;
235 MusicDeviceMIDIEventProc mMIDIEventProc;
236 MusicDeviceStartNoteProc mStartNoteProc;
237 MusicDeviceStopNoteProc mStopNoteProc;
240 void * mConnInstanceStorage;
245 AUState (
const AUState&) {}
246 AUState& operator= (
const AUState&) {
return *
this; }
250 CAAudioUnit::AUState::~AUState ()
252 if (mUnit && (mNode == 0)) {
253 ::AudioComponentInstanceDispose (mUnit);
259 OSStatus CAAudioUnit::Open (
const CAComponent& inComp, CAAudioUnit &outUnit)
264 }
catch (OSStatus res) {
271 CAAudioUnit::CAAudioUnit (
const AudioUnit& inUnit)
272 : mComp (inUnit), mDataPtr (new AUState (kCAAU_DoNotKnowIfAUNode, inUnit))
276 CAAudioUnit::CAAudioUnit (
const CAComponent& inComp)
277 : mComp (inComp), mDataPtr (new AUState (mComp.Comp()))
281 CAAudioUnit::CAAudioUnit (
const AUNode &inNode,
const AudioUnit& inUnit)
282 : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit))
286 CAAudioUnit::~CAAudioUnit ()
291 void CAAudioUnit::Close()
299 CAAudioUnit& CAAudioUnit::operator= (
const CAAudioUnit &a)
301 if (mDataPtr != a.mDataPtr) {
305 if ((mDataPtr = a.mDataPtr) != NULL)
316 if (mDataPtr == y.mDataPtr)
return true;
317 AudioUnit au1 = mDataPtr ? mDataPtr->mUnit : 0;
318 AudioUnit au2 = y.mDataPtr ? y.mDataPtr->mUnit : 0;
324 if (!mDataPtr)
return false;
325 return mDataPtr->mUnit == y;
328 OSStatus CAAudioUnit::RemovePropertyListener (AudioUnitPropertyID inID,
329 AudioUnitPropertyListenerProc inProc,
330 void * inProcUserData)
334 OSStatus result = AudioUnitRemovePropertyListenerWithUserData(AU(), inID,
335 inProc, inProcUserData);
336 #if !__LP64__ && !TARGET_OS_IPHONE
337 if (result) result = AudioUnitRemovePropertyListener (AU(), inID, inProc);
342 #pragma mark __State Management
344 bool CAAudioUnit::IsValid ()
const
346 return mDataPtr ? mDataPtr->mUnit != 0 :
false;
349 AudioUnit CAAudioUnit::AU()
const
351 return mDataPtr ? mDataPtr->mUnit : 0;
354 AUNode CAAudioUnit::GetAUNode ()
const
356 return mDataPtr ? mDataPtr->mNode : 0;
359 #pragma mark __Format Handling
361 bool CAAudioUnit::CanDo (
int inChannelsIn,
362 int inChannelsOut)
const
365 Boolean* isWritable = 0;
368 OSStatus result = AudioUnitGetPropertyInfo (AU(),
369 kAudioUnitProperty_SupportedNumChannels,
370 kAudioUnitScope_Global, 0,
371 &dataSize, isWritable);
377 if (Comp().Desc().IsEffect() && (inChannelsIn == inChannelsOut)
378 || Comp().Desc().IsOffline() && (inChannelsIn == inChannelsOut))
390 StackAUChannelInfo info (dataSize);
392 result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
393 kAudioUnitScope_Global, 0,
394 info.mChanInfo, &dataSize);
395 if (result) {
return false; }
397 return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo)));
400 bool CAAudioUnit::ValidateChannelPair (
int inChannelsIn,
402 const AUChannelInfo * info,
403 UInt32 numChanInfo)
const
418 for (
unsigned int i = 0; i < numChanInfo; ++i)
421 if ((info[i].inChannels < 0) && (info[i].outChannels < 0))
424 if (info[i].inChannels == -1 && info[i].outChannels == -1) {
425 if (inChannelsIn && inChannelsOut) {
426 if (inChannelsOut == inChannelsIn)
431 else if ((info[i].inChannels == -1 && info[i].outChannels == -2)
432 || (info[i].inChannels == -2 && info[i].outChannels == -1))
439 bool outWrite =
false;
bool inWrite =
false;
440 IsElementCountWritable (kAudioUnitScope_Output, outWrite);
441 IsElementCountWritable (kAudioUnitScope_Input, inWrite);
442 if (inWrite && outWrite) {
443 if ((inChannelsOut <= abs(info[i].outChannels))
444 && (inChannelsIn <= abs(info[i].inChannels)))
453 else if (info[i].inChannels < 0) {
454 if (info[i].outChannels == inChannelsOut)
457 if (info[i].inChannels == -1) {
462 bool inWrite =
false;
463 IsElementCountWritable (kAudioUnitScope_Input, inWrite);
464 if (inWrite && (inChannelsIn <= abs(info[i].inChannels))) {
472 else if (info[i].outChannels < 0) {
473 if (info[i].inChannels == inChannelsIn)
476 if (info[i].outChannels == -1) {
481 bool outWrite =
false;
482 IsElementCountWritable (kAudioUnitScope_Output, outWrite);
483 if (outWrite && (inChannelsOut <= abs(info[i].outChannels))) {
491 else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) {
497 else if (inChannelsIn == 0) {
498 if (info[i].outChannels == inChannelsOut) {
502 else if (inChannelsOut == 0) {
503 if (info[i].inChannels == inChannelsIn) {
512 bool CheckDynCount (SInt32 inTotalChans,
const CAAUChanHelper &inHelper)
515 for (
unsigned int i = 0; i < inHelper.mNumEls; ++i)
516 totalChans += inHelper.mChans[i];
517 return (totalChans <= inTotalChans);
520 bool CAAudioUnit::CheckOneSide (
const CAAUChanHelper &inHelper,
522 const AUChannelInfo *info,
523 UInt32 numInfo)
const
526 for (
unsigned int el = 0; el < inHelper.mNumEls; ++el) {
527 bool testAlready =
false;
528 for (
unsigned int i = 0; i < el; ++i) {
529 if (inHelper.mChans[i] == inHelper.mChans[el]) {
536 if (!ValidateChannelPair (0, inHelper.mChans[el], info, numInfo))
return false;
538 if (!ValidateChannelPair (inHelper.mChans[el], 0, info, numInfo))
return false;
545 bool CAAudioUnit::CanDo (
const CAAUChanHelper &inputs,
546 const CAAUChanHelper &outputs)
const
551 if (inputs.mNumEls == 0 && outputs.mNumEls == 0)
return false;
554 if (GetElementCount (kAudioUnitScope_Input, elCount)) {
return false; }
555 if (elCount != inputs.mNumEls)
return false;
557 if (GetElementCount (kAudioUnitScope_Output, elCount)) {
return false; }
558 if (elCount != outputs.mNumEls)
return false;
562 if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
563 kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr)
565 if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) {
566 UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0];
567 for (
unsigned int in = 0; in < inputs.mNumEls; ++in)
568 if (numChan != inputs.mChans[in])
return false;
569 for (
unsigned int out = 0; out < outputs.mNumEls; ++out)
570 if (numChan != outputs.mChans[out])
return false;
575 if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
576 for (
unsigned int in = 0; in < inputs.mNumEls; ++in) {
578 if (NumberChannels (kAudioUnitScope_Input, in, chan))
return false;
579 if (chan != UInt32(inputs.mChans[in]))
return false;
581 for (
unsigned int out = 0; out < outputs.mNumEls; ++out) {
583 if (NumberChannels (kAudioUnitScope_Output, out, chan))
return false;
584 if (chan != UInt32(outputs.mChans[out]))
return false;
593 StackAUChannelInfo info (dataSize);
595 if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
596 kAudioUnitScope_Global, 0,
597 info.mChanInfo, &dataSize) != noErr)
602 int numInfo = dataSize /
sizeof(AUChannelInfo);
605 SInt32 dynInChans = 0;
606 if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
607 if (CheckDynCount (dynInChans, inputs) ==
false)
return false;
610 SInt32 dynOutChans = 0;
611 if (ValidateDynamicScope (kAudioUnitScope_Output, dynOutChans, info.mChanInfo, numInfo)) {
612 if (CheckDynCount (dynOutChans, outputs) ==
false)
return false;
615 if (dynOutChans && dynInChans) {
return true; }
618 if (dynInChans || (inputs.mNumEls == 0)) {
619 return CheckOneSide (outputs,
true, info.mChanInfo, numInfo);
622 if (dynOutChans || (outputs.mNumEls == 0)) {
623 return CheckOneSide (inputs,
false, info.mChanInfo, numInfo);
627 for (
unsigned int in = 0; in < inputs.mNumEls; ++in)
629 bool testInAlready =
false;
630 for (
unsigned int i = 0; i < in; ++i) {
631 if (inputs.mChans[i] == inputs.mChans[in]) {
632 testInAlready =
true;
636 if (!testInAlready) {
637 for (
unsigned int out = 0; out < outputs.mNumEls; ++out) {
639 bool testOutAlready =
false;
640 for (
unsigned int i = 0; i < out; ++i) {
641 if (outputs.mChans[i] == outputs.mChans[out]) {
642 testOutAlready =
true;
646 if (!testOutAlready) {
647 if (!ValidateChannelPair (inputs.mChans[in], outputs.mChans[out],info.mChanInfo, numInfo)) {
658 bool CAAudioUnit::SupportsNumChannels ()
const
661 Boolean* isWritable = 0;
664 OSStatus result = AudioUnitGetPropertyInfo (AU(),
665 kAudioUnitProperty_SupportedNumChannels,
666 kAudioUnitScope_Global, 0,
667 &dataSize, isWritable);
672 if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline())
675 return result == noErr;
678 OSStatus CAAudioUnit::GetChannelLayoutTags (AudioUnitScope inScope,
679 AudioUnitElement inEl,
680 ChannelTagVector &outChannelVector)
const
682 if (HasChannelLayouts (inScope, inEl) ==
false)
return kAudioUnitErr_InvalidProperty;
685 OSStatus result = AudioUnitGetPropertyInfo (AU(),
686 kAudioUnitProperty_SupportedChannelLayoutTags,
690 if (result)
return result;
693 AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
694 result = AudioUnitGetProperty (AU(),
695 kAudioUnitProperty_SupportedChannelLayoutTags,
698 if (result)
goto home;
700 outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
701 for (
unsigned int i = 0; i < (dataSize /
sizeof (AudioChannelLayoutTag)); ++i)
702 outChannelVector.push_back (info[i]);
709 bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope,
710 AudioUnitElement inEl)
const
712 OSStatus result = AudioUnitGetPropertyInfo (AU(),
713 kAudioUnitProperty_SupportedChannelLayoutTags,
719 bool CAAudioUnit::HasChannelLayout (AudioUnitScope inScope,
720 AudioUnitElement inEl)
const
725 return AudioUnitGetPropertyInfo (AU(),
726 kAudioUnitProperty_AudioChannelLayout,
728 &size, &writable) == noErr;
731 OSStatus CAAudioUnit::GetChannelLayout (AudioUnitScope inScope,
732 AudioUnitElement inEl,
733 CAAudioChannelLayout &outLayout)
const
736 OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
737 inScope, inEl, &size, NULL);
738 if (result)
return result;
740 AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
742 ca_require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
743 inScope, inEl, layout, &size), home);
745 outLayout = CAAudioChannelLayout (layout);
752 OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
753 AudioUnitElement inEl,
754 const CAAudioChannelLayout &inLayout)
756 OSStatus result = AudioUnitSetProperty (AU(),
757 kAudioUnitProperty_AudioChannelLayout,
759 inLayout, inLayout.Size());
763 OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
764 AudioUnitElement inEl,
765 const AudioChannelLayout &inLayout,
768 OSStatus result = AudioUnitSetProperty (AU(),
769 kAudioUnitProperty_AudioChannelLayout,
775 OSStatus CAAudioUnit::ClearChannelLayout (AudioUnitScope inScope,
776 AudioUnitElement inEl)
778 return AudioUnitSetProperty (AU(),
779 kAudioUnitProperty_AudioChannelLayout,
780 inScope, inEl, NULL, 0);
783 OSStatus CAAudioUnit::GetFormat (AudioUnitScope inScope,
784 AudioUnitElement inEl,
785 AudioStreamBasicDescription &outFormat)
const
787 UInt32 dataSize =
sizeof (AudioStreamBasicDescription);
788 return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat,
790 &outFormat, &dataSize);
793 OSStatus CAAudioUnit::SetFormat (AudioUnitScope inScope,
794 AudioUnitElement inEl,
795 const AudioStreamBasicDescription &inFormat)
797 return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat,
799 const_cast<AudioStreamBasicDescription*>(&inFormat),
800 sizeof (AudioStreamBasicDescription));
803 OSStatus CAAudioUnit::GetSampleRate (AudioUnitScope inScope,
804 AudioUnitElement inEl,
805 Float64 &outRate)
const
807 UInt32 dataSize =
sizeof (Float64);
808 return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate,
810 &outRate, &dataSize);
813 OSStatus CAAudioUnit::SetSampleRate (AudioUnitScope inScope,
814 AudioUnitElement inEl,
817 AudioStreamBasicDescription desc;
818 OSStatus result = GetFormat (inScope, inEl, desc);
819 if (result)
return result;
820 desc.mSampleRate = inRate;
821 return SetFormat (inScope, inEl, desc);
824 OSStatus CAAudioUnit::SetSampleRate (Float64 inSampleRate)
829 ca_require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
831 for (
unsigned int i = 0; i < elCount; ++i) {
832 ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
836 ca_require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
838 for (
unsigned int i = 0; i < elCount; ++i) {
839 ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
847 OSStatus CAAudioUnit::NumberChannels (AudioUnitScope inScope,
848 AudioUnitElement inEl,
849 UInt32 &outChans)
const
851 AudioStreamBasicDescription desc;
852 OSStatus result = GetFormat (inScope, inEl, desc);
854 outChans = desc.mChannelsPerFrame;
858 OSStatus CAAudioUnit::SetNumberChannels (AudioUnitScope inScope,
859 AudioUnitElement inEl,
863 CAStreamBasicDescription desc;
864 OSStatus result = GetFormat (inScope, inEl, desc);
865 if (result)
return result;
866 desc.SetAUCanonical (inChans, desc.IsInterleaved());
867 result = SetFormat (inScope, inEl, desc);
871 OSStatus CAAudioUnit::IsElementCountWritable (AudioUnitScope inScope,
bool &outWritable)
const
875 OSStatus result = GetPropertyInfo (kAudioUnitProperty_ElementCount, inScope, 0, &outDataSize, &isWritable);
878 outWritable = isWritable ?
true :
false;
882 OSStatus CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount)
const
884 UInt32 propSize =
sizeof(outCount);
885 return GetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &outCount, &propSize);
888 OSStatus CAAudioUnit::SetElementCount (AudioUnitScope inScope, UInt32 inCount)
890 return SetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &inCount,
sizeof(inCount));
893 bool CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels)
const
897 Boolean* isWritable = 0;
899 OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
900 kAudioUnitScope_Global, 0,
901 &dataSize, isWritable);
904 if (result)
return false;
906 StackAUChannelInfo info (dataSize);
908 result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
909 kAudioUnitScope_Global, 0,
910 info.mChanInfo, &dataSize);
911 if (result)
return false;
913 return ValidateDynamicScope (inScope, outTotalNumChannels, info.mChanInfo, (dataSize /
sizeof(AUChannelInfo)));
924 bool CAAudioUnit::ValidateDynamicScope (AudioUnitScope inScope,
925 SInt32 &outTotalNumChannels,
926 const AUChannelInfo *info,
927 UInt32 numInfo)
const
929 bool writable =
false;
930 OSStatus result = IsElementCountWritable (inScope, writable);
931 if (result || (writable ==
false))
935 for (
unsigned int i = 0; i < numInfo; ++i)
939 if (((info[i].inChannels == -1) && (info[i].outChannels == -2))
940 || ((info[i].inChannels == -2) && (info[i].outChannels == -1)))
942 outTotalNumChannels = -1;
947 if (inScope == kAudioUnitScope_Input) {
949 if (info[i].inChannels >= 0)
952 if (info[i].inChannels < -2) {
953 outTotalNumChannels = abs (info[i].inChannels);
958 else if (inScope == kAudioUnitScope_Output) {
960 if (info[i].outChannels >= 0)
963 if (info[i].outChannels < -2) {
964 outTotalNumChannels = abs (info[i].outChannels);
977 OSStatus CAAudioUnit::ConfigureDynamicScope (AudioUnitScope inScope,
978 UInt32 inNumElements,
979 UInt32 *inChannelsPerElement,
980 Float64 inSampleRate)
982 SInt32 numChannels = 0;
983 bool isDyamic = HasDynamicScope (inScope, numChannels);
984 if (isDyamic ==
false)
985 return kAudioUnitErr_InvalidProperty;
989 if (numChannels > 0) {
991 for (
unsigned int i = 0; i < inNumElements; ++i)
992 count += inChannelsPerElement[i];
993 if (count > numChannels)
994 return kAudioUnitErr_InvalidPropertyValue;
997 OSStatus result = SetElementCount (inScope, inNumElements);
1001 CAStreamBasicDescription desc;
1002 desc.mSampleRate = inSampleRate;
1003 for (
unsigned int i = 0; i < inNumElements; ++i) {
1004 desc.SetAUCanonical (inChannelsPerElement[i],
false);
1005 result = SetFormat (inScope, i, desc);
1012 #pragma mark __Properties
1014 bool CAAudioUnit::CanBypass ()
const
1016 Boolean outWritable;
1017 OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_BypassEffect,
1018 kAudioUnitScope_Global, 0,
1019 NULL, &outWritable);
1020 return (!result && outWritable);
1023 bool CAAudioUnit::GetBypass ()
const
1025 UInt32 dataSize =
sizeof (UInt32);
1027 OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_BypassEffect,
1028 kAudioUnitScope_Global, 0,
1029 &outBypass, &dataSize);
1030 return (result ?
false : outBypass);
1033 OSStatus CAAudioUnit::SetBypass (
bool inBypass)
const
1035 UInt32 bypass = inBypass ? 1 : 0;
1036 return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect,
1037 kAudioUnitScope_Global, 0,
1038 &bypass,
sizeof (UInt32));
1041 Float64 CAAudioUnit::Latency ()
const
1044 UInt32 size =
sizeof(secs);
1045 if (GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &secs, &size))
1050 OSStatus CAAudioUnit::GetAUPreset (CFPropertyListRef &outData)
const
1052 UInt32 dataSize =
sizeof(outData);
1053 return AudioUnitGetProperty (AU(), kAudioUnitProperty_ClassInfo,
1054 kAudioUnitScope_Global, 0,
1055 &outData, &dataSize);
1058 OSStatus CAAudioUnit::SetAUPreset (CFPropertyListRef &inData)
1060 return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfo,
1061 kAudioUnitScope_Global, 0,
1062 &inData,
sizeof (CFPropertyListRef));
1065 #if !TARGET_OS_IPHONE
1066 OSStatus CAAudioUnit::SetAUPresetFromDocument (CFPropertyListRef &inData)
1068 return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfoFromDocument,
1069 kAudioUnitScope_Global, 0,
1070 &inData,
sizeof (CFPropertyListRef));
1074 OSStatus CAAudioUnit::GetPresentPreset (AUPreset &outData)
const
1076 UInt32 dataSize =
sizeof(outData);
1077 OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset,
1078 kAudioUnitScope_Global, 0,
1079 &outData, &dataSize);
1080 #if !TARGET_OS_IPHONE
1082 if (result == kAudioUnitErr_InvalidProperty) {
1083 dataSize =
sizeof(outData);
1084 result = AudioUnitGetProperty (AU(), kAudioUnitProperty_CurrentPreset,
1085 kAudioUnitScope_Global, 0,
1086 &outData, &dataSize);
1087 if (result == noErr) {
1090 if (outData.presetName)
1091 CFRetain (outData.presetName);
1099 OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData)
1101 OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset,
1102 kAudioUnitScope_Global, 0,
1103 &inData,
sizeof (AUPreset));
1104 #if !TARGET_OS_IPHONE
1106 if (result == kAudioUnitErr_InvalidProperty) {
1107 result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset,
1108 kAudioUnitScope_Global, 0,
1109 &inData,
sizeof (AUPreset));
1116 bool CAAudioUnit::HasCustomView ()
const
1118 #if !TARGET_OS_IPHONE
1119 UInt32 dataSize = 0;
1120 OSStatus result = -4;
1122 result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList,
1123 kAudioUnitScope_Global, 0,
1126 if (result || !dataSize) {
1128 result = GetPropertyInfo(kAudioUnitProperty_CocoaUI,
1129 kAudioUnitScope_Global, 0,
1131 if (result || !dataSize)
1141 OSStatus CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
1142 Float32 &outValue)
const
1144 return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : paramErr;
1147 OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
1148 Float32 value, UInt32 bufferOffsetFrames)
1150 return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : paramErr;
1153 #if !TARGET_OS_IPHONE
1154 OSStatus CAAudioUnit::MIDIEvent (UInt32 inStatus,
1157 UInt32 inOffsetSampleFrame)
1159 return mDataPtr ? mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr;
1162 OSStatus CAAudioUnit::StartNote (MusicDeviceInstrumentID inInstrument,
1163 MusicDeviceGroupID inGroupID,
1164 NoteInstanceID * outNoteInstanceID,
1165 UInt32 inOffsetSampleFrame,
1166 const MusicDeviceNoteParams * inParams)
1168 return mDataPtr ? mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams)
1172 OSStatus CAAudioUnit::StopNote (MusicDeviceGroupID inGroupID,
1173 NoteInstanceID inNoteInstanceID,
1174 UInt32 inOffsetSampleFrame)
1176 return mDataPtr ? mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr;
1181 #pragma mark __Render
1183 OSStatus CAAudioUnit::Render (AudioUnitRenderActionFlags * ioActionFlags,
1184 const AudioTimeStamp * inTimeStamp,
1185 UInt32 inOutputBusNumber,
1186 UInt32 inNumberFrames,
1187 AudioBufferList * ioData)
1189 return mDataPtr ? mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : paramErr;
1192 #pragma mark __CAAUChanHelper
1194 CAAUChanHelper::CAAUChanHelper(
const CAAudioUnit &inAU, AudioUnitScope inScope)
1195 :mChans(NULL), mNumEls(0), mDidAllocate(false)
1198 if (inAU.GetElementCount (inScope, elCount))
return;
1199 if (elCount > kStaticElCount) {
1200 mChans =
new UInt32[elCount];
1201 mDidAllocate =
true;
1202 memset (mChans, 0,
sizeof(
int) * elCount);
1204 mChans = mStaticChans;
1205 memset (mChans, 0,
sizeof(
int) * kStaticElCount);
1207 for (
unsigned int i = 0; i < elCount; ++i) {
1209 if (inAU.NumberChannels (inScope, i, numChans))
return;
1210 mChans[i] = numChans;
1215 CAAUChanHelper::CAAUChanHelper(UInt32 inMaxElems)
1216 : mNumEls(inMaxElems), mDidAllocate(false)
1218 if (inMaxElems > kStaticElCount) {
1219 mChans =
new UInt32[inMaxElems];
1220 mDidAllocate =
true;
1221 memset (mChans, 0,
sizeof(
int) * inMaxElems);
1223 mChans = mStaticChans;
1224 memset (mChans, 0,
sizeof(
int) * kStaticElCount);
1228 CAAUChanHelper::~CAAUChanHelper()
1230 if (mDidAllocate)
delete [] mChans;
1233 CAAUChanHelper& CAAUChanHelper::operator= (
const CAAUChanHelper &c)
1235 if (mDidAllocate)
delete [] mChans;
1236 if (c.mDidAllocate) {
1237 mChans =
new UInt32[c.mNumEls];
1238 mDidAllocate =
true;
1240 mDidAllocate =
false;
1241 mChans = mStaticChans;
1243 memcpy (mChans, c.mChans, c.mNumEls *
sizeof(
int));
1249 #pragma mark __Print Utilities
1251 void CAAudioUnit::Print (FILE* file)
const
1253 fprintf (file,
"AudioUnit:%p\n", AU());
1255 fprintf (file,
"\tnode=%ld\t", (
long)GetAUNode()); Comp().Print (file);
bool TTFOUNDATION_EXPORT operator==(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for equality.