1 /* Copyright © 2007 Apple Inc. All Rights Reserved.
3 Disclaimer: IMPORTANT: This Apple software is supplied to you by
4 Apple Inc. ("Apple") in consideration of your agreement to the
5 following terms, and your use, installation, modification or
6 redistribution of this Apple software constitutes acceptance of these
7 terms. If you do not agree with these terms, please do not use,
8 install, modify or redistribute this Apple software.
10 In consideration of your agreement to abide by the following terms, and
11 subject to these terms, Apple grants you a personal, non-exclusive
12 license, under Apple's copyrights in this original Apple software (the
13 "Apple Software"), to use, reproduce, modify and redistribute the Apple
14 Software, with or without modifications, in source and/or binary forms;
15 provided that if you redistribute the Apple Software in its entirety and
16 without modifications, you must retain this notice and the following
17 text and disclaimers in all such redistributions of the Apple Software.
18 Neither the name, trademarks, service marks or logos of Apple Inc.
19 may be used to endorse or promote products derived from the Apple
20 Software without specific prior written permission from Apple. Except
21 as expressly stated in this notice, no other rights or licenses, express
22 or implied, are granted by Apple herein, including but not limited to
23 any patent rights that may be infringed by your derivative works or by
24 other works in which the Apple Software may be incorporated.
26 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
32 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
41 /*=============================================================================
44 =============================================================================*/
49 #include <TargetConditionals.h>
56 #error Unsupported Operating System
61 #include "ComponentBase.h"
62 #include "AUScopeElement.h"
63 #include "AUInputElement.h"
64 #include "AUOutputElement.h"
67 #include "CAThreadSafeList.h"
68 #include "CAVectorUnit.h"
70 typedef AUElement AUGlobalElement
;
71 typedef AUElement AUGroupElement
;
72 typedef AUElement AUPartElement
;
74 // ________________________________________________________________________
75 // These are to be moved to the public AudioUnit headers
77 #define kAUDefaultSampleRate 44100.0
79 #define kAUDefaultMaxFramesPerSlice 1156
80 //this allows enough default frames for a 512 dest 44K and SRC from 96K
81 // add a padding of 4 frames for any altivec rounding
83 #define kAUDefaultMaxFramesPerSlice 2048
86 class AUDebugDispatcher
;
88 // ________________________________________________________________________
91 class AUBase
: public ComponentBase
, public AUElementCreator
{
95 AUBase( AudioUnit inInstance
,
96 UInt32 numInputElements
,
97 UInt32 numOutputElements
,
98 UInt32 numGroupElements
= 0,
99 UInt32 numPartElements
= 0);
103 /*! @method PostConstructor */
104 virtual void PostConstructor() { CreateElements(); }
106 /*! @method PreDestructor */
107 virtual void PreDestructor();
109 /*! @method CreateElements */
110 void CreateElements();
111 // Called immediately after construction, when virtual methods work.
112 // Or, a subclass may call this in order to have access to elements
113 // in its constructor.
115 // ________________________________________________________________________
116 // Virtual methods (mostly) directly corresponding to the entry points. Many of these
117 // have useful implementations here and will not need overriding.
119 /*! @method DoInitialize */
120 ComponentResult
DoInitialize();
121 // this implements the entry point and makes sure that initialization
122 // is only attempted exactly once...
124 /*! @method Initialize */
125 virtual ComponentResult
Initialize();
126 // ... so that overrides to this method can assume that they will only
127 // be called exactly once.
129 /*! @method IsInitialized */
130 bool IsInitialized() const { return mInitialized
; }
132 /*! @method DoCleanup */
134 // same pattern as with Initialize
136 /*! @method Cleanup */
137 virtual void Cleanup();
140 virtual ComponentResult
Reset( AudioUnitScope inScope
,
141 AudioUnitElement inElement
);
143 // Note about GetPropertyInfo, GetProperty, SetProperty:
144 // Certain properties are trapped out in these dispatch functions and handled with different virtual
145 // methods. (To discourage hacks and keep vtable size down, these are non-virtual)
147 /*! @method DispatchGetPropertyInfo */
148 ComponentResult
DispatchGetPropertyInfo(AudioUnitPropertyID inID
,
149 AudioUnitScope inScope
,
150 AudioUnitElement inElement
,
151 UInt32
& outDataSize
,
152 Boolean
& outWritable
);
154 /*! @method DispatchGetProperty */
155 ComponentResult
DispatchGetProperty( AudioUnitPropertyID inID
,
156 AudioUnitScope inScope
,
157 AudioUnitElement inElement
,
160 /*! @method DispatchSetProperty */
161 ComponentResult
DispatchSetProperty( AudioUnitPropertyID inID
,
162 AudioUnitScope inScope
,
163 AudioUnitElement inElement
,
167 ComponentResult
DispatchRemovePropertyValue( AudioUnitPropertyID inID
,
168 AudioUnitScope inScope
,
169 AudioUnitElement inElement
);
171 /*! @method GetPropertyInfo */
172 virtual ComponentResult
GetPropertyInfo( AudioUnitPropertyID inID
,
173 AudioUnitScope inScope
,
174 AudioUnitElement inElement
,
175 UInt32
& outDataSize
,
176 Boolean
& outWritable
);
178 /*! @method GetProperty */
179 virtual ComponentResult
GetProperty( AudioUnitPropertyID inID
,
180 AudioUnitScope inScope
,
181 AudioUnitElement inElement
,
184 /*! @method SetProperty */
185 virtual ComponentResult
SetProperty( AudioUnitPropertyID inID
,
186 AudioUnitScope inScope
,
187 AudioUnitElement inElement
,
191 /*! @method ClearPropertyUsage */
192 virtual ComponentResult
RemovePropertyValue ( AudioUnitPropertyID inID
,
193 AudioUnitScope inScope
,
194 AudioUnitElement inElement
);
196 /*! @method AddPropertyListener */
197 virtual ComponentResult
AddPropertyListener( AudioUnitPropertyID inID
,
198 AudioUnitPropertyListenerProc inProc
,
199 void * inProcRefCon
);
201 /*! @method RemovePropertyListener */
202 virtual ComponentResult
RemovePropertyListener( AudioUnitPropertyID inID
,
203 AudioUnitPropertyListenerProc inProc
,
205 bool refConSpecified
);
207 /*! @method SetRenderNotification */
208 virtual ComponentResult
SetRenderNotification( ProcPtr inProc
,
211 /*! @method RemoveRenderNotification */
212 virtual ComponentResult
RemoveRenderNotification(
216 /*! @method GetParameter */
217 virtual ComponentResult
GetParameter( AudioUnitParameterID inID
,
218 AudioUnitScope inScope
,
219 AudioUnitElement inElement
,
220 AudioUnitParameterValue
& outValue
);
222 /*! @method SetParameter */
223 virtual ComponentResult
SetParameter( AudioUnitParameterID inID
,
224 AudioUnitScope inScope
,
225 AudioUnitElement inElement
,
226 AudioUnitParameterValue inValue
,
227 UInt32 inBufferOffsetInFrames
);
229 /*! @method SetGroupParameter */
230 virtual ComponentResult
SetGroupParameter( AudioUnitParameterID inID
,
231 AudioUnitElement inElement
,
232 AudioUnitParameterValue inValue
,
233 UInt32 inBufferOffsetInFrames
);
235 /*! @method GetGroupParameter */
236 virtual ComponentResult
GetGroupParameter( AudioUnitParameterID inID
,
237 AudioUnitElement inElement
,
238 AudioUnitParameterValue
& outValue
);
240 /*! @method ScheduleParameter */
241 virtual ComponentResult
ScheduleParameter ( const AudioUnitParameterEvent
*inParameterEvent
,
245 /*! @method DoRender */
246 ComponentResult
DoRender( AudioUnitRenderActionFlags
& ioActionFlags
,
247 const AudioTimeStamp
& inTimeStamp
,
249 UInt32 inNumberFrames
,
250 AudioBufferList
& ioData
);
253 // Override this method if your AU processes multiple output busses completely independently --
254 // you'll want to just call Render without the NeedsToRender check.
255 // Otherwise, override Render().
257 // N.B. Implementations of this method can assume that the output's buffer list has already been
258 // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
259 // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
260 // copy may occur after rendering.
261 /*! @method RenderBus */
262 virtual ComponentResult
RenderBus( AudioUnitRenderActionFlags
& ioActionFlags
,
263 const AudioTimeStamp
& inTimeStamp
,
265 UInt32 inNumberFrames
)
267 if (NeedsToRender(inTimeStamp
.mSampleTime
))
268 return Render(ioActionFlags
, inTimeStamp
, inNumberFrames
);
269 return noErr
; // was presumably already rendered via another bus
272 // N.B. For a unit with only one output bus, it can assume in its implementation of this
273 // method that the output's buffer list has already been prepared and access it with
274 // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
275 // -- if PrepareBuffer is called, a copy may occur after rendering.
276 /*! @method Render */
277 virtual ComponentResult
Render( AudioUnitRenderActionFlags
& ioActionFlags
,
278 const AudioTimeStamp
& inTimeStamp
,
279 UInt32 inNumberFrames
)
285 static const Float64 kNoLastRenderedSampleTime
;
287 // ________________________________________________________________________
288 // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
290 /*! @method BusCountWritable */
291 virtual bool BusCountWritable( AudioUnitScope inScope
)
295 virtual ComponentResult
SetBusCount( AudioUnitScope inScope
,
298 /*! @method SetConnection */
299 virtual ComponentResult
SetConnection( const AudioUnitConnection
& inConnection
);
301 /*! @method SetInputCallback */
302 virtual ComponentResult
SetInputCallback( UInt32 inPropertyID
,
303 AudioUnitElement inElement
,
307 /*! @method GetParameterList */
308 virtual ComponentResult
GetParameterList( AudioUnitScope inScope
,
309 AudioUnitParameterID
* outParameterList
,
310 UInt32
& outNumParameters
);
311 // outParameterList may be a null pointer
313 /*! @method GetParameterInfo */
314 virtual ComponentResult
GetParameterInfo( AudioUnitScope inScope
,
315 AudioUnitParameterID inParameterID
,
316 AudioUnitParameterInfo
& outParameterInfo
);
318 /*! @method SaveState */
319 virtual ComponentResult
SaveState( CFPropertyListRef
* outData
);
321 /*! @method RestoreState */
322 virtual ComponentResult
RestoreState( CFPropertyListRef inData
);
324 /*! @method GetParameterValueStrings */
325 virtual ComponentResult
GetParameterValueStrings(AudioUnitScope inScope
,
326 AudioUnitParameterID inParameterID
,
327 CFArrayRef
* outStrings
);
329 /*! @method GetPresets */
330 virtual ComponentResult
GetPresets ( CFArrayRef
* outData
) const;
332 // set the default preset for the unit -> the number of the preset MUST be >= 0
333 // and the name should be valid, or the preset WON'T take
334 /*! @method SetAFactoryPresetAsCurrent */
335 bool SetAFactoryPresetAsCurrent (const AUPreset
& inPreset
);
337 // Called when someone sets a new, valid preset
338 // If this is a valid preset, then the subclass sets its state to that preset
339 // and returns noErr.
340 // If not a valid preset, return an error, and the pre-existing preset is restored
341 /*! @method NewFactoryPresetSet */
342 virtual OSStatus
NewFactoryPresetSet (const AUPreset
& inNewFactoryPreset
);
344 /*! @method GetNumCustomUIComponents */
345 virtual int GetNumCustomUIComponents ();
346 /*! @method GetUIComponentDescs */
347 virtual void GetUIComponentDescs (ComponentDescription
* inDescArray
);
349 /*! @method CopyIconLocation */
350 virtual CFURLRef
CopyIconLocation ();
352 // default is no latency, and unimplemented tail time
353 /*! @method GetLatency */
354 virtual Float64
GetLatency() {return 0.0;}
355 /*! @method GetTailTime */
356 virtual Float64
GetTailTime() {return 0;}
357 /*! @method SupportsRampAndTail */
358 virtual bool SupportsTail () { return false; }
360 /*! @method IsStreamFormatWritable */
361 bool IsStreamFormatWritable( AudioUnitScope scope
,
362 AudioUnitElement element
);
364 /*! @method StreamFormatWritable */
365 virtual bool StreamFormatWritable( AudioUnitScope scope
,
366 AudioUnitElement element
) = 0;
367 // scope will always be input or output
369 // pass in a pointer to get the struct, and num channel infos
370 // you can pass in NULL to just get the number
371 // a return value of 0 (the default in AUBase) means the property is not supported...
372 /*! @method SupportedNumChannels */
373 virtual UInt32
SupportedNumChannels ( const AUChannelInfo
** outInfo
);
375 /*! @method ValidFormat */
376 virtual bool ValidFormat( AudioUnitScope inScope
,
377 AudioUnitElement inElement
,
378 const CAStreamBasicDescription
& inNewFormat
);
379 // Will only be called after StreamFormatWritable
381 // Default implementation requires canonical format:
382 // native-endian 32-bit float, any sample rate,
383 // any number of channels; override when other
384 // formats are supported. A subclass's override can
385 // choose to always return true and trap invalid
386 // formats in ChangeStreamFormat.
389 /*! @method FormatIsCanonical */
390 bool FormatIsCanonical( const CAStreamBasicDescription
&format
);
392 /*! @method MakeCanonicalFormat */
393 void MakeCanonicalFormat( CAStreamBasicDescription
& outDesc
,
394 int numChannels
= 2);
396 /*! @method GetStreamFormat */
397 virtual const CAStreamBasicDescription
&
398 GetStreamFormat( AudioUnitScope inScope
,
399 AudioUnitElement inElement
);
401 /*! @method ChangeStreamFormat */
402 virtual ComponentResult
ChangeStreamFormat( AudioUnitScope inScope
,
403 AudioUnitElement inElement
,
404 const CAStreamBasicDescription
& inPrevFormat
,
405 const CAStreamBasicDescription
& inNewFormat
);
406 // Will only be called after StreamFormatWritable
407 // and ValidFormat have succeeded.
409 // ________________________________________________________________________
411 /*! @method ComponentEntryDispatch */
412 static ComponentResult
ComponentEntryDispatch( ComponentParameters
* params
,
415 // ________________________________________________________________________
416 // Methods useful for subclasses
418 /*! @method GetScope */
419 AUScope
& GetScope( AudioUnitScope inScope
)
421 if (inScope
>= kNumScopes
) COMPONENT_THROW(kAudioUnitErr_InvalidScope
);
422 return mScopes
[inScope
];
425 /*! @method GlobalScope */
426 AUScope
& GlobalScope() { return mScopes
[kAudioUnitScope_Global
]; }
427 /*! @method Inputs */
428 AUScope
& Inputs() { return mScopes
[kAudioUnitScope_Input
]; }
429 /*! @method Outputs */
430 AUScope
& Outputs() { return mScopes
[kAudioUnitScope_Output
]; }
431 /*! @method Groups */
432 AUScope
& Groups() { return mScopes
[kAudioUnitScope_Group
]; }
433 /*! @method Groups */
434 AUScope
& Parts() { return mScopes
[kAudioUnitScope_Part
]; }
435 /*! @method Globals */
436 AUElement
* Globals() { return mScopes
[kAudioUnitScope_Global
].GetElement(0); }
438 /*! @method SetNumberOfElements */
439 void SetNumberOfElements( AudioUnitScope inScope
,
442 /*! @method GetElement */
443 AUElement
* GetElement( AudioUnitScope inScope
,
444 AudioUnitElement inElement
)
446 return GetScope(inScope
).GetElement(inElement
);
449 /*! @method GetIOElement */
450 AUIOElement
* GetIOElement( AudioUnitScope inScope
,
451 AudioUnitElement inElement
)
453 return GetScope(inScope
).GetIOElement(inElement
);
456 /*! @method SafeGetElement */
457 AUElement
* SafeGetElement( AudioUnitScope inScope
,
458 AudioUnitElement inElement
)
460 return GetScope(inScope
).SafeGetElement(inElement
);
463 /*! @method GetInput */
464 AUInputElement
* GetInput( AudioUnitElement inElement
)
466 return static_cast<AUInputElement
*>(Inputs().SafeGetElement(inElement
));
469 /*! @method GetOutput */
470 AUOutputElement
* GetOutput( AudioUnitElement inElement
)
472 return static_cast<AUOutputElement
*>(Outputs().SafeGetElement(inElement
));
475 /*! @method GetGroup */
476 AUGroupElement
* GetGroup( AudioUnitElement inElement
)
478 return static_cast<AUGroupElement
*>(Groups().SafeGetElement(inElement
));
481 /*! @method PullInput */
482 ComponentResult
PullInput( UInt32 inBusNumber
,
483 AudioUnitRenderActionFlags
&ioActionFlags
,
484 const AudioTimeStamp
& inTimeStamp
,
485 UInt32 inNumberFrames
)
487 AUInputElement
*input
= GetInput(inBusNumber
); // throws if error
488 return input
->PullInput(ioActionFlags
, inTimeStamp
, inBusNumber
, inNumberFrames
);
491 /*! @method GetMaxFramesPerSlice */
492 UInt32
GetMaxFramesPerSlice() const { return mMaxFramesPerSlice
; }
494 /*! @method GetVectorUnitType */
495 static SInt32
GetVectorUnitType() { return sVectorUnitType
; }
496 /*! @method HasVectorUnit */
497 static bool HasVectorUnit() { return sVectorUnitType
> 0; }
498 /*! @method HasAltivec */
499 static bool HasAltivec() { return sVectorUnitType
== kVecAltivec
; }
500 /*! @method HasSSE2 */
501 static bool HasSSE2() { return sVectorUnitType
>= kVecSSE2
; }
502 /*! @method HasSSE3 */
503 static bool HasSSE3() { return sVectorUnitType
== kVecSSE3
; }
505 /*! @method AudioUnitAPIVersion */
506 UInt8
AudioUnitAPIVersion() const { return mAudioUnitAPIVersion
; }
508 /*! @method IsRenderThread */
509 bool InRenderThread () const
512 return (mRenderThreadID
? pthread_equal (mRenderThreadID
, pthread_self()) : false);
513 #elif TARGET_OS_WIN32
514 return (mRenderThreadID
? mRenderThreadID
== GetCurrentThreadId() : false);
518 /*! @method HasInput */
519 bool HasInput( AudioUnitElement inElement
) {
520 AUInputElement
*in
= GetInput(inElement
);
521 return in
!= NULL
&& in
->IsActive();
523 // says whether an input is connected or has a callback
526 // These calls can be used to call a Host's Callbacks. The method returns -1 if the host
527 // hasn't supplied the callback. Any other result is returned by the host.
528 // As in the API contract, for a parameter's value, you specify a pointer
529 // to that data type. Specify NULL for a parameter that you are not interested
530 // as this can save work in the host.
532 /*! @method CallHostBeatAndTempo */
533 OSStatus
CallHostBeatAndTempo (Float64
*outCurrentBeat
,
534 Float64
*outCurrentTempo
)
536 return (mHostCallbackInfo
.beatAndTempoProc
537 ? (*mHostCallbackInfo
.beatAndTempoProc
) (mHostCallbackInfo
.hostUserData
,
543 /*! @method CallHostMusicalTimeLocation */
544 OSStatus
CallHostMusicalTimeLocation (UInt32
*outDeltaSampleOffsetToNextBeat
,
545 Float32
*outTimeSig_Numerator
,
546 UInt32
*outTimeSig_Denominator
,
547 Float64
*outCurrentMeasureDownBeat
)
549 return (mHostCallbackInfo
.musicalTimeLocationProc
550 ? (*mHostCallbackInfo
.musicalTimeLocationProc
) (mHostCallbackInfo
.hostUserData
,
551 outDeltaSampleOffsetToNextBeat
,
552 outTimeSig_Numerator
,
553 outTimeSig_Denominator
,
554 outCurrentMeasureDownBeat
)
558 /*! @method CallHostTransportState */
559 OSStatus
CallHostTransportState (Boolean
*outIsPlaying
,
560 Boolean
*outTransportStateChanged
,
561 Float64
*outCurrentSampleInTimeLine
,
562 Boolean
*outIsCycling
,
563 Float64
*outCycleStartBeat
,
564 Float64
*outCycleEndBeat
)
566 return (mHostCallbackInfo
.transportStateProc
567 ? (*mHostCallbackInfo
.transportStateProc
) (mHostCallbackInfo
.hostUserData
,
569 outTransportStateChanged
,
570 outCurrentSampleInTimeLine
,
577 /*! @method PropertyChanged */
578 void PropertyChanged( AudioUnitPropertyID inID
,
579 AudioUnitScope inScope
,
580 AudioUnitElement inElement
);
583 char* GetLoggingString () const;
586 // ________________________________________________________________________
587 // AUElementCreator override, may be further overridden by subclasses
588 /*! @method CreateElement */
589 virtual AUElement
* CreateElement( AudioUnitScope scope
,
590 AudioUnitElement element
);
592 /*! @method ReallocateBuffers */
593 virtual void ReallocateBuffers();
594 // needs to be called when mMaxFramesPerSlice changes
596 /*! @method FillInParameterName */
597 static void FillInParameterName (AudioUnitParameterInfo
& ioInfo
, CFStringRef inName
, bool inShouldRelease
)
599 ioInfo
.cfNameString
= inName
;
600 ioInfo
.flags
|= kAudioUnitParameterFlag_HasCFNameString
;
602 ioInfo
.flags
|= kAudioUnitParameterFlag_CFNameRelease
;
603 CFStringGetCString (inName
, ioInfo
.name
, offsetof (AudioUnitParameterInfo
, clumpID
), kCFStringEncodingUTF8
);
606 static void HasClump (AudioUnitParameterInfo
& ioInfo
, UInt32 inClumpID
)
608 ioInfo
.clumpID
= inClumpID
;
609 ioInfo
.flags
|= kAudioUnitParameterFlag_HasClump
;
612 /*! @method SetMaxFramesPerSlice */
613 virtual void SetMaxFramesPerSlice(UInt32 nFrames
);
615 /*! @method CanSetMaxFrames */
616 virtual OSStatus
CanSetMaxFrames() const;
618 /*! @method WantsRenderThreadID */
619 bool WantsRenderThreadID () const { return mWantsRenderThreadID
; }
621 /*! @method SetWantsRenderThreadID */
622 void SetWantsRenderThreadID (bool inFlag
);
624 /*! @method SetRenderError */
625 OSStatus
SetRenderError (OSStatus inErr
)
627 if (inErr
&& mLastRenderError
== 0) {
628 mLastRenderError
= inErr
;
629 PropertyChanged(kAudioUnitProperty_LastRenderError
, kAudioUnitScope_Global
, 0);
635 /*! @method DoRenderBus */
636 // shared between Render and RenderSlice, inlined to minimize function call overhead
637 ComponentResult
DoRenderBus( AudioUnitRenderActionFlags
& ioActionFlags
,
638 const AudioTimeStamp
& inTimeStamp
,
640 AUOutputElement
* theOutput
,
641 UInt32 inNumberFrames
,
642 AudioBufferList
& ioData
)
644 if (ioData
.mBuffers
[0].mData
== NULL
|| Outputs().GetNumberOfElements() > 1)
645 // will render into cache buffer
646 theOutput
->PrepareBuffer(inNumberFrames
);
648 // will render into caller's buffer
649 theOutput
->SetBufferList(ioData
);
650 ComponentResult result
= RenderBus(
651 ioActionFlags
, inTimeStamp
,
652 inBusNumber
, inNumberFrames
);
653 if (result
== noErr
) {
654 if (ioData
.mBuffers
[0].mData
== NULL
)
655 theOutput
->CopyBufferListTo(ioData
);
657 theOutput
->CopyBufferContentsTo(ioData
);
658 theOutput
->InvalidateBufferList();
664 /*! @method HasIcon */
668 /*! @method GetAudioChannelLayout */
669 virtual UInt32
GetChannelLayoutTags( AudioUnitScope scope
,
670 AudioUnitElement element
,
671 AudioChannelLayoutTag
* outLayoutTags
);
673 /*! @method GetAudioChannelLayout */
674 virtual UInt32
GetAudioChannelLayout( AudioUnitScope scope
,
675 AudioUnitElement element
,
676 AudioChannelLayout
* outLayoutPtr
,
677 Boolean
& outWritable
);
679 /*! @method SetAudioChannelLayout */
680 virtual OSStatus
SetAudioChannelLayout( AudioUnitScope scope
,
681 AudioUnitElement element
,
682 const AudioChannelLayout
* inLayout
);
684 /*! @method RemoveAudioChannelLayout */
685 virtual OSStatus
RemoveAudioChannelLayout(AudioUnitScope scope
, AudioUnitElement element
);
687 /*! @method NeedsToRender */
688 bool NeedsToRender( Float64 inSampleTime
)
690 bool needsToRender
= fnotequal(inSampleTime
, mLastRenderedSampleTime
);
691 mLastRenderedSampleTime
= inSampleTime
;
692 return needsToRender
;
695 // Scheduled parameter implementation:
697 typedef std::vector
<AudioUnitParameterEvent
> ParameterEventList
;
699 // Usually, you won't override this method. You only need to call this if your DSP code
700 // is prepared to handle scheduled immediate and ramped parameter changes.
701 // Before calling this method, it is assumed you have already called PullInput() on the input busses
702 // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
703 // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
704 // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
705 // pieces according to the scheduled times found in the ParameterEventList (usually coming
706 // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
707 // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
708 // to do the actual DSP for each of these divisions.
709 virtual ComponentResult
ProcessForScheduledParams( ParameterEventList
&inParamList
,
710 UInt32 inFramesToProcess
,
713 // This method is called (potentially repeatedly) by ProcessForScheduledParams()
714 // in order to perform the actual DSP required for this portion of the entire buffer
715 // being processed. The entire buffer can be divided up into smaller "slices"
716 // according to the timestamps on the scheduled parameters...
718 // sub-classes wishing to handle scheduled parameter changes should override this method
719 // in order to do the appropriate DSP. AUEffectBase already overrides this for standard
720 // effect AudioUnits.
721 virtual ComponentResult
ProcessScheduledSlice( void *inUserData
,
722 UInt32 inStartFrameInBuffer
,
723 UInt32 inSliceFramesToProcess
,
724 UInt32 inTotalBufferFrames
) {return noErr
;}; // default impl does nothing...
726 // ________________________________________________________________________
727 // Private data members to discourage hacking in subclasses
729 struct RenderCallback
{
730 RenderCallback(ProcPtr proc
, void *ref
) :
732 mRenderNotifyRefCon(ref
)
735 ProcPtr mRenderNotify
;
736 void * mRenderNotifyRefCon
;
738 bool operator == (const RenderCallback
&other
) {
739 return this->mRenderNotify
== other
.mRenderNotify
&&
740 this->mRenderNotifyRefCon
== other
.mRenderNotifyRefCon
;
743 typedef TThreadSafeList
<RenderCallback
> RenderCallbackList
;
745 enum { kNumScopes
= 5 };
747 /*! @var mElementsCreated */
748 bool mElementsCreated
;
750 /*! @var mInitialized */
753 /*! @var mAudioUnitAPIVersion */
754 UInt8 mAudioUnitAPIVersion
;
756 /*! @var mInitNumInputEls */
757 UInt32 mInitNumInputEls
;
758 /*! @var mInitNumOutputEls */
759 UInt32 mInitNumOutputEls
;
760 /*! @var mInitNumGroupEls */
761 UInt32 mInitNumGroupEls
;
762 /*! @var mInitNumPartEls */
763 UInt32 mInitNumPartEls
;
765 AUScope mScopes
[kNumScopes
];
767 /*! @var mRenderCallbacks */
768 RenderCallbackList mRenderCallbacks
;
770 /*! @var mRenderThreadID */
772 pthread_t mRenderThreadID
;
773 #elif TARGET_OS_WIN32
774 UInt32 mRenderThreadID
;
777 /*! @var mWantsRenderThreadID */
778 bool mWantsRenderThreadID
;
780 /*! @var mLastRenderedSampleTime */
781 Float64 mLastRenderedSampleTime
;
783 /*! @var mMaxFramesPerSlice */
784 UInt32 mMaxFramesPerSlice
;
786 /*! @var mLastRenderError */
787 OSStatus mLastRenderError
;
788 /*! @var mCurrentPreset */
789 AUPreset mCurrentPreset
;
792 struct PropertyListener
{
793 AudioUnitPropertyID propertyID
;
794 AudioUnitPropertyListenerProc listenerProc
;
795 void * listenerRefCon
;
797 typedef std::vector
<PropertyListener
> PropertyListeners
;
799 /*! @var mParamList */
800 ParameterEventList mParamList
;
801 /*! @var mPropertyListeners */
802 PropertyListeners mPropertyListeners
;
803 /*! @var mHostCallbackInfo */
804 HostCallbackInfo mHostCallbackInfo
;
805 /*! @var mContextInfo */
806 CFStringRef mContextName
;
808 /*! @var mBuffersAllocated */
809 bool mBuffersAllocated
;
811 /*! @var mLogString */
812 // if this is NOT null, it will contain identifying info about this AU.
816 AUDebugDispatcher
* mDebugDispatcher
;
819 /*! @var sVectorUnitType */
820 static SInt32 sVectorUnitType
;
823 #endif // __AUBase_h__