2 File: CAAUParameter.cpp
3 Abstract: CAAUParameter.h
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 #include "CAAUParameter.h"
49 CAAUParameter::CAAUParameter()
51 memset(this, 0, sizeof(CAAUParameter));
54 CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
56 memset(this, 0, sizeof(CAAUParameter));
57 Init (au, param, scope, element);
60 CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
62 memset(this, 0, sizeof(CAAUParameter));
63 Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
66 CAAUParameter::CAAUParameter(const CAAUParameter &a)
68 memset(this, 0, sizeof(CAAUParameter));
72 CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a)
74 if (mParamName) CFRelease(mParamName);
75 if (mParamTag) CFRelease(mParamTag);
76 if (mNamedParams) CFRelease(mNamedParams);
78 memcpy(this, &a, sizeof(CAAUParameter));
80 if (mParamName) CFRetain(mParamName);
81 if (mParamTag) CFRetain(mParamTag);
82 if (mNamedParams) CFRetain(mNamedParams);
87 CAAUParameter::~CAAUParameter()
89 if (mParamName) CFRelease(mParamName);
90 if (mParamTag) CFRelease(mParamTag);
91 if (mNamedParams) CFRelease (mNamedParams);
94 void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
101 UInt32 propertySize = sizeof(mParamInfo);
102 OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
103 scope, param, &mParamInfo, &propertySize);
105 memset(&mParamInfo, 0, sizeof(mParamInfo));
106 if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
107 mParamName = mParamInfo.cfNameString;
108 if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease))
109 CFRetain (mParamName);
111 mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
114 switch (mParamInfo.unit)
116 case kAudioUnitParameterUnit_Boolean:
119 case kAudioUnitParameterUnit_Percent:
120 case kAudioUnitParameterUnit_EqualPowerCrossfade:
123 case kAudioUnitParameterUnit_Seconds:
126 case kAudioUnitParameterUnit_SampleFrames:
129 case kAudioUnitParameterUnit_Phase:
130 case kAudioUnitParameterUnit_Degrees:
133 case kAudioUnitParameterUnit_Hertz:
136 case kAudioUnitParameterUnit_Cents:
137 case kAudioUnitParameterUnit_AbsoluteCents:
140 case kAudioUnitParameterUnit_RelativeSemiTones:
143 case kAudioUnitParameterUnit_MIDINoteNumber:
144 case kAudioUnitParameterUnit_MIDIController:
146 //these are inclusive, so add one value here
147 mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
149 case kAudioUnitParameterUnit_Decibels:
152 case kAudioUnitParameterUnit_MixerFaderCurve1:
153 case kAudioUnitParameterUnit_LinearGain:
156 case kAudioUnitParameterUnit_Pan:
159 case kAudioUnitParameterUnit_Meters:
162 case kAudioUnitParameterUnit_Octaves:
165 case kAudioUnitParameterUnit_BPM:
168 case kAudioUnitParameterUnit_Beats:
171 case kAudioUnitParameterUnit_Milliseconds:
174 case kAudioUnitParameterUnit_Ratio:
177 case kAudioUnitParameterUnit_Indexed:
179 propertySize = sizeof(mNamedParams);
180 err = AudioUnitGetProperty (au,
181 kAudioUnitProperty_ParameterValueStrings,
186 if (!err && mNamedParams) {
187 mNumIndexedParams = CFArrayGetCount(mNamedParams);
189 //these are inclusive, so add one value here
190 mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
195 case kAudioUnitParameterUnit_CustomUnit:
197 CFStringRef unitName = mParamInfo.unitName;
198 static char paramStr[256];
199 CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
200 if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
201 CFRelease (unitName);
205 case kAudioUnitParameterUnit_Generic:
206 case kAudioUnitParameterUnit_Rate:
213 mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
219 Float32 CAAUParameter::GetValue() const
223 AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
227 CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
228 const CAAUParameter * inParameter,
231 if (!inParameter) return nil;
233 AudioUnitParameterInfo info = inParameter->ParamInfo();
237 case kAudioUnitParameterUnit_Hertz:
238 // number of significant digits based on value
239 pow10 = int(log10(fmax(inParameterValue, .000001)));
242 // number of significant digits based on parameter range
243 pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001)));
247 // pow10 range nDigitsAfterDecimal
256 int nDigitsAfterDecimal = inDigits - (pow10 + 1);
257 if (nDigitsAfterDecimal < 0)
258 nDigitsAfterDecimal = 0; // the least number of digits possible is zero
260 if (info.flags & kAudioUnitParameterFlag_IsHighResolution)
261 nDigitsAfterDecimal = 4;
263 CFLocaleRef currentLocale = CFLocaleCopyCurrent();
264 CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
266 CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
268 if (nDigitsAfterDecimal > 0)
269 nDigitsAfterDecimal = minDigits;
271 CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
273 CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits);
274 CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits);
275 CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue);
277 CFRelease(currentLocale);
278 CFRelease(numberFormatter);
279 CFRelease(maxFractionDigits);
280 CFRelease(minFractionDigits);
282 return formattedNumberString;
285 CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
286 const CAAUParameter * inParameter,
288 return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1);
291 double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) {
292 CFLocaleRef currentLocale = CFLocaleCopyCurrent();
293 CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
296 Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value);
298 CFRelease(currentLocale);
299 CFRelease(numberFormatter);
304 AudioUnitParameterInfo info = inParameter->ParamInfo();
305 return info.defaultValue;
309 CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
311 if (HasNamedParams())
313 Float32 val = (value == NULL ? GetValue() : *value);
314 int index = int(mParamInfo.minValue) + int(val);
315 CFStringRef str = GetParamName (index);
321 else if (ValuesHaveStrings())
323 AudioUnitParameterStringFromValue stringValue;
324 stringValue.inParamID = mParameterID;
325 stringValue.inValue = value;
326 stringValue.outString = NULL;
327 UInt32 propertySize = sizeof(stringValue);
329 OSStatus err = AudioUnitGetProperty (mAudioUnit,
330 kAudioUnitProperty_ParameterStringFromValue,
336 if (!err && stringValue.outString != NULL)
337 return stringValue.outString;
340 Float32 val = (value == NULL ? GetValue() : *value);
341 AudioUnitParameterUnit unit = this->ParamInfo().unit;
342 if (unit == kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents)
343 return CreateLocalizedStringForParameterValue(val, this, 4, 0);
345 return CreateLocalizedStringForParameterValue(val, this, 4);
348 Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
350 if (ValuesHaveStrings())
352 AudioUnitParameterValueFromString valueString;
353 valueString.inParamID = mParameterID;
354 valueString.inString = str;
355 UInt32 propertySize = sizeof(valueString);
357 OSStatus err = AudioUnitGetProperty (mAudioUnit,
358 kAudioUnitProperty_ParameterValueFromString,
365 return valueString.outValue;
369 return (Float32) ValueForLocalizedParameterString(str, this);
372 void CAAUParameter::SetValue( AUParameterListenerRef inListener,
374 Float32 inValue) const
376 // clip inValue as: maxValue >= inValue >= minValue before setting
377 Float32 valueToSet = inValue;
378 if (valueToSet > mParamInfo.maxValue)
379 valueToSet = mParamInfo.maxValue;
380 if (valueToSet < mParamInfo.minValue)
381 valueToSet = mParamInfo.minValue;
383 AUParameterSet(inListener, inObject, this, valueToSet, 0);
387 void CAAUParameter::Print() const
392 UInt32 len = static_cast<UInt32>(CFStringGetLength(mParamName));
393 char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
394 if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
397 printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars);