diff options
Diffstat (limited to 'distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h')
-rwxr-xr-x | distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h new file mode 100755 index 00000000..bb55f763 --- /dev/null +++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h @@ -0,0 +1,535 @@ +/* Copyright © 2007 Apple Inc. All Rights Reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef __AUScopeElement_h__ +#define __AUScopeElement_h__ + +#include <map> +#include <vector> + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioUnit/AudioUnit.h> +#else + #include <AudioUnit.h> +#endif +#include "ComponentBase.h" +#include "AUBuffer.h" + + +class AUBase; + +// ____________________________________________________________________________ +// +// represents a parameter's value (either constant or ramped) +/*! @class ParameterMapEvent */ +class ParameterMapEvent +{ +public: +/*! @ctor ParameterMapEvent */ + ParameterMapEvent() + : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0), mValue2(0.0), mSliceDurationFrames(0) + {} + +/*! @ctor ParameterMapEvent */ + ParameterMapEvent(AudioUnitParameterValue inValue) + : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0) + {} + + // constructor for scheduled event +/*! @ctor ParameterMapEvent */ + ParameterMapEvent( const AudioUnitParameterEvent &inEvent, + UInt32 inSliceOffsetInBuffer, + UInt32 inSliceDurationFrames ) + { + SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames ); + }; + +/*! @method SetScheduledEvent */ + void SetScheduledEvent( const AudioUnitParameterEvent &inEvent, + UInt32 inSliceOffsetInBuffer, + UInt32 inSliceDurationFrames ) + { + mEventType = inEvent.eventType; + mSliceDurationFrames = inSliceDurationFrames; + + if(mEventType == kParameterEvent_Immediate ) + { + // constant immediate value for the whole slice + mValue1 = inEvent.eventValues.immediate.value; + mValue2 = mValue1; + mDurationInFrames = inSliceDurationFrames; + mBufferOffset = 0; + } + else + { + mDurationInFrames = inEvent.eventValues.ramp.durationInFrames; + mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice + mValue1 = inEvent.eventValues.ramp.startValue; + mValue2 = inEvent.eventValues.ramp.endValue; + } + }; + + + +/*! @method GetEventType */ + AUParameterEventType GetEventType() const {return mEventType;}; + +/*! @method GetValue */ + AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type +/*! @method GetEndValue */ + AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type +/*! @method SetValue */ + void SetValue(AudioUnitParameterValue inValue) + { + mEventType = kParameterEvent_Immediate; + mValue1 = inValue; + mValue2 = inValue; + } + + // interpolates the start and end values corresponding to the current processing slice + // most ramp parameter implementations will want to use this method + // the start value will correspond to the start of the slice + // the end value will correspond to the end of the slice +/*! @method GetRampSliceStartEnd */ + void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue, + AudioUnitParameterValue & outEndValue, + AudioUnitParameterValue & outValuePerFrameDelta ) + { + if (mEventType == kParameterEvent_Ramped) { + outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames; + + outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice + outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames; + } else { + outValuePerFrameDelta = 0; + outStartValue = outEndValue = mValue1; + } + }; + + // Some ramp parameter implementations will want to interpret the ramp using their + // own interpolation method (perhaps non-linear) + // This method gives the raw ramp information, relative to this processing slice + // for the client to interpret as desired +/*! @method GetRampInfo */ + void GetRampInfo( SInt32 & outBufferOffset, + UInt32 & outDurationInFrames, + AudioUnitParameterValue & outStartValue, + AudioUnitParameterValue & outEndValue ) + { + outBufferOffset = mBufferOffset; + outDurationInFrames = mDurationInFrames; + outStartValue = mValue1; + outEndValue = mValue2; + }; + +#if DEBUG + void Print() + { + printf("ParameterEvent @ %p\n", this); + printf(" mEventType = %d\n", (int)mEventType); + printf(" mBufferOffset = %d\n", (int)mBufferOffset); + printf(" mDurationInFrames = %d\n", (int)mDurationInFrames); + printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames); + printf(" mValue1 = %.5f\n", mValue1); + printf(" mValue2 = %.5f\n", mValue2); + } +#endif + +private: + AUParameterEventType mEventType; + + SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative) + UInt32 mDurationInFrames; // total duration of ramp parameter + AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp + AudioUnitParameterValue mValue2; // endValue (only used for ramp) + + UInt32 mSliceDurationFrames; // duration of this processing slice +}; + + + +// ____________________________________________________________________________ +// + +/*! @class AUElement */ +class AUElement { +public: +/*! @ctor AUElement */ + AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit), + mUseIndexedParameters(false), mElementName(0) { } + +/*! @dtor ~AUElement */ + virtual ~AUElement() { if (mElementName) CFRelease (mElementName); } + +/*! @method GetNumberOfParameters */ + UInt32 GetNumberOfParameters() + { + if(mUseIndexedParameters) return mIndexedParameters.size(); else return mParameters.size(); + } +/*! @method GetParameterList */ + void GetParameterList(AudioUnitParameterID *outList); + +/*! @method GetParameter */ + AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID); +/*! @method SetParameter */ + void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false); + // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted. + + // interpolates the start and end values corresponding to the current processing slice + // most ramp parameter implementations will want to use this method +/*! @method GetRampSliceStartEnd */ + void GetRampSliceStartEnd( AudioUnitParameterID paramID, + AudioUnitParameterValue & outStartValue, + AudioUnitParameterValue & outEndValue, + AudioUnitParameterValue & outValuePerFrameDelta ); + +/*! @method GetEndValue */ + AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID); + +/*! @method SetRampParameter */ + void SetScheduledEvent( AudioUnitParameterID paramID, + const AudioUnitParameterEvent &inEvent, + UInt32 inSliceOffsetInBuffer, + UInt32 inSliceDurationFrames, + bool okWhenInitialized = false ); + // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted. + + +/*! @method GetAudioUnit */ + AUBase * GetAudioUnit() const { return mAudioUnit; }; + +/*! @method SaveState */ + void SaveState(CFMutableDataRef data); +/*! @method RestoreState */ + const UInt8 * RestoreState(const UInt8 *state); +/*! @method GetName */ + CFStringRef GetName () const { return mElementName; } +/*! @method SetName */ + void SetName (CFStringRef inName); +/*! @method HasName */ + bool HasName () const { return mElementName != 0; } +/*! @method UseIndexedParameters */ + virtual void UseIndexedParameters(int inNumberOfParameters); + +protected: + inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID); + +private: + typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap; + +/*! @var mAudioUnit */ + AUBase * mAudioUnit; +/*! @var mParameters */ + ParameterMap mParameters; + +/*! @var mUseIndexedParameters */ + bool mUseIndexedParameters; +/*! @var mIndexedParameters */ + std::vector<ParameterMapEvent> mIndexedParameters; + +/*! @var mElementName */ + CFStringRef mElementName; +}; + + + +// ____________________________________________________________________________ +// +/*! @class AUIOElement */ +class AUIOElement : public AUElement { +public: +/*! @ctor AUIOElement */ + AUIOElement(AUBase *audioUnit); + +/*! @method GetStreamFormat */ + const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; } + +/*! @method SetStreamFormat */ + virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc); + +/*! @method AllocateBuffer */ + virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0); +/*! @method DeallocateBuffer */ + void DeallocateBuffer(); +/*! @method NeedsBufferSpace */ + virtual bool NeedsBufferSpace() const = 0; + +/*! @method DeallocateBuffer */ + void SetWillAllocateBuffer(bool inFlag) { + mWillAllocate = inFlag; + } +/*! @method DeallocateBuffer */ + bool WillAllocateBuffer() const { + return mWillAllocate; + } + +/*! @method UseExternalBuffer */ + void UseExternalBuffer(const AudioUnitExternalBuffer &buf) { + mIOBuffer.UseExternalBuffer(mStreamFormat, buf); + } +/*! @method PrepareBuffer */ + AudioBufferList & PrepareBuffer(UInt32 nFrames) { + if (mWillAllocate) + return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames); + throw OSStatus(kAudioUnitErr_InvalidPropertyValue); + } +/*! @method PrepareNullBuffer */ + AudioBufferList & PrepareNullBuffer(UInt32 nFrames) { + return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames); + } +/*! @method SetBufferList */ + AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); } +/*! @method SetBuffer */ + void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); } +/*! @method InvalidateBufferList */ + void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); } + +/*! @method GetBufferList */ + AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); } + +/*! @method GetChannelData */ + AudioUnitSampleType * GetChannelData(int ch) const { + if (mStreamFormat.IsInterleaved()) + return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData); + } + SInt16 * GetInt16ChannelData(int ch) const { + if (mStreamFormat.IsInterleaved()) + return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData); + } + +/*! @method CopyBufferListTo */ + void CopyBufferListTo(AudioBufferList &abl) const { + mIOBuffer.CopyBufferListTo(abl); + } +/*! @method CopyBufferContentsTo */ + void CopyBufferContentsTo(AudioBufferList &abl) const { + mIOBuffer.CopyBufferContentsTo(abl); + } + +/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; } + UInt32 BytesToFrames(AudioBufferList &abl) { + return BytesToFrames(abl.mBuffers[0].mDataByteSize); + } + UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/ + +/*! @method IsInterleaved */ + bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); } +/*! @method NumberChannels */ + UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); } +/*! @method NumberInterleavedChannels */ + UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); } + +/*! @method GetChannelMapTags */ + virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr); + +/*! @method GetAudioChannelLayout */ + virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable); + +/*! @method SetAudioChannelLayout */ + virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData); + +/*! @method RemoveAudioChannelLayout */ + virtual OSStatus RemoveAudioChannelLayout (); + +protected: +/*! @var mStreamFormat */ + CAStreamBasicDescription mStreamFormat; +/*! @var mIOBuffer */ + AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed + // for output: output cache, usually allocated early on +/*! @var mWillAllocate */ + bool mWillAllocate; +}; + +// ____________________________________________________________________________ +// +/*! @class AUElementCreator */ +class AUElementCreator { +public: +/*! @method CreateElement */ + virtual AUElement * CreateElement(AudioUnitScope scope, AudioUnitElement element) = 0; + virtual ~AUElementCreator() { } +}; + +// ____________________________________________________________________________ +// +// AUScopeDelegates are a way to get virtual scopes. +/*! @class AUScopeDelegate */ +class AUScopeDelegate { +public: +/*! @ctor AUScopeDelegate */ + AUScopeDelegate() : mCreator(NULL), mScope(0) { } +/*! @dtor ~AUScopeDelegate */ + virtual ~AUScopeDelegate() {} + +/*! @method Initialize */ + virtual void Initialize( AUElementCreator *creator, + AudioUnitScope scope, + UInt32 numElements) + { + mCreator = creator; + mScope = scope; + SetNumberOfElements(numElements); + } + +/*! @method SetNumberOfElements */ + virtual void SetNumberOfElements(UInt32 numElements) = 0; + +/*! @method GetNumberOfElements */ + virtual UInt32 GetNumberOfElements() = 0; + +/*! @method GetElement */ + virtual AUElement * GetElement(UInt32 elementIndex) = 0; + + AUElementCreator * GetCreator() const { return mCreator; } + AudioUnitScope GetScope() const { return mScope; } + + +private: +/*! @var mCreator */ + AUElementCreator * mCreator; +/*! @var mScope */ + AudioUnitScope mScope; +}; + + + +// ____________________________________________________________________________ +// +/*! @class AUScope */ +class AUScope { +public: +/*! @ctor AUScope */ + AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { } +/*! @dtor ~AUScope */ + ~AUScope(); + +/*! @method Initialize */ + void Initialize(AUElementCreator *creator, + AudioUnitScope scope, + UInt32 numElements) + { + if (mDelegate) + return mDelegate->Initialize(creator, scope, numElements); + + mCreator = creator; + mScope = scope; + SetNumberOfElements(numElements); + } + +/*! @method SetNumberOfElements */ + void SetNumberOfElements(UInt32 numElements); + +/*! @method GetNumberOfElements */ + UInt32 GetNumberOfElements() const + { + if (mDelegate) + return mDelegate->GetNumberOfElements(); + + return mElements.size(); + } + +/*! @method GetElement */ + AUElement * GetElement(UInt32 elementIndex) const + { + if (mDelegate) + return mDelegate->GetElement(elementIndex); + + ElementVector::const_iterator i = mElements.begin() + elementIndex; + // catch passing -1 in as the elementIndex - causes a wrap around + return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i; + } + +/*! @method SafeGetElement */ + AUElement * SafeGetElement(UInt32 elementIndex) + { + AUElement *element = GetElement(elementIndex); + if (element == NULL) + COMPONENT_THROW(kAudioUnitErr_InvalidElement); + return element; + } + +/*! @method GetIOElement */ + AUIOElement * GetIOElement(UInt32 elementIndex) const + { + AUElement *element = GetElement(elementIndex); + AUIOElement *ioel; + #if !CA_NO_RTTI + if (element == NULL || (ioel = dynamic_cast<AUIOElement *>(element)) == NULL) + COMPONENT_THROW (kAudioUnitErr_InvalidElement); + #else + if (element == NULL || (ioel = static_cast<AUIOElement *>(element)) == NULL) + COMPONENT_THROW (kAudioUnitErr_InvalidElement); + #endif + return ioel; + } + +/*! @method HasElementWithName */ + bool HasElementWithName () const; + +/*! @method AddElementNamesToDict */ + void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict); + + bool RestoreElementNames (CFDictionaryRef& inNameDict); + + AUElementCreator * GetCreator() const { return mCreator; } + AudioUnitScope GetScope() const { return mScope; } + + void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; } + +private: + typedef std::vector<AUElement *> ElementVector; +/*! @var mCreator */ + AUElementCreator * mCreator; +/*! @var mScope */ + AudioUnitScope mScope; +/*! @var mElements */ + ElementVector mElements; +/*! @var mDelegate */ + AUScopeDelegate * mDelegate; +}; + + + +#endif // __AUScopeElement_h__ |