Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / platform / mac / SuperColliderAU / AUSDK / AUBase.h
blob8d1e0f624432eb8e89fa2e9722d7273f9fe71c91
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 /*=============================================================================
42 AUBase.h
44 =============================================================================*/
46 #ifndef __AUBase_h__
47 #define __AUBase_h__
49 #include <TargetConditionals.h>
51 #if TARGET_OS_MAC
52 #include <pthread.h>
53 #elif TARGET_OS_WIN32
54 #include <windows.h>
55 #else
56 #error Unsupported Operating System
57 #endif
59 #include <vector>
61 #include "ComponentBase.h"
62 #include "AUScopeElement.h"
63 #include "AUInputElement.h"
64 #include "AUOutputElement.h"
65 #include "AUBuffer.h"
66 #include "CAMath.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
78 #if !TARGET_OS_WIN32
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
82 #else
83 #define kAUDefaultMaxFramesPerSlice 2048
84 #endif
86 class AUDebugDispatcher;
88 // ________________________________________________________________________
90 /*! @class AUBase */
91 class AUBase : public ComponentBase, public AUElementCreator {
92 public:
94 /*! @ctor AUBase */
95 AUBase( AudioUnit inInstance,
96 UInt32 numInputElements,
97 UInt32 numOutputElements,
98 UInt32 numGroupElements = 0,
99 UInt32 numPartElements = 0);
100 /*! @dtor AUBase */
101 virtual ~AUBase();
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 */
133 void DoCleanup();
134 // same pattern as with Initialize
136 /*! @method Cleanup */
137 virtual void Cleanup();
139 /*! @method Reset */
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,
158 void * outData);
160 /*! @method DispatchSetProperty */
161 ComponentResult DispatchSetProperty( AudioUnitPropertyID inID,
162 AudioUnitScope inScope,
163 AudioUnitElement inElement,
164 const void * inData,
165 UInt32 inDataSize);
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,
182 void * outData);
184 /*! @method SetProperty */
185 virtual ComponentResult SetProperty( AudioUnitPropertyID inID,
186 AudioUnitScope inScope,
187 AudioUnitElement inElement,
188 const void * inData,
189 UInt32 inDataSize);
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,
204 void * inProcRefCon,
205 bool refConSpecified);
207 /*! @method SetRenderNotification */
208 virtual ComponentResult SetRenderNotification( ProcPtr inProc,
209 void * inRefCon);
211 /*! @method RemoveRenderNotification */
212 virtual ComponentResult RemoveRenderNotification(
213 ProcPtr inProc,
214 void * inRefCon);
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,
242 UInt32 inNumEvents);
245 /*! @method DoRender */
246 ComponentResult DoRender( AudioUnitRenderActionFlags & ioActionFlags,
247 const AudioTimeStamp & inTimeStamp,
248 UInt32 inBusNumber,
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,
264 UInt32 inBusNumber,
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)
281 return noErr;
285 static const Float64 kNoLastRenderedSampleTime;
287 // ________________________________________________________________________
288 // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
290 /*! @method BusCountWritable */
291 virtual bool BusCountWritable( AudioUnitScope inScope)
293 return false;
295 virtual ComponentResult SetBusCount( AudioUnitScope inScope,
296 UInt32 inCount);
298 /*! @method SetConnection */
299 virtual ComponentResult SetConnection( const AudioUnitConnection & inConnection);
301 /*! @method SetInputCallback */
302 virtual ComponentResult SetInputCallback( UInt32 inPropertyID,
303 AudioUnitElement inElement,
304 ProcPtr inProc,
305 void * inRefCon);
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
380 // has succeeded.
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,
413 AUBase * This);
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,
440 UInt32 numElements);
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
511 #if TARGET_OS_MAC
512 return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
513 #elif TARGET_OS_WIN32
514 return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
515 #endif
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,
538 outCurrentBeat,
539 outCurrentTempo)
540 : -1);
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)
555 : -1);
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,
568 outIsPlaying,
569 outTransportStateChanged,
570 outCurrentSampleInTimeLine,
571 outIsCycling,
572 outCycleStartBeat,
573 outCycleEndBeat)
574 : -1);
577 /*! @method PropertyChanged */
578 void PropertyChanged( AudioUnitPropertyID inID,
579 AudioUnitScope inScope,
580 AudioUnitElement inElement);
583 char* GetLoggingString () const;
585 protected:
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;
601 if (inShouldRelease)
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);
631 return inErr;
634 private:
635 /*! @method DoRenderBus */
636 // shared between Render and RenderSlice, inlined to minimize function call overhead
637 ComponentResult DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
638 const AudioTimeStamp & inTimeStamp,
639 UInt32 inBusNumber,
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);
647 else
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);
656 else {
657 theOutput->CopyBufferContentsTo(ioData);
658 theOutput->InvalidateBufferList();
661 return result;
664 /*! @method HasIcon */
665 bool HasIcon ();
667 protected:
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,
711 void *inUserData );
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
728 private:
729 struct RenderCallback {
730 RenderCallback(ProcPtr proc, void *ref) :
731 mRenderNotify(proc),
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;
749 protected:
750 /*! @var mInitialized */
751 bool mInitialized;
752 private:
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;
764 /*! @var mScopes */
765 AUScope mScopes[kNumScopes];
767 /*! @var mRenderCallbacks */
768 RenderCallbackList mRenderCallbacks;
770 /*! @var mRenderThreadID */
771 #if TARGET_OS_MAC
772 pthread_t mRenderThreadID;
773 #elif TARGET_OS_WIN32
774 UInt32 mRenderThreadID;
775 #endif
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;
791 protected:
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.
813 char* mLogString;
815 public:
816 AUDebugDispatcher* mDebugDispatcher;
818 private:
819 /*! @var sVectorUnitType */
820 static SInt32 sVectorUnitType;
823 #endif // __AUBase_h__