/*============================================================================= CAAudioUnit.h $Log: CAAudioUnit.h,v $ Revision 1.47 2004/12/05 02:34:21 bills some tweaks to the multi can do Revision 1.46 2004/12/03 23:06:11 bills optimise CanDo checks Revision 1.45 2004/12/02 02:48:36 bills add full multi-bus CanDo support (inc. definition of CAAUChanHelper class) Revision 1.44 2004/11/29 22:58:27 bills add fast dispatch for MusicDeviceMIDIEvent Revision 1.43 2004/11/10 19:04:37 bills add global sample rate method Revision 1.42 2004/09/28 23:14:41 jcm10 flat includes Revision 1.41 2004/07/26 19:28:23 bills define equality operator Revision 1.40 2004/04/28 18:41:58 bills add HasCustomView Revision 1.39 2004/04/17 23:25:10 bills add method to get an AU's latency Revision 1.38 2003/12/13 23:31:50 bills add handlers for dynamic/configurable I/O Revision 1.37 2003/12/03 23:05:01 bills don't link in AUGraph API Revision 1.36 2003/11/20 22:56:53 dwyatt __COREAUDIO_USE_FLAT_INCLUDES__ Revision 1.35 2003/10/29 01:54:00 bills add element count API Revision 1.34 2003/10/25 00:17:46 bills fast dispatch support Revision 1.33 2003/10/22 00:33:26 bills add convenience for render notifications Revision 1.32 2003/10/19 20:46:40 bills add a preroll call Revision 1.31 2003/10/18 18:48:26 bills add supports num channels query Revision 1.30 2003/10/09 05:30:25 bills change GetNumChannels to NumberChannels for consistency Revision 1.29 2003/09/16 06:26:43 bills some methods should be const Revision 1.28 2003/08/16 20:55:15 bills add a couple more convenience calls Revision 1.27 2003/08/06 22:20:23 bills handle present preset property correctly Revision 1.26 2003/08/02 00:27:22 dwyatt add simple wrappers for most AudioUnit* functions Revision 1.25 2003/08/01 20:25:19 mhopkins Moved PrintMatrixMixerVolumes() into MatrixMixerVolumes.cpp Revision 1.24 2003/07/16 00:59:37 bills get/set AUPreset Revision 1.23 2003/07/08 14:53:42 bills reinstate alternate SetChanLayout Revision 1.22 2003/07/08 06:22:57 bills SetChannelLayout Revision 1.21 2003/07/08 00:03:57 bills remove unused ACL methods Revision 1.20 2003/07/07 18:36:05 bills fix some of the channel layout methods Revision 1.19 2003/06/15 23:58:48 bills make the opening of an AU a static method that returns a bad result code if it fails (nothing worse than failing silently) Revision 1.18 2003/06/02 19:25:15 bills tweaks Revision 1.17 2003/05/11 22:07:45 bills some tweaks Revision 1.16 2003/04/30 06:49:31 bills better use of const to define those things in an AU that should and shouldn't be changed if the AU is part of a graph Revision 1.15 2003/04/29 17:57:58 bills add print for matrix mixer Revision 1.14 2003/04/02 18:20:02 bills changes to make persistence work Revision 1.13 2003/03/30 23:10:45 bills ChannelMap to ChannelLayout Revision 1.12 2003/03/23 02:53:12 bills some rewrite and add methods Revision 1.11 2003/03/21 06:53:36 bills prelim impl of CA-AU persistence Revision 1.10 2003/03/19 21:16:34 bills changes to how CAAudioUnit manages its internal state Revision 1.9 2003/03/17 02:56:12 bills AU can now keep track of its active busses Revision 1.8 2003/03/15 18:32:35 bills some API tweaks Revision 1.7 2003/03/14 22:47:32 bills ACM handling Revision 1.6 2003/03/13 18:19:13 bills add handling of AudioChannelLayouts Revision 1.5 2003/03/12 23:38:21 bills CAAudioUnit::CanDo Revision 1.4 2003/03/12 06:49:45 bills redo CAAudioUnit to dynamically manage its state Revision 1.3 2003/03/12 05:05:05 bills refactor persistence Revision 1.2 2003/03/11 20:57:29 bills first pass at save/restore state Revision 1.1 2003/03/11 00:38:21 bills initial checkin Created by William Stewart on Sat Mar 08 2003. Copyright (c) 2003 Apple Computer. All rights reserved. =============================================================================*/ #ifndef __CAAudioUnit_h__ #define __CAAudioUnit_h__ #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) #include #include #include #include #else #include #include #include #include #include #endif #include #include "CAStreamBasicDescription.h" #include "CAComponent.h" #include "CAAudioChannelLayout.h" // defined below class CAAUChanHelper; // These constructors will NOT throw exceptions - so "check" after creation if AU IsValid() // The destructor will NOT automatically close the AU down // This state should be managed by the Caller // once closed, the unit represented by this object is no longer valid // it is up to the user of this object to ensure its validity is in sync // if it is removed from a graph // methods that can significantly change the state of the AU (like its format) are // NOT const whereas those that don't change the externally related state of the AU are not const class CAAudioUnit { public: typedef std::vector ChannelTagVector; typedef ChannelTagVector::iterator ChannelTagVectorIter; public: CAAudioUnit () : mDataPtr(0) {} CAAudioUnit (const AudioUnit& inUnit); CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit); CAAudioUnit (const CAAudioUnit& y) : mDataPtr(0) { *this = y; } static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit); ~CAAudioUnit (); CAAudioUnit& operator= (const CAAudioUnit& y); bool operator== (const CAAudioUnit& y) const; bool operator== (const AudioUnit& y) const; #pragma mark __State Management bool IsValid () const; AudioUnit AU() const; operator AudioUnit () const { return AU(); } const CAComponent& Comp() const { return mComp; } bool FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; } AUNode GetAUNode () const; operator AUNode () const { return GetAUNode(); } #pragma mark __API Wrapper OSStatus Initialize() const { return AudioUnitInitialize(AU()); } OSStatus Uninitialize() const { return AudioUnitUninitialize(AU()); } OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, UInt32 *outDataSize, Boolean *outWritable) const { return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable); } OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, void *outData, UInt32 *ioDataSize) const { return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize); } OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, const void *inData, UInt32 inDataSize) { return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize); } OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, Float32 value, UInt32 bufferOffsetFrames=0); OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, Float32 &outValue) const; OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData); OSStatus Reset (AudioUnitScope scope, AudioUnitElement element) { return AudioUnitReset (AU(), scope, element); } OSStatus GlobalReset () { return AudioUnitReset (AU(), kAudioUnitScope_Global, 0); } OSStatus Preroll (UInt32 inFrameSize); OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon) { return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon); } OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon) { return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon); } // Fast dispatch support for MIDI Effects or Music Devices OSStatus MIDIEvent (UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame); #pragma mark __Format Utilities // typically you ask this about an AU // These Questions are asking about Input and Output... // These ones just say whether an AU can do a single combination of channels // and is fine if the AU has a single output (and if an input, a single input) bool CanDo (int inChannelsInOut) const { return CanDo (inChannelsInOut, inChannelsInOut); } bool CanDo ( int inChannelsIn, int inChannelsOut) const; // This version does a more thorough test for ANY AU with ANY ins/outs // you pass in the channel helper (for the current element count on that scope) bool CanDo ( const CAAUChanHelper &input, const CAAUChanHelper &output) const; bool SupportsNumChannels () const; bool HasChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl) const; bool GetChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl, ChannelTagVector &outChannelVector) const; OSStatus GetChannelLayout (AudioUnitScope inScope, AudioUnitElement inEl, CAAudioChannelLayout &outLayout) const; OSStatus SetChannelLayout (AudioUnitScope inScope, AudioUnitElement inEl, CAAudioChannelLayout &inLayout); OSStatus SetChannelLayout (AudioUnitScope inScope, AudioUnitElement inEl, AudioChannelLayout &inLayout, UInt32 inSize); OSStatus ClearChannelLayout (AudioUnitScope inScope, AudioUnitElement inEl); OSStatus GetFormat (AudioUnitScope inScope, AudioUnitElement inEl, AudioStreamBasicDescription &outFormat) const; // if an AudioChannelLayout is either required or set, this call can fail // and the SetChannelLayout call should be used to set the format OSStatus SetFormat (AudioUnitScope inScope, AudioUnitElement inEl, const AudioStreamBasicDescription &inFormat); OSStatus GetSampleRate (AudioUnitScope inScope, AudioUnitElement inEl, Float64 &outRate) const; OSStatus SetSampleRate (AudioUnitScope inScope, AudioUnitElement inEl, Float64 inRate); // this sets the sample rate on all in/out buses of the AU OSStatus SetSampleRate (Float64 inSampleRate); OSStatus NumberChannels (AudioUnitScope inScope, AudioUnitElement inEl, UInt32 &outChans) const; OSStatus IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const; OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const; OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount); // value of -1 for outTotalNumChannels indicates no restriction on num channels // for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to // any number of channels. // outTotalNumChannels is only valid if method returns true... bool HasDynamicInputs (SInt32 &outTotalNumChannels) const { return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels); } bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const { return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels); } // here, if the in (or out) elements are dynamic, then you supply the number of elements // you want on in (or out) scope, and the number of channels on each consecutive element OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) { return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate); } OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) { return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate); } bool CanBypass () const; bool GetBypass () const; OSStatus SetBypass (bool inBypass) const; Float64 Latency () const; // these calls just deal with the global preset state // you could rescope them to deal with presets on the part scope OSStatus GetAUPreset (CFPropertyListRef &outData) const; OSStatus SetAUPreset (CFPropertyListRef &inData); OSStatus GetPresentPreset (AUPreset &outData) const; OSStatus SetPresentPreset (AUPreset &inData); bool HasCustomView () const; #pragma mark __Print void Print () const { Print (stdout); } void Print (FILE* file) const; private: CAComponent mComp; class AUState; AUState* mDataPtr; // this can throw - so wrap this up in a static that returns a result code... CAAudioUnit (const CAComponent& inComp); bool HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const; OSStatus ConfigureDynamicScope (AudioUnitScope inScope, UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate); bool ValidateChannelPair (int inChannelsIn, int inChannelsOut, const AUChannelInfo * info, UInt32 numChanInfo) const; bool ValidateDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels, const AUChannelInfo * info, UInt32 numInfo) const; bool CheckOneSide (const CAAUChanHelper &inHelper, bool checkOutput, const AUChannelInfo *info, UInt32 numInfo) const; }; class CAAUChanHelper { public: CAAUChanHelper() : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) { memset (mChans, 0, sizeof(UInt32) * 8); } CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope); CAAUChanHelper (const CAAUChanHelper &c) :mChans(mStaticChans), mNumEls(0), mDidAllocate(false) { *this = c; } ~CAAUChanHelper(); CAAUChanHelper& operator= (const CAAUChanHelper &c); UInt32 * mChans; UInt32 mNumEls; private: UInt32 mStaticChans[8]; bool mDidAllocate; }; #endif