Jamoma API  0.6.0.a19
AUBase.h
1 /* Copyright 2007 Apple Inc. All Rights Reserved.
2 
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.
9 
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.
25 
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.
31 
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.
40 */
41 #ifndef __AUBase_h__
42 #define __AUBase_h__
43 
44 #include <TargetConditionals.h>
45 
46 #if TARGET_OS_MAC
47  #include <pthread.h>
48 #elif TARGET_OS_WIN32
49  #include <windows.h>
50 #else
51  #error Unsupported Operating System
52 #endif
53 
54 #include <vector>
55 
56 #include "ComponentBase.h"
57 #include "AUScopeElement.h"
58 #include "AUInputElement.h"
59 #include "AUOutputElement.h"
60 #include "AUBuffer.h"
61 #include "CAMath.h"
62 #include "CAThreadSafeList.h"
63 #include "CAVectorUnit.h"
64 
65 #if 0 && DEBUG
66  #include "CATrace.h"
67 #else
68  #define CATRACE(code, a, b, c, d)
69 #endif
70 
71 typedef AUElement AUGlobalElement;
72 #if !TARGET_OS_IPHONE
73  typedef AUElement AUGroupElement;
74  typedef AUElement AUPartElement;
75 #endif
76 
77 
78 
79 // ________________________________________________________________________
80 // These are to be moved to the public AudioUnit headers
81 
82 #define kAUDefaultSampleRate 44100.0
83 #if !TARGET_OS_WIN32
84 #define kAUDefaultMaxFramesPerSlice 1156
85 //this allows enough default frames for a 512 dest 44K and SRC from 96K
86 // add a padding of 4 frames for any altivec rounding
87 #else
88 #define kAUDefaultMaxFramesPerSlice 2048
89 #endif
90 
91 class AUDebugDispatcher;
92 
93 // ________________________________________________________________________
94 
95 /*! @class AUBase */
96 class AUBase : public ComponentBase, public AUElementCreator {
97 public:
98 
99  /*! @ctor AUBase */
100  AUBase( AudioComponentInstance inInstance,
101  UInt32 numInputElements,
102  UInt32 numOutputElements,
103  UInt32 numGroupElements = 0,
104  UInt32 numPartElements = 0);
105  /*! @dtor AUBase */
106  virtual ~AUBase();
107 
108  /*! @method PostConstructor */
109  virtual void PostConstructor() { CreateElements(); }
110 
111  /*! @method PreDestructor */
112  virtual void PreDestructor();
113 
114  /*! @method CreateElements */
115  void CreateElements();
116  // Called immediately after construction, when virtual methods work.
117  // Or, a subclass may call this in order to have access to elements
118  // in its constructor.
119 
120  // ________________________________________________________________________
121  // Virtual methods (mostly) directly corresponding to the entry points. Many of these
122  // have useful implementations here and will not need overriding.
123 
124  /*! @method DoInitialize */
125  OSStatus DoInitialize();
126  // this implements the entry point and makes sure that initialization
127  // is only attempted exactly once...
128 
129  /*! @method Initialize */
130  virtual OSStatus Initialize();
131  // ... so that overrides to this method can assume that they will only
132  // be called exactly once.
133 
134  /*! @method IsInitialized */
135  bool IsInitialized() const { return mInitialized; }
136  /*! @method HasBegunInitializing */
137  bool HasBegunInitializing() const { return mHasBegunInitializing; }
138 
139  /*! @method DoCleanup */
140  void DoCleanup();
141  // same pattern as with Initialize
142 
143  /*! @method Cleanup */
144  virtual void Cleanup();
145 
146  /*! @method Reset */
147  virtual OSStatus Reset( AudioUnitScope inScope,
148  AudioUnitElement inElement);
149 
150  // Note about GetPropertyInfo, GetProperty, SetProperty:
151  // Certain properties are trapped out in these dispatch functions and handled with different virtual
152  // methods. (To discourage hacks and keep vtable size down, these are non-virtual)
153 
154  /*! @method DispatchGetPropertyInfo */
155  OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID,
156  AudioUnitScope inScope,
157  AudioUnitElement inElement,
158  UInt32 & outDataSize,
159  Boolean & outWritable);
160 
161  /*! @method DispatchGetProperty */
162  OSStatus DispatchGetProperty( AudioUnitPropertyID inID,
163  AudioUnitScope inScope,
164  AudioUnitElement inElement,
165  void * outData);
166 
167  /*! @method DispatchSetProperty */
168  OSStatus DispatchSetProperty( AudioUnitPropertyID inID,
169  AudioUnitScope inScope,
170  AudioUnitElement inElement,
171  const void * inData,
172  UInt32 inDataSize);
173 
174  OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID,
175  AudioUnitScope inScope,
176  AudioUnitElement inElement);
177 
178  /*! @method GetPropertyInfo */
179  virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
180  AudioUnitScope inScope,
181  AudioUnitElement inElement,
182  UInt32 & outDataSize,
183  Boolean & outWritable);
184 
185  /*! @method GetProperty */
186  virtual OSStatus GetProperty( AudioUnitPropertyID inID,
187  AudioUnitScope inScope,
188  AudioUnitElement inElement,
189  void * outData);
190 
191  /*! @method SetProperty */
192  virtual OSStatus SetProperty( AudioUnitPropertyID inID,
193  AudioUnitScope inScope,
194  AudioUnitElement inElement,
195  const void * inData,
196  UInt32 inDataSize);
197 
198  /*! @method ClearPropertyUsage */
199  virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID,
200  AudioUnitScope inScope,
201  AudioUnitElement inElement);
202 
203  /*! @method AddPropertyListener */
204  virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID,
205  AudioUnitPropertyListenerProc inProc,
206  void * inProcRefCon);
207 
208  /*! @method RemovePropertyListener */
209  virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID,
210  AudioUnitPropertyListenerProc inProc,
211  void * inProcRefCon,
212  bool refConSpecified);
213 
214  /*! @method SetRenderNotification */
215  virtual OSStatus SetRenderNotification( AURenderCallback inProc,
216  void * inRefCon);
217 
218  /*! @method RemoveRenderNotification */
219  virtual OSStatus RemoveRenderNotification(
220  AURenderCallback inProc,
221  void * inRefCon);
222 
223  /*! @method GetParameter */
224  virtual OSStatus GetParameter( AudioUnitParameterID inID,
225  AudioUnitScope inScope,
226  AudioUnitElement inElement,
227  AudioUnitParameterValue & outValue);
228 
229  /*! @method SetParameter */
230  virtual OSStatus SetParameter( AudioUnitParameterID inID,
231  AudioUnitScope inScope,
232  AudioUnitElement inElement,
233  AudioUnitParameterValue inValue,
234  UInt32 inBufferOffsetInFrames);
235 
236 #if !TARGET_OS_IPHONE
237  /*! @method SetGroupParameter */
238  virtual OSStatus SetGroupParameter( AudioUnitParameterID inID,
239  AudioUnitElement inElement,
240  AudioUnitParameterValue inValue,
241  UInt32 inBufferOffsetInFrames);
242 
243  /*! @method GetGroupParameter */
244  virtual OSStatus GetGroupParameter( AudioUnitParameterID inID,
245  AudioUnitElement inElement,
246  AudioUnitParameterValue & outValue);
247 #endif
248 
249  /*! @method ScheduleParameter */
250  virtual OSStatus ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
251  UInt32 inNumEvents);
252 
253 
254  /*! @method DoRender */
255  OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags,
256  const AudioTimeStamp & inTimeStamp,
257  UInt32 inBusNumber,
258  UInt32 inNumberFrames,
259  AudioBufferList & ioData);
260 
261 
262  // Override this method if your AU processes multiple output busses completely independently --
263  // you'll want to just call Render without the NeedsToRender check.
264  // Otherwise, override Render().
265  //
266  // N.B. Implementations of this method can assume that the output's buffer list has already been
267  // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
268  // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
269  // copy may occur after rendering.
270  /*! @method RenderBus */
271  virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags,
272  const AudioTimeStamp & inTimeStamp,
273  UInt32 inBusNumber,
274  UInt32 inNumberFrames)
275  {
276  if (NeedsToRender(inTimeStamp.mSampleTime))
277  return Render(ioActionFlags, inTimeStamp, inNumberFrames);
278  return noErr; // was presumably already rendered via another bus
279  }
280 
281  // N.B. For a unit with only one output bus, it can assume in its implementation of this
282  // method that the output's buffer list has already been prepared and access it with
283  // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
284  // -- if PrepareBuffer is called, a copy may occur after rendering.
285  /*! @method Render */
286  virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
287  const AudioTimeStamp & inTimeStamp,
288  UInt32 inNumberFrames)
289  {
290  return noErr;
291  }
292 
293 
294  static const Float64 kNoLastRenderedSampleTime;
295 
296  // ________________________________________________________________________
297  // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
298 
299  /*! @method BusCountWritable */
300  virtual bool BusCountWritable( AudioUnitScope inScope)
301  {
302  return false;
303  }
304  virtual OSStatus SetBusCount( AudioUnitScope inScope,
305  UInt32 inCount);
306 
307  /*! @method SetConnection */
308  virtual OSStatus SetConnection( const AudioUnitConnection & inConnection);
309 
310  /*! @method SetInputCallback */
311  virtual OSStatus SetInputCallback( UInt32 inPropertyID,
312  AudioUnitElement inElement,
313  AURenderCallback inProc,
314  void * inRefCon);
315 
316  /*! @method GetParameterList */
317  virtual OSStatus GetParameterList( AudioUnitScope inScope,
318  AudioUnitParameterID * outParameterList,
319  UInt32 & outNumParameters);
320  // outParameterList may be a null pointer
321 
322  /*! @method GetParameterInfo */
323  virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
324  AudioUnitParameterID inParameterID,
325  AudioUnitParameterInfo & outParameterInfo);
326 
327  /*! @method SaveState */
328  virtual OSStatus SaveState( CFPropertyListRef * outData);
329 
330  /*! @method RestoreState */
331  virtual OSStatus RestoreState( CFPropertyListRef inData);
332 
333  /*! @method GetParameterValueStrings */
334  virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope,
335  AudioUnitParameterID inParameterID,
336  CFArrayRef * outStrings);
337 
338  /*! @method CopyClumpName */
339  virtual OSStatus CopyClumpName( AudioUnitScope inScope,
340  UInt32 inClumpID,
341  UInt32 inDesiredNameLength,
342  CFStringRef * outClumpName);
343 
344  /*! @method GetPresets */
345  virtual OSStatus GetPresets ( CFArrayRef * outData) const;
346 
347  // set the default preset for the unit -> the number of the preset MUST be >= 0
348  // and the name should be valid, or the preset WON'T take
349  /*! @method SetAFactoryPresetAsCurrent */
350  bool SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
351 
352  // Called when someone sets a new, valid preset
353  // If this is a valid preset, then the subclass sets its state to that preset
354  // and returns noErr.
355  // If not a valid preset, return an error, and the pre-existing preset is restored
356  /*! @method NewFactoryPresetSet */
357  virtual OSStatus NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);
358 
359  /*! @method GetNumCustomUIComponents */
360  virtual int GetNumCustomUIComponents ();
361 #if !TARGET_OS_IPHONE
362  /*! @method GetUIComponentDescs */
363  virtual void GetUIComponentDescs (ComponentDescription* inDescArray);
364 #endif
365 
366  /*! @method CopyIconLocation */
367  virtual CFURLRef CopyIconLocation ();
368 
369  // default is no latency, and unimplemented tail time
370  /*! @method GetLatency */
371  virtual Float64 GetLatency() {return 0.0;}
372  /*! @method GetTailTime */
373  virtual Float64 GetTailTime() {return 0;}
374  /*! @method SupportsRampAndTail */
375  virtual bool SupportsTail () { return false; }
376 
377  /*! @method IsStreamFormatWritable */
378  bool IsStreamFormatWritable( AudioUnitScope scope,
379  AudioUnitElement element);
380 
381  /*! @method StreamFormatWritable */
382  virtual bool StreamFormatWritable( AudioUnitScope scope,
383  AudioUnitElement element) = 0;
384  // scope will always be input or output
385 
386  // pass in a pointer to get the struct, and num channel infos
387  // you can pass in NULL to just get the number
388  // a return value of 0 (the default in AUBase) means the property is not supported...
389  /*! @method SupportedNumChannels */
390  virtual UInt32 SupportedNumChannels ( const AUChannelInfo** outInfo);
391 
392  /*! @method ValidFormat */
393  virtual bool ValidFormat( AudioUnitScope inScope,
394  AudioUnitElement inElement,
395  const CAStreamBasicDescription & inNewFormat);
396  // Will only be called after StreamFormatWritable
397  // has succeeded.
398  // Default implementation requires canonical format:
399  // native-endian 32-bit float, any sample rate,
400  // any number of channels; override when other
401  // formats are supported. A subclass's override can
402  // choose to always return true and trap invalid
403  // formats in ChangeStreamFormat.
404 
405 
406  /*! @method FormatIsCanonical */
407  bool FormatIsCanonical( const CAStreamBasicDescription &format);
408 
409  /*! @method MakeCanonicalFormat */
410  void MakeCanonicalFormat( CAStreamBasicDescription & outDesc,
411  int numChannels = 2);
412 
413  /*! @method GetStreamFormat */
414  virtual const CAStreamBasicDescription &
415  GetStreamFormat( AudioUnitScope inScope,
416  AudioUnitElement inElement);
417 
418  /*! @method ChangeStreamFormat */
419  virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope,
420  AudioUnitElement inElement,
421  const CAStreamBasicDescription & inPrevFormat,
422  const CAStreamBasicDescription & inNewFormat);
423  // Will only be called after StreamFormatWritable
424  // and ValidFormat have succeeded.
425 
426  // ________________________________________________________________________
427 
428 #if !TARGET_OS_IPHONE
429  /*! @method ComponentEntryDispatch */
430  static OSStatus ComponentEntryDispatch( ComponentParameters * params,
431  AUBase * This);
432 #endif
433 
434  // ________________________________________________________________________
435  // Methods useful for subclasses
436 
437  /*! @method GetScope */
438  AUScope & GetScope( AudioUnitScope inScope)
439  {
440  if (inScope >= kNumScopes) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
441  return mScopes[inScope];
442  }
443 
444  /*! @method GlobalScope */
445  AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
446  /*! @method Inputs */
447  AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; }
448  /*! @method Outputs */
449  AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; }
450  /*! @method Groups */
451 #if !TARGET_OS_IPHONE
452  AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; }
453  /*! @method Parts */
454  AUScope & Parts() { return mScopes[kAudioUnitScope_Part]; }
455 #endif
456  /*! @method Globals */
457  AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }
458 
459  /*! @method SetNumberOfElements */
460  void SetNumberOfElements( AudioUnitScope inScope,
461  UInt32 numElements);
462 
463  /*! @method GetElement */
464  AUElement * GetElement( AudioUnitScope inScope,
465  AudioUnitElement inElement)
466  {
467  return GetScope(inScope).GetElement(inElement);
468  }
469 
470  /*! @method GetIOElement */
471  AUIOElement * GetIOElement( AudioUnitScope inScope,
472  AudioUnitElement inElement)
473  {
474  return GetScope(inScope).GetIOElement(inElement);
475  }
476 
477  /*! @method SafeGetElement */
478  AUElement * SafeGetElement( AudioUnitScope inScope,
479  AudioUnitElement inElement)
480  {
481  return GetScope(inScope).SafeGetElement(inElement);
482  }
483 
484  /*! @method GetInput */
485  AUInputElement * GetInput( AudioUnitElement inElement)
486  {
487  return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
488  }
489 
490  /*! @method GetOutput */
491  AUOutputElement * GetOutput( AudioUnitElement inElement)
492  {
493  return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
494  }
495 
496 #if !TARGET_OS_IPHONE
497  /*! @method GetGroup */
498  AUGroupElement * GetGroup( AudioUnitElement inElement)
499  {
500  return static_cast<AUGroupElement *>(Groups().SafeGetElement(inElement));
501  }
502 #endif
503 
504  /*! @method PullInput */
505  OSStatus PullInput( UInt32 inBusNumber,
506  AudioUnitRenderActionFlags &ioActionFlags,
507  const AudioTimeStamp & inTimeStamp,
508  UInt32 inNumberFrames)
509  {
510  AUInputElement *input = GetInput(inBusNumber); // throws if error
511  return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
512  }
513 
514  /*! @method GetMaxFramesPerSlice */
515  UInt32 GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
516 
517  /*! @method GetVectorUnitType */
518  static SInt32 GetVectorUnitType() { return sVectorUnitType; }
519  /*! @method HasVectorUnit */
520  static bool HasVectorUnit() { return sVectorUnitType > 0; }
521  /*! @method HasAltivec */
522  static bool HasAltivec() { return sVectorUnitType == kVecAltivec; }
523  /*! @method HasSSE2 */
524  static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; }
525  /*! @method HasSSE3 */
526  static bool HasSSE3() { return sVectorUnitType == kVecSSE3; }
527 
528  /*! @method AudioUnitAPIVersion */
529  UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
530 
531  /*! @method IsRenderThread */
532  bool InRenderThread () const
533  {
534 #if TARGET_OS_MAC
535  return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
536 #elif TARGET_OS_WIN32
537  return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
538 #endif
539  }
540 
541  /*! @method HasInput */
542  bool HasInput( AudioUnitElement inElement) {
543  AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
544  return in != NULL && in->IsActive();
545  }
546  // says whether an input is connected or has a callback
547 
548  /*! @method PropertyChanged */
549  void PropertyChanged( AudioUnitPropertyID inID,
550  AudioUnitScope inScope,
551  AudioUnitElement inElement);
552 
553 #if !TARGET_OS_IPHONE
554  // These calls can be used to call a Host's Callbacks. The method returns -1 if the host
555  // hasn't supplied the callback. Any other result is returned by the host.
556  // As in the API contract, for a parameter's value, you specify a pointer
557  // to that data type. Specify NULL for a parameter that you are not interested
558  // as this can save work in the host.
559 
560  /*! @method CallHostBeatAndTempo */
561  OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat,
562  Float64 *outCurrentTempo)
563  {
564  return (mHostCallbackInfo.beatAndTempoProc
565  ? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
566  outCurrentBeat,
567  outCurrentTempo)
568  : -1);
569  }
570 
571  /*! @method CallHostMusicalTimeLocation */
572  OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat,
573  Float32 *outTimeSig_Numerator,
574  UInt32 *outTimeSig_Denominator,
575  Float64 *outCurrentMeasureDownBeat)
576  {
577  return (mHostCallbackInfo.musicalTimeLocationProc
578  ? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
579  outDeltaSampleOffsetToNextBeat,
580  outTimeSig_Numerator,
581  outTimeSig_Denominator,
582  outCurrentMeasureDownBeat)
583  : -1);
584  }
585 
586  /*! @method CallHostTransportState */
587  OSStatus CallHostTransportState (Boolean *outIsPlaying,
588  Boolean *outTransportStateChanged,
589  Float64 *outCurrentSampleInTimeLine,
590  Boolean *outIsCycling,
591  Float64 *outCycleStartBeat,
592  Float64 *outCycleEndBeat)
593  {
594  return (mHostCallbackInfo.transportStateProc
595  ? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
596  outIsPlaying,
597  outTransportStateChanged,
598  outCurrentSampleInTimeLine,
599  outIsCycling,
600  outCycleStartBeat,
601  outCycleEndBeat)
602  : -1);
603  }
604 #endif
605 
606  char* GetLoggingString () const;
607 
608 protected:
609  // ________________________________________________________________________
610  // AUElementCreator override, may be further overridden by subclasses
611  /*! @method CreateElement */
612  virtual AUElement * CreateElement( AudioUnitScope scope,
613  AudioUnitElement element);
614 
615  /*! @method ReallocateBuffers */
616  virtual void ReallocateBuffers();
617  // needs to be called when mMaxFramesPerSlice changes
618 
619  /*! @method FillInParameterName */
620  static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
621  {
622  ioInfo.cfNameString = inName;
623  ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
624  if (inShouldRelease)
625  ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
626  CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
627  }
628 
629  static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
630  {
631  ioInfo.clumpID = inClumpID;
632  ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
633  }
634 
635  /*! @method SetMaxFramesPerSlice */
636  virtual void SetMaxFramesPerSlice(UInt32 nFrames);
637 
638  /*! @method CanSetMaxFrames */
639  virtual OSStatus CanSetMaxFrames() const;
640 
641  /*! @method WantsRenderThreadID */
642  bool WantsRenderThreadID () const { return mWantsRenderThreadID; }
643 
644  /*! @method SetWantsRenderThreadID */
645  void SetWantsRenderThreadID (bool inFlag);
646 
647  /*! @method SetRenderError */
648  OSStatus SetRenderError (OSStatus inErr)
649  {
650  if (inErr && mLastRenderError == 0) {
651  mLastRenderError = inErr;
652  PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
653  }
654  return inErr;
655  }
656 
657 private:
658  /*! @method DoRenderBus */
659  // shared between Render and RenderSlice, inlined to minimize function call overhead
660  OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
661  const AudioTimeStamp & inTimeStamp,
662  UInt32 inBusNumber,
663  AUOutputElement * theOutput,
664  UInt32 inNumberFrames,
665  AudioBufferList & ioData)
666  {
667  if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
668  // will render into cache buffer
669  theOutput->PrepareBuffer(inNumberFrames);
670  else
671  // will render into caller's buffer
672  theOutput->SetBufferList(ioData);
673  OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
674  if (result == noErr) {
675  if (ioData.mBuffers[0].mData == NULL) {
676  theOutput->CopyBufferListTo(ioData);
677  CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
678  } else {
679  theOutput->CopyBufferContentsTo(ioData);
680  CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, (int)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
681  theOutput->InvalidateBufferList();
682  }
683  }
684  return result;
685  }
686 
687  /*! @method HasIcon */
688  bool HasIcon ();
689 
690 protected:
691  /*! @method GetAudioChannelLayout */
692  virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope,
693  AudioUnitElement element,
694  AudioChannelLayoutTag * outLayoutTags);
695 
696  /*! @method GetAudioChannelLayout */
697  virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope,
698  AudioUnitElement element,
699  AudioChannelLayout * outLayoutPtr,
700  Boolean & outWritable);
701 
702  /*! @method SetAudioChannelLayout */
703  virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope,
704  AudioUnitElement element,
705  const AudioChannelLayout * inLayout);
706 
707  /*! @method RemoveAudioChannelLayout */
708  virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
709 
710  /*! @method NeedsToRender */
711  bool NeedsToRender( Float64 inSampleTime)
712  {
713  bool needsToRender = fnotequal(inSampleTime, mLastRenderedSampleTime);
714  mLastRenderedSampleTime = inSampleTime;
715  return needsToRender;
716  }
717 
718  // Scheduled parameter implementation:
719 
720  typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
721 
722  // Usually, you won't override this method. You only need to call this if your DSP code
723  // is prepared to handle scheduled immediate and ramped parameter changes.
724  // Before calling this method, it is assumed you have already called PullInput() on the input busses
725  // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
726  // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
727  // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
728  // pieces according to the scheduled times found in the ParameterEventList (usually coming
729  // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
730  // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
731  // to do the actual DSP for each of these divisions.
732  virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
733  UInt32 inFramesToProcess,
734  void *inUserData );
735 
736  // This method is called (potentially repeatedly) by ProcessForScheduledParams()
737  // in order to perform the actual DSP required for this portion of the entire buffer
738  // being processed. The entire buffer can be divided up into smaller "slices"
739  // according to the timestamps on the scheduled parameters...
740  //
741  // sub-classes wishing to handle scheduled parameter changes should override this method
742  // in order to do the appropriate DSP. AUEffectBase already overrides this for standard
743  // effect AudioUnits.
744  virtual OSStatus ProcessScheduledSlice( void *inUserData,
745  UInt32 inStartFrameInBuffer,
746  UInt32 inSliceFramesToProcess,
747  UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing...
748 
749  // ________________________________________________________________________
750  // Private data members to discourage hacking in subclasses
751 private:
752  struct RenderCallback {
753  RenderCallback(AURenderCallback proc, void *ref) :
754  mRenderNotify(proc),
755  mRenderNotifyRefCon(ref)
756  { }
757 
758  AURenderCallback mRenderNotify;
759  void * mRenderNotifyRefCon;
760 
761  bool operator == (const RenderCallback &other) {
762  return this->mRenderNotify == other.mRenderNotify &&
763  this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
764  }
765  };
766  typedef TThreadSafeList<RenderCallback> RenderCallbackList;
767 
768 #if TARGET_OS_IPHONE
769  enum { kNumScopes = 3 };
770 #else
771  enum { kNumScopes = 5 };
772 #endif
773 
774  /*! @var mElementsCreated */
775  bool mElementsCreated;
776 protected:
777  /*! @var mInitialized */
778  bool mInitialized;
779  /*! @var mHasBegunInitializing */
780  bool mHasBegunInitializing;
781 private:
782  /*! @var mAudioUnitAPIVersion */
783  UInt8 mAudioUnitAPIVersion;
784 
785  /*! @var mInitNumInputEls */
786  UInt32 mInitNumInputEls;
787  /*! @var mInitNumOutputEls */
788  UInt32 mInitNumOutputEls;
789 #if !TARGET_OS_IPHONE
790  /*! @var mInitNumGroupEls */
791  UInt32 mInitNumGroupEls;
792  /*! @var mInitNumPartEls */
793  UInt32 mInitNumPartEls;
794 #endif
795  /*! @var mScopes */
796  AUScope mScopes[kNumScopes];
797 
798  /*! @var mRenderCallbacks */
799  RenderCallbackList mRenderCallbacks;
800  bool mRenderCallbacksTouched;
801 
802  /*! @var mRenderThreadID */
803 #if TARGET_OS_MAC
804  pthread_t mRenderThreadID;
805 #elif TARGET_OS_WIN32
806  UInt32 mRenderThreadID;
807 #endif
808 
809  /*! @var mWantsRenderThreadID */
810  bool mWantsRenderThreadID;
811 
812  /*! @var mLastRenderedSampleTime */
813  Float64 mLastRenderedSampleTime;
814 
815  /*! @var mMaxFramesPerSlice */
816  UInt32 mMaxFramesPerSlice;
817 
818  /*! @var mLastRenderError */
819  OSStatus mLastRenderError;
820  /*! @var mCurrentPreset */
821  AUPreset mCurrentPreset;
822 
823 protected:
824  struct PropertyListener {
825  AudioUnitPropertyID propertyID;
826  AudioUnitPropertyListenerProc listenerProc;
827  void * listenerRefCon;
828  };
829  typedef std::vector<PropertyListener> PropertyListeners;
830 
831  /*! @var mParamList */
832  ParameterEventList mParamList;
833  /*! @var mPropertyListeners */
834  PropertyListeners mPropertyListeners;
835 
836  /*! @var mBuffersAllocated */
837  bool mBuffersAllocated;
838 
839  /*! @var mLogString */
840  // if this is NOT null, it will contain identifying info about this AU.
841  char* mLogString;
842 
843 private:
844  /*! @var sVectorUnitType */
845  static SInt32 sVectorUnitType;
846 
847 #if !TARGET_OS_IPHONE
848 protected:
849  /*! @var mHostCallbackInfo */
850  HostCallbackInfo mHostCallbackInfo;
851 
852  /*! @var mContextInfo */
853  CFStringRef mContextName;
854 
855 public:
856  AUDebugDispatcher* mDebugDispatcher;
857 #endif
858 };
859 
860 inline OSStatus AUInputElement::PullInputWithBufferList(
861  AudioUnitRenderActionFlags & ioActionFlags,
862  const AudioTimeStamp & inTimeStamp,
863  AudioUnitElement inElement,
864  UInt32 nFrames,
865  AudioBufferList * inBufferList)
866 {
867  OSStatus theResult;
868 
869  if (HasConnection()) {
870  // only support connections for V2 audio units
871 #if !TARGET_OS_IPHONE
872  if (mConnRenderProc != NULL)
873  theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
874  mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
875  else
876 #endif
877  theResult = AudioUnitRender(
878  mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
879  } else {
880  // kFromCallback:
881  theResult = (mInputProc)(
882  mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
883  }
884 
885  if (mInputType == kNoInput) // defense: the guy upstream could have disconnected
886  // it's a horrible thing to do, but may happen!
887  return kAudioUnitErr_NoConnection;
888 
889 
890  return theResult;
891 }
892 
893 #endif // __AUBase_h__
bool TTFOUNDATION_EXPORT operator==(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for equality.
Definition: TTObject.cpp:167