3 Abstract: Part of CoreAudio Utility Classes
6 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 Inc. ("Apple") in consideration of your agreement to the following
8 terms, and your use, installation, modification or redistribution of
9 this Apple software constitutes acceptance of these terms. If you do
10 not agree with these terms, please do not use, install, modify or
11 redistribute this Apple software.
13 In consideration of your agreement to abide by the following terms, and
14 subject to these terms, Apple grants you a personal, non-exclusive
15 license, under Apple's copyrights in this original Apple software (the
16 "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 Software, with or without modifications, in source and/or binary forms;
18 provided that if you redistribute the Apple Software in its entirety and
19 without modifications, you must retain this notice and the following
20 text and disclaimers in all such redistributions of the Apple Software.
21 Neither the name, trademarks, service marks or logos of Apple Inc. may
22 be used to endorse or promote products derived from the Apple Software
23 without specific prior written permission from Apple. Except as
24 expressly stated in this notice, no other rights or licenses, express or
25 implied, are granted by Apple herein, including but not limited to any
26 patent rights that may be infringed by your derivative works or by other
27 works in which the Apple Software may be incorporated.
29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 POSSIBILITY OF SUCH DAMAGE.
44 Copyright (C) 2014 Apple Inc. All Rights Reserved.
47 #ifndef __AUScopeElement_h__
48 #define __AUScopeElement_h__
53 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
54 #include <AudioUnit/AudioUnit.h>
56 #include <AudioUnit.h>
58 #include "ComponentBase.h"
64 // ____________________________________________________________________________
66 // represents a parameter's value (either constant or ramped)
67 /*! @class ParameterMapEvent */
68 class ParameterMapEvent
71 /*! @ctor ParameterMapEvent */
73 : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0f), mValue2(0.0f), mSliceDurationFrames(0)
76 /*! @ctor ParameterMapEvent */
77 ParameterMapEvent(AudioUnitParameterValue inValue)
78 : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0)
81 // constructor for scheduled event
82 /*! @ctor ParameterMapEvent */
83 ParameterMapEvent( const AudioUnitParameterEvent &inEvent,
84 UInt32 inSliceOffsetInBuffer,
85 UInt32 inSliceDurationFrames )
87 SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
90 /*! @method SetScheduledEvent */
91 void SetScheduledEvent( const AudioUnitParameterEvent &inEvent,
92 UInt32 inSliceOffsetInBuffer,
93 UInt32 inSliceDurationFrames )
95 mEventType = inEvent.eventType;
96 mSliceDurationFrames = inSliceDurationFrames;
98 if(mEventType == kParameterEvent_Immediate )
100 // constant immediate value for the whole slice
101 mValue1 = inEvent.eventValues.immediate.value;
103 mDurationInFrames = inSliceDurationFrames;
108 mDurationInFrames = inEvent.eventValues.ramp.durationInFrames;
109 mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice
110 mValue1 = inEvent.eventValues.ramp.startValue;
111 mValue2 = inEvent.eventValues.ramp.endValue;
117 /*! @method GetEventType */
118 AUParameterEventType GetEventType() const {return mEventType;};
120 /*! @method GetValue */
121 AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type
122 /*! @method GetEndValue */
123 AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type
124 /*! @method SetValue */
125 void SetValue(AudioUnitParameterValue inValue)
127 mEventType = kParameterEvent_Immediate;
132 // interpolates the start and end values corresponding to the current processing slice
133 // most ramp parameter implementations will want to use this method
134 // the start value will correspond to the start of the slice
135 // the end value will correspond to the end of the slice
136 /*! @method GetRampSliceStartEnd */
137 void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue,
138 AudioUnitParameterValue & outEndValue,
139 AudioUnitParameterValue & outValuePerFrameDelta )
141 if (mEventType == kParameterEvent_Ramped) {
142 outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
144 outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice
145 outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames;
147 outValuePerFrameDelta = 0;
148 outStartValue = outEndValue = mValue1;
152 // Some ramp parameter implementations will want to interpret the ramp using their
153 // own interpolation method (perhaps non-linear)
154 // This method gives the raw ramp information, relative to this processing slice
155 // for the client to interpret as desired
156 /*! @method GetRampInfo */
157 void GetRampInfo( SInt32 & outBufferOffset,
158 UInt32 & outDurationInFrames,
159 AudioUnitParameterValue & outStartValue,
160 AudioUnitParameterValue & outEndValue )
162 outBufferOffset = mBufferOffset;
163 outDurationInFrames = mDurationInFrames;
164 outStartValue = mValue1;
165 outEndValue = mValue2;
171 printf("ParameterEvent @ %p\n", this);
172 printf(" mEventType = %d\n", (int)mEventType);
173 printf(" mBufferOffset = %d\n", (int)mBufferOffset);
174 printf(" mDurationInFrames = %d\n", (int)mDurationInFrames);
175 printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
176 printf(" mValue1 = %.5f\n", mValue1);
177 printf(" mValue2 = %.5f\n", mValue2);
182 AUParameterEventType mEventType;
184 SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative)
185 UInt32 mDurationInFrames; // total duration of ramp parameter
186 AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp
187 AudioUnitParameterValue mValue2; // endValue (only used for ramp)
189 UInt32 mSliceDurationFrames; // duration of this processing slice
194 // ____________________________________________________________________________
198 /*! @class AUElement */
201 /*! @ctor AUElement */
202 AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
203 mUseIndexedParameters(false), mElementName(0) { }
205 /*! @dtor ~AUElement */
206 virtual ~AUElement() { if (mElementName) CFRelease (mElementName); }
208 /*! @method GetNumberOfParameters */
209 virtual UInt32 GetNumberOfParameters()
211 if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
213 /*! @method GetParameterList */
214 virtual void GetParameterList(AudioUnitParameterID *outList);
215 /*! @method HasParameterID */
216 bool HasParameterID (AudioUnitParameterID paramID) const;
218 /*! @method GetParameter */
219 AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID);
220 /*! @method SetParameter */
221 void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
222 // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
224 // interpolates the start and end values corresponding to the current processing slice
225 // most ramp parameter implementations will want to use this method
226 /*! @method GetRampSliceStartEnd */
227 void GetRampSliceStartEnd( AudioUnitParameterID paramID,
228 AudioUnitParameterValue & outStartValue,
229 AudioUnitParameterValue & outEndValue,
230 AudioUnitParameterValue & outValuePerFrameDelta );
232 /*! @method GetEndValue */
233 AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID);
235 /*! @method SetRampParameter */
236 void SetScheduledEvent( AudioUnitParameterID paramID,
237 const AudioUnitParameterEvent &inEvent,
238 UInt32 inSliceOffsetInBuffer,
239 UInt32 inSliceDurationFrames,
240 bool okWhenInitialized = false );
241 // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
244 /*! @method GetAudioUnit */
245 AUBase * GetAudioUnit() const { return mAudioUnit; };
247 /*! @method SaveState */
248 void SaveState(CFMutableDataRef data);
249 /*! @method RestoreState */
250 const UInt8 * RestoreState(const UInt8 *state);
251 /*! @method GetName */
252 CFStringRef GetName () const { return mElementName; }
253 /*! @method SetName */
254 void SetName (CFStringRef inName);
255 /*! @method HasName */
256 bool HasName () const { return mElementName != 0; }
257 /*! @method UseIndexedParameters */
258 virtual void UseIndexedParameters(int inNumberOfParameters);
260 /*! @method AsIOElement*/
261 virtual AUIOElement* AsIOElement () { return NULL; }
264 inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
267 typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
269 /*! @var mAudioUnit */
271 /*! @var mParameters */
272 ParameterMap mParameters;
274 /*! @var mUseIndexedParameters */
275 bool mUseIndexedParameters;
276 /*! @var mIndexedParameters */
277 std::vector<ParameterMapEvent> mIndexedParameters;
279 /*! @var mElementName */
280 CFStringRef mElementName;
285 // ____________________________________________________________________________
287 /*! @class AUIOElement */
288 class AUIOElement : public AUElement {
290 /*! @ctor AUIOElement */
291 AUIOElement(AUBase *audioUnit);
293 /*! @method GetStreamFormat */
294 const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
296 /*! @method SetStreamFormat */
297 virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
299 /*! @method AllocateBuffer */
300 virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
301 /*! @method DeallocateBuffer */
302 void DeallocateBuffer();
303 /*! @method NeedsBufferSpace */
304 virtual bool NeedsBufferSpace() const = 0;
306 /*! @method SetWillAllocateBuffer */
307 void SetWillAllocateBuffer(bool inFlag) {
308 mWillAllocate = inFlag;
310 /*! @method WillAllocateBuffer */
311 bool WillAllocateBuffer() const {
312 return mWillAllocate;
315 /*! @method UseExternalBuffer */
316 void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
317 mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
319 /*! @method PrepareBuffer */
320 AudioBufferList & PrepareBuffer(UInt32 nFrames) {
322 return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
323 throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
325 /*! @method PrepareNullBuffer */
326 AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
327 return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
329 /*! @method SetBufferList */
330 AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
331 /*! @method SetBuffer */
332 void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
333 /*! @method InvalidateBufferList */
334 void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
336 /*! @method GetBufferList */
337 AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }
339 /*! @method GetChannelData */
340 AudioUnitSampleType * GetChannelData(int ch) const {
341 if (mStreamFormat.IsInterleaved())
342 return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
344 return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
346 Float32 * GetFloat32ChannelData(int ch) const {
347 if (mStreamFormat.IsInterleaved())
348 return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
350 return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
352 SInt32 * GetSInt32ChannelData(int ch) const {
353 if (mStreamFormat.IsInterleaved())
354 return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
356 return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
358 SInt16 * GetInt16ChannelData(int ch) const {
359 if (mStreamFormat.IsInterleaved())
360 return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
362 return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
365 /*! @method CopyBufferListTo */
366 void CopyBufferListTo(AudioBufferList &abl) const {
367 mIOBuffer.CopyBufferListTo(abl);
369 /*! @method CopyBufferContentsTo */
370 void CopyBufferContentsTo(AudioBufferList &abl) const {
371 mIOBuffer.CopyBufferContentsTo(abl);
374 /* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
375 UInt32 BytesToFrames(AudioBufferList &abl) {
376 return BytesToFrames(abl.mBuffers[0].mDataByteSize);
378 UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
380 /*! @method IsInterleaved */
381 bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
382 /*! @method NumberChannels */
383 UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
384 /*! @method NumberInterleavedChannels */
385 UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
387 /*! @method GetChannelMapTags */
388 virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);
390 /*! @method GetAudioChannelLayout */
391 virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);
393 /*! @method SetAudioChannelLayout */
394 virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
396 /*! @method RemoveAudioChannelLayout */
397 virtual OSStatus RemoveAudioChannelLayout ();
399 /*! @method AsIOElement*/
400 virtual AUIOElement* AsIOElement () { return this; }
403 /*! @var mStreamFormat */
404 CAStreamBasicDescription mStreamFormat;
405 /*! @var mIOBuffer */
406 AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
407 // for output: output cache, usually allocated early on
408 /*! @var mWillAllocate */
412 // ____________________________________________________________________________
414 // AUScopeDelegates are a way to get virtual scopes.
415 /*! @class AUScopeDelegate */
416 class AUScopeDelegate {
418 /*! @ctor AUScopeDelegate */
419 AUScopeDelegate() : mCreator(NULL), mScope(0) { }
420 /*! @dtor ~AUScopeDelegate */
421 virtual ~AUScopeDelegate() {}
423 /*! @method Initialize */
424 void Initialize( AUBase *creator,
425 AudioUnitScope scope,
430 SetNumberOfElements(numElements);
433 /*! @method SetNumberOfElements */
434 virtual void SetNumberOfElements(UInt32 numElements) = 0;
436 /*! @method GetNumberOfElements */
437 virtual UInt32 GetNumberOfElements() = 0;
439 /*! @method GetElement */
440 virtual AUElement * GetElement(UInt32 elementIndex) = 0;
442 AUBase * GetCreator() const { return mCreator; }
443 AudioUnitScope GetScope() const { return mScope; }
450 AudioUnitScope mScope;
455 // ____________________________________________________________________________
457 /*! @class AUScope */
461 AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }
462 /*! @dtor ~AUScope */
465 /*! @method Initialize */
466 void Initialize(AUBase *creator,
467 AudioUnitScope scope,
474 return mDelegate->Initialize(creator, scope, numElements);
476 SetNumberOfElements(numElements);
479 /*! @method SetNumberOfElements */
480 void SetNumberOfElements(UInt32 numElements);
482 /*! @method GetNumberOfElements */
483 UInt32 GetNumberOfElements() const
486 return mDelegate->GetNumberOfElements();
488 return static_cast<UInt32>(mElements.size());
491 /*! @method GetElement */
492 AUElement * GetElement(UInt32 elementIndex) const
495 return mDelegate->GetElement(elementIndex);
497 ElementVector::const_iterator i = mElements.begin() + elementIndex;
498 // catch passing -1 in as the elementIndex - causes a wrap around
499 return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
502 /*! @method SafeGetElement */
503 AUElement * SafeGetElement(UInt32 elementIndex)
505 AUElement *element = GetElement(elementIndex);
507 COMPONENT_THROW(kAudioUnitErr_InvalidElement);
511 /*! @method GetIOElement */
512 AUIOElement * GetIOElement(UInt32 elementIndex) const
514 AUElement *element = GetElement(elementIndex);
515 AUIOElement *ioel = element ? element->AsIOElement () : NULL;
517 COMPONENT_THROW (kAudioUnitErr_InvalidElement);
521 /*! @method HasElementWithName */
522 bool HasElementWithName () const;
524 /*! @method AddElementNamesToDict */
525 void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
527 bool RestoreElementNames (CFDictionaryRef& inNameDict);
529 AudioUnitScope GetScope() const { return mScope; }
531 void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
533 /*! @method SaveState */
534 void SaveState(CFMutableDataRef data);
536 /*! @method RestoreState */
537 const UInt8 * RestoreState(const UInt8 *state);
540 typedef std::vector<AUElement *> ElementVector;
544 AudioUnitScope mScope;
545 /*! @var mElements */
546 ElementVector mElements;
547 /*! @var mDelegate */
548 AUScopeDelegate * mDelegate;
553 #endif // __AUScopeElement_h__