1 /* 2 File: CAAudioUnit.h 3 Abstract: Part of CoreAudio Utility Classes 4 Version: 1.1 5 6 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 Inc. ("Apple") in consideration of your agreement to the following 8 terms, and your use, installation, modification or redistribution of 9 this Apple software constitutes acceptance of these terms. If you do 10 not agree with these terms, please do not use, install, modify or 11 redistribute this Apple software. 12 13 In consideration of your agreement to abide by the following terms, and 14 subject to these terms, Apple grants you a personal, non-exclusive 15 license, under Apple's copyrights in this original Apple software (the 16 "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 Software, with or without modifications, in source and/or binary forms; 18 provided that if you redistribute the Apple Software in its entirety and 19 without modifications, you must retain this notice and the following 20 text and disclaimers in all such redistributions of the Apple Software. 21 Neither the name, trademarks, service marks or logos of Apple Inc. may 22 be used to endorse or promote products derived from the Apple Software 23 without specific prior written permission from Apple. Except as 24 expressly stated in this notice, no other rights or licenses, express or 25 implied, are granted by Apple herein, including but not limited to any 26 patent rights that may be infringed by your derivative works or by other 27 works in which the Apple Software may be incorporated. 28 29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 POSSIBILITY OF SUCH DAMAGE. 43 44 Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 46 */ 47 #ifndef __CAAudioUnit_h__ 48 #define __CAAudioUnit_h__ 49 50 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) 51 #include <CoreAudio/CoreAudioTypes.h> 52 #include <AudioUnit/AudioUnit.h> 53 #include <AudioToolbox/AUGraph.h> 54 #include <AudioUnit/MusicDevice.h> 55 #else 56 #include <ConditionalMacros.h> 57 #include <CoreAudioTypes.h> 58 #include <AudioUnit.h> 59 #include <MusicDevice.h> 60 #include <AUGraph.h> 61 #include <MusicDevice.h> 62 #endif 63 64 #include <vector> 65 #include "CAStreamBasicDescription.h" 66 #include "CAComponent.h" 67 #include "CAAudioChannelLayout.h" 68 69 // defined below 70 class CAAUChanHelper; 71 72 // These constructors will NOT throw exceptions - so "check" after creation if AU IsValid() 73 // The destructor will NOT automatically close the AU down 74 // This state should be managed by the Caller 75 // once closed, the unit represented by this object is no longer valid 76 // it is up to the user of this object to ensure its validity is in sync 77 // if it is removed from a graph 78 79 // methods that can significantly change the state of the AU (like its format) are 80 // NOT const whereas those that don't change the externally related state of the AU are not const 81 82 class CAAudioUnit { 83 enum { 84 paramErr = -50, 85 badComponentSelector = (long)0x80008002 86 }; 87 public: 88 typedef std::vector<AudioChannelLayoutTag> ChannelTagVector; 89 typedef ChannelTagVector::iterator ChannelTagVectorIter; 90 91 public: CAAudioUnit()92 CAAudioUnit () 93 : mDataPtr(0) {} 94 95 CAAudioUnit (const AudioUnit& inUnit); 96 97 CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit); 98 CAAudioUnit(const CAAudioUnit & y)99 CAAudioUnit (const CAAudioUnit& y) 100 : mDataPtr(0) { *this = y; } 101 102 static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit); 103 104 ~CAAudioUnit (); 105 106 void Close (); 107 108 109 CAAudioUnit& operator= (const CAAudioUnit& y); 110 111 bool operator== (const CAAudioUnit& y) const; 112 113 bool operator== (const AudioUnit& y) const; 114 115 #pragma mark __State Management 116 bool IsValid () const; 117 118 AudioUnit AU() const; AudioUnit()119 operator AudioUnit () const { return AU(); } 120 Comp()121 const CAComponent& Comp() const { return mComp; } 122 Desc()123 const CAComponentDescription& Desc() const { return mComp.Desc(); } 124 FromAUGraph()125 bool FromAUGraph () const { return GetAUNode() != 0 && GetAUNode() != kCAAU_DoNotKnowIfAUNode; } 126 127 AUNode GetAUNode () const; AUNode()128 operator AUNode () const { return GetAUNode(); } 129 130 #pragma mark __API Wrapper Initialize()131 OSStatus Initialize() const { 132 return AudioUnitInitialize(AU()); 133 } Uninitialize()134 OSStatus Uninitialize() const { 135 return AudioUnitUninitialize(AU()); 136 } GetPropertyInfo(AudioUnitPropertyID propID,AudioUnitScope scope,AudioUnitElement element,UInt32 * outDataSize,Boolean * outWritable)137 OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, 138 UInt32 *outDataSize, Boolean *outWritable) const 139 { 140 return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable); 141 } GetProperty(AudioUnitPropertyID propID,AudioUnitScope scope,AudioUnitElement element,void * outData,UInt32 * ioDataSize)142 OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, 143 void *outData, UInt32 *ioDataSize) const 144 { 145 return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize); 146 } SetProperty(AudioUnitPropertyID propID,AudioUnitScope scope,AudioUnitElement element,const void * inData,UInt32 inDataSize)147 OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, 148 const void *inData, UInt32 inDataSize) 149 { 150 return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize); 151 } 152 OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, 153 Float32 value, UInt32 bufferOffsetFrames=0); 154 155 OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, 156 Float32 &outValue) const; 157 158 OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, 159 const AudioTimeStamp * inTimeStamp, 160 UInt32 inOutputBusNumber, 161 UInt32 inNumberFrames, 162 AudioBufferList * ioData); 163 164 OSStatus Process (AudioUnitRenderActionFlags & ioActionFlags, 165 const AudioTimeStamp & inTimeStamp, 166 UInt32 inNumberFrames, 167 AudioBufferList & ioData); 168 169 OSStatus ProcessMultiple (AudioUnitRenderActionFlags & ioActionFlags, 170 const AudioTimeStamp & inTimeStamp, 171 UInt32 inNumberFrames, 172 UInt32 inNumberInputBufferLists, 173 const AudioBufferList ** inInputBufferLists, 174 UInt32 inNumberOutputBufferLists, 175 AudioBufferList ** ioOutputBufferLists); 176 177 Reset(AudioUnitScope scope,AudioUnitElement element)178 OSStatus Reset (AudioUnitScope scope, AudioUnitElement element) 179 { 180 return AudioUnitReset (AU(), scope, element); 181 } GlobalReset()182 OSStatus GlobalReset () 183 { 184 return AudioUnitReset (AU(), kAudioUnitScope_Global, 0); 185 } 186 AddRenderNotify(AURenderCallback inProc,void * inProcRefCon)187 OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon) 188 { 189 return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon); 190 } 191 RemoveRenderNotify(AURenderCallback inProc,void * inProcRefCon)192 OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon) 193 { 194 return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon); 195 } 196 AddPropertyListener(AudioUnitPropertyID inID,AudioUnitPropertyListenerProc inProc,void * inProcRefCon)197 OSStatus AddPropertyListener (AudioUnitPropertyID inID, 198 AudioUnitPropertyListenerProc inProc, 199 void * inProcRefCon) 200 { 201 return AudioUnitAddPropertyListener (AU(), inID, inProc, inProcRefCon); 202 } 203 204 OSStatus RemovePropertyListener (AudioUnitPropertyID inID, 205 AudioUnitPropertyListenerProc inProc, 206 void * inProcUserData); 207 208 OSStatus MIDIEvent (UInt32 inStatus, 209 UInt32 inData1, 210 UInt32 inData2, 211 UInt32 inOffsetSampleFrame); 212 213 // uses the default VoiceForGroup value - this is the normal case StartNote(MusicDeviceGroupID inGroupID,NoteInstanceID * outNoteInstanceID,UInt32 inOffsetSampleFrame,const MusicDeviceNoteParams * inParams)214 OSStatus StartNote (MusicDeviceGroupID inGroupID, 215 NoteInstanceID * outNoteInstanceID, 216 UInt32 inOffsetSampleFrame, 217 const MusicDeviceNoteParams * inParams) 218 { 219 return StartNote (kMusicNoteEvent_UseGroupInstrument, 220 inGroupID, outNoteInstanceID, 221 inOffsetSampleFrame, inParams); 222 } 223 224 OSStatus StartNote (MusicDeviceInstrumentID inInstrument, 225 MusicDeviceGroupID inGroupID, 226 NoteInstanceID * outNoteInstanceID, 227 UInt32 inOffsetSampleFrame, 228 const MusicDeviceNoteParams * inParams); 229 230 OSStatus StopNote (MusicDeviceGroupID inGroupID, 231 NoteInstanceID inNoteInstanceID, 232 UInt32 inOffsetSampleFrame); 233 234 #pragma mark __Format Utilities 235 // typically you ask this about an AU 236 // These Questions are asking about Input and Output... 237 238 // These ones just say whether an AU can do a single combination of channels 239 // and is fine if the AU has a single output (and if an input, a single input) CanDo(int inChannelsInOut)240 bool CanDo (int inChannelsInOut) const 241 { 242 return CanDo (inChannelsInOut, inChannelsInOut); 243 } 244 245 bool CanDo ( int inChannelsIn, 246 int inChannelsOut) const; 247 248 // This version does a more thorough test for ANY AU with ANY ins/outs 249 // you pass in the channel helper (for the current element count on that scope) 250 251 bool CanDo ( const CAAUChanHelper &input, 252 const CAAUChanHelper &output) const; 253 254 bool SupportsNumChannels () const; 255 256 bool HasChannelLayouts (AudioUnitScope inScope, 257 AudioUnitElement inEl) const; 258 259 int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt); 260 OSStatus GetChannelLayoutTags (AudioUnitScope inScope, 261 AudioUnitElement inEl, 262 ChannelTagVector &outChannelVector) const; 263 264 bool HasChannelLayout (AudioUnitScope inScope, 265 AudioUnitElement inEl) const; 266 267 OSStatus GetChannelLayout (AudioUnitScope inScope, 268 AudioUnitElement inEl, 269 CAAudioChannelLayout &outLayout) const; 270 271 OSStatus SetChannelLayout (AudioUnitScope inScope, 272 AudioUnitElement inEl, 273 const CAAudioChannelLayout &inLayout); 274 275 OSStatus SetChannelLayout (AudioUnitScope inScope, 276 AudioUnitElement inEl, 277 const AudioChannelLayout &inLayout, 278 UInt32 inSize); 279 280 OSStatus ClearChannelLayout (AudioUnitScope inScope, 281 AudioUnitElement inEl); 282 283 OSStatus GetFormat (AudioUnitScope inScope, 284 AudioUnitElement inEl, 285 AudioStreamBasicDescription &outFormat) const; 286 // if an AudioChannelLayout is either required or set, this call can fail 287 // and the SetChannelLayout call should be used to set the format 288 OSStatus SetFormat (AudioUnitScope inScope, 289 AudioUnitElement inEl, 290 const AudioStreamBasicDescription &inFormat); 291 292 OSStatus GetSampleRate (AudioUnitScope inScope, 293 AudioUnitElement inEl, 294 Float64 &outRate) const; 295 OSStatus SetSampleRate (AudioUnitScope inScope, 296 AudioUnitElement inEl, 297 Float64 inRate); 298 299 // this sets the sample rate on all in/out buses of the AU 300 OSStatus SetSampleRate (Float64 inSampleRate); 301 302 OSStatus NumberChannels (AudioUnitScope inScope, 303 AudioUnitElement inEl, 304 UInt32 &outChans) const; 305 GetNumberChannels(AudioUnitScope inScope,AudioUnitElement inEl,UInt32 & outChans)306 OSStatus GetNumberChannels (AudioUnitScope inScope, 307 AudioUnitElement inEl, 308 UInt32 &outChans) const 309 { 310 return NumberChannels (inScope, inEl, outChans); 311 } 312 313 OSStatus SetNumberChannels (AudioUnitScope inScope, 314 AudioUnitElement inEl, 315 UInt32 inChans); 316 317 OSStatus IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const; 318 319 OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const; 320 321 OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount); 322 323 // value of -1 for outTotalNumChannels indicates no restriction on num channels 324 // for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to 325 // any number of channels. 326 // outTotalNumChannels is only valid if method returns true... HasDynamicInputs(SInt32 & outTotalNumChannels)327 bool HasDynamicInputs (SInt32 &outTotalNumChannels) const 328 { 329 return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels); 330 } 331 HasDynamicOutputs(SInt32 & outTotalNumChannels)332 bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const 333 { 334 return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels); 335 } 336 337 // here, if the in (or out) elements are dynamic, then you supply the number of elements 338 // you want on in (or out) scope, and the number of channels on each consecutive element ConfigureDynamicInput(UInt32 inNumElements,UInt32 * inChannelsPerElement,Float64 inSampleRate)339 OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) 340 { 341 return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate); 342 } 343 ConfigureDynamicOutput(UInt32 inNumElements,UInt32 * inChannelsPerElement,Float64 inSampleRate)344 OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) 345 { 346 return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate); 347 } 348 349 bool CanBypass () const; 350 351 bool GetBypass () const; 352 353 OSStatus SetBypass (bool inBypass) const; 354 355 OSStatus GetMaxFramesPerSlice (UInt32& outMaxFrames) const; 356 357 OSStatus SetMaxFramesPerSlice (UInt32 inMaxFrames); 358 359 Float64 Latency () const; 360 361 // these calls just deal with the global preset state 362 // you could rescope them to deal with presets on the part scope 363 OSStatus GetAUPreset (CFPropertyListRef &outData) const; 364 365 OSStatus SetAUPreset (CFPropertyListRef &inData); 366 367 OSStatus SetAUPresetFromDocument (CFPropertyListRef &inData); 368 369 OSStatus GetPresentPreset (AUPreset &outData) const; 370 371 OSStatus SetPresentPreset (AUPreset &inData); 372 373 bool HasCustomView () const; 374 375 #pragma mark __Print Print()376 void Print () const { Print (stdout); } 377 void Print (FILE* file) const; 378 379 private: 380 CAComponent mComp; 381 382 class AUState; 383 AUState* mDataPtr; 384 385 // this can throw - so wrap this up in a static that returns a result code... 386 CAAudioUnit (const CAComponent& inComp); 387 388 bool HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const; 389 OSStatus ConfigureDynamicScope (AudioUnitScope inScope, 390 UInt32 inNumElements, 391 UInt32 *inChannelsPerElement, 392 Float64 inSampleRate); 393 bool ValidateChannelPair (int inChannelsIn, 394 int inChannelsOut, 395 const AUChannelInfo * info, 396 UInt32 numChanInfo) const; 397 398 bool ValidateDynamicScope (AudioUnitScope inScope, 399 SInt32 &outTotalNumChannels, 400 const AUChannelInfo * info, 401 UInt32 numInfo) const; 402 bool CheckOneSide (const CAAUChanHelper &inHelper, 403 bool checkOutput, 404 const AUChannelInfo *info, 405 UInt32 numInfo) const; 406 enum { 407 kCAAU_DoNotKnowIfAUNode = -1 408 }; 409 }; 410 411 class CAAUChanHelper { 412 public: CAAUChanHelper()413 CAAUChanHelper() 414 : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) 415 { 416 memset (mChans, 0, sizeof(UInt32) * kStaticElCount); 417 } 418 CAAUChanHelper(UInt32 inMaxElems); 419 CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope); CAAUChanHelper(const CAAUChanHelper & c)420 CAAUChanHelper (const CAAUChanHelper &c) 421 : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) 422 { *this = c; } 423 424 ~CAAUChanHelper(); 425 426 CAAUChanHelper& operator= (const CAAUChanHelper &c); 427 428 UInt32 * mChans; 429 UInt32 mNumEls; 430 431 private: 432 enum { 433 kStaticElCount = 8 434 }; 435 UInt32 mStaticChans[kStaticElCount]; 436 bool mDidAllocate; 437 }; 438 439 #endif 440