summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp')
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp706
1 files changed, 706 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
new file mode 100644
index 0000000000..f1e2f248ab
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
@@ -0,0 +1,706 @@
+/*
+ File: AUPannerBase.cpp
+ Abstract: AUPannerBase.h
+ Version: 1.1
+
+ 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.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUPannerBase.h"
+#include "CABundleLocker.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <Accelerate/Accelerate.h>
+
+static bool sLocalized = false;
+
+static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth");
+static CFStringRef kPanner_Elevation_Name = CFSTR("elevation");
+static CFStringRef kPanner_Distance_Name = CFSTR("distance");
+
+static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale");
+static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance");
+static CFStringRef kPanner_Gain_Name = CFSTR("gain");
+
+static Float32 kPannerParamDefault_Azimuth = 0.;
+static Float32 kPannerParamDefault_Elevation = 0.;
+static Float32 kPannerParamDefault_Distance = 1.;
+
+static Float32 kPannerParamDefault_CoordScale = 10.;
+static Float32 kPannerParamDefault_RefDistance = 1.;
+static Float32 kPannerParamDefault_Gain = 1.;
+
+//_____________________________________________________________________________
+//
+AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
+ : AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
+{
+ {
+ CABundleLocker lock;
+ if (!sLocalized)
+ {
+ CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
+ if (bundle != NULL)
+ {
+ kPanner_Azimuth_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Elevation_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Distance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ kPanner_CoordScale_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Gain_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ }
+
+ sLocalized = true;
+ }
+ }
+
+ CreateElements();
+
+ SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
+ SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
+ SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
+
+ SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
+ SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
+ SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
+}
+
+//_____________________________________________________________________________
+//
+AUPannerBase::~AUPannerBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Initialize */
+OSStatus AUPannerBase::Initialize()
+{
+ OSStatus err = noErr;
+ AllocBypassMatrix();
+ err = UpdateBypassMatrix();
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method AllocBypassMatrix */
+void AUPannerBase::AllocBypassMatrix()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+}
+
+static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
+{
+ switch (inNumberChannels) {
+ case 1: return kAudioChannelLayoutTag_Mono;
+ case 2: return kAudioChannelLayoutTag_Stereo;
+ case 4: return kAudioChannelLayoutTag_Quadraphonic;
+ case 5: return kAudioChannelLayoutTag_AudioUnit_5_0;
+ case 6: return kAudioChannelLayoutTag_AudioUnit_6_0;
+ case 7: return kAudioChannelLayoutTag_AudioUnit_7_0;
+ case 8: return kAudioChannelLayoutTag_AudioUnit_8;
+
+ default: return 0xFFFF0000 | inNumberChannels;
+ }
+}
+
+//_____________________________________________________________________________
+//
+/*! @method UpdateBypassMatrix */
+OSStatus AUPannerBase::SetDefaultChannelLayoutsIfNone()
+{
+ OSStatus err = noErr;
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 inChannels = GetNumberOfInputChannels();
+ AudioChannelLayout inputLayoutSubstitute;
+ const AudioChannelLayout* inputLayout = &GetInputLayout();
+ if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
+ inputLayout = &inputLayoutSubstitute;
+ inputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ inputLayoutSubstitute.mChannelBitmap = 0;
+ inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);
+
+ mInputLayout = &inputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
+ if (err) return err;
+ }
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ AudioChannelLayout outputLayoutSubstitute;
+ const AudioChannelLayout* outputLayout = &GetOutputLayout();
+ if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
+ outputLayout = &outputLayoutSubstitute;
+ outputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ outputLayoutSubstitute.mChannelBitmap = 0;
+ outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);
+
+ mOutputLayout = &outputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
+ if (err) return err;
+ }
+
+ return err;
+}
+
+
+
+OSStatus AUPannerBase::UpdateBypassMatrix()
+{
+ OSStatus err = SetDefaultChannelLayoutsIfNone();
+ if (err) return err;
+
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+
+ const AudioChannelLayout* inoutACL[2];
+
+ inoutACL[0] = &GetInputLayout();
+ inoutACL[1] = &GetOutputLayout();
+
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+
+ UInt32 propSize = inChannels * outChannels * sizeof(Float32);
+
+ err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
+ if (err) {
+ // if there is an error, use a diagonal matrix.
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
+ {
+ float *amp = bypass + (chan * outChannels + chan);
+ *amp = 1.;
+ }
+ }
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Cleanup */
+void AUPannerBase::Cleanup()
+{
+
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method Reset */
+OSStatus AUPannerBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return AUBase::Reset(inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetParameterInfo */
+OSStatus AUPannerBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ OSStatus result = noErr;
+
+ outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
+ + kAudioUnitParameterFlag_IsReadable;
+
+ if (inScope == kAudioUnitScope_Global) {
+
+ switch(inParameterID)
+ {
+ case kPannerParam_Azimuth:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -180.;
+ outParameterInfo.maxValue = 180;
+ outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
+ break;
+
+ case kPannerParam_Elevation:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -90.;
+ outParameterInfo.maxValue = 90;
+ outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
+ break;
+
+ case kPannerParam_Distance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.0;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Distance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
+ //outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_CoordScale:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_RefDistance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_Gain:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Gain;
+ break;
+
+ default:
+ result = kAudioUnitErr_InvalidParameter;
+ break;
+ }
+ } else {
+ result = kAudioUnitErr_InvalidParameter;
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outValue = Globals()->GetParameter(inParamID);
+
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ Globals()->SetParameter(inParamID, inValue);
+
+ return noErr;
+}
+
+
+
+//_____________________________________________________________________________
+//
+/*! @method GetPropertyInfo */
+OSStatus AUPannerBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus err = noErr;
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ break;
+ default:
+ err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetProperty */
+OSStatus AUPannerBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus err = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ break;
+ default:
+ err = AUBase::GetProperty(inID, inScope, inElement, outData);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method SetProperty */
+OSStatus AUPannerBase::SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method StreamFormatWritable */
+bool AUPannerBase::StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method ChangeStreamFormat */
+OSStatus AUPannerBase::ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
+ RemoveAudioChannelLayout(inScope, inElement);
+
+ return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ if (IsBypassEffect())
+ return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
+ else
+ return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ AudioUnitRenderActionFlags xflags = 0;
+ OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
+ if (result) return false;
+ bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;
+
+ AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
+ AUBufferList::ZeroBuffer(outputBufferList);
+
+ if (!isSilent)
+ {
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
+ {
+ float* outData = GetOutput(0)->GetChannelData(outChan);
+
+ for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
+ {
+ float* inData = GetInput(0)->GetChannelData(inChan);
+ float *amp = bypass + (inChan * outChannels + outChan);
+ vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
+ }
+ }
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ SetDefaultChannelLayoutsIfNone();
+
+ outWritable = true;
+
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+
+ if (inElement != 0)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+
+ UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
+ if (size > 0 && outLayoutPtr)
+ memcpy(outLayoutPtr, &caacl->Layout(), size);
+
+ return size;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ *caacl = NULL;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ if (!inLayout)
+ return RemoveAudioChannelLayout(inScope, inElement);
+
+ if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
+ return kAudioUnitErr_FormatNotSupported;
+
+ CAAudioChannelLayout* caacl = NULL;
+ UInt32 currentChannels;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ currentChannels = GetNumberOfInputChannels();
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ currentChannels = GetNumberOfOutputChannels();
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ *caacl = inLayout;
+ if (IsInitialized())
+ UpdateBypassMatrix();
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Mono;
+ outTags[1] = kAudioChannelLayoutTag_Stereo;
+ outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
+ }
+ return 3;
+ case kAudioUnitScope_Output:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Stereo;
+ outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
+ outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
+ outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
+ outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
+ outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
+ outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
+ }
+ return 7;
+ default: {
+ OSStatus err = kAudioUnitErr_InvalidScope;
+ throw err;
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelConfigIsSupported()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
+ return true;
+ }
+ return false;
+}
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].outChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag)
+{
+ UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
+ CAAutoFree<AudioChannelLayoutTag> tags(numTags);
+ GetChannelLayoutTags(inScope, inElement, tags());
+
+ for (UInt32 i = 0; i < numTags; ++i)
+ {
+ if (tags[i] == inTag)
+ return true;
+ }
+
+ return false;
+}
+