1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

AUv3: Improved the host-provided parameter views

This commit is contained in:
Tom Poole 2018-02-01 12:05:41 +00:00
parent c24c06d2bb
commit 3c0d634b4f
2 changed files with 103 additions and 17 deletions

View file

@ -525,11 +525,11 @@ public:
{
if (juceFilter != nullptr)
{
const int paramID = getJuceIndexForAUParameterID (pv->inParamID);
const int i = getJuceIndexForAUParameterID (pv->inParamID);
const String text (String::fromCFString (pv->inString));
if (AudioProcessorParameter* param = juceFilter->getParameters() [paramID])
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (paramID);
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (i);
else
pv->outValue = text.getFloatValue();
@ -545,12 +545,12 @@ public:
{
if (juceFilter != nullptr)
{
const int paramID = getJuceIndexForAUParameterID (pv->inParamID);
const int i = getJuceIndexForAUParameterID (pv->inParamID);
const float value = (float) *(pv->inValue);
String text;
if (AudioProcessorParameter* param = juceFilter->getParameters() [paramID])
text = param->getText (value / getMaximumParameterValue (paramID), 0);
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
text = param->getText (value / getMaximumParameterValue (i), 0);
else
text = String (value);
@ -776,7 +776,7 @@ public:
return (UInt32) layouts.size();
}
OSStatus SetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override
OSStatus SetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override
{
bool isInput;
int busNr;
@ -877,8 +877,8 @@ public:
else
{
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
outParameterInfo.unit = isParameterDiscrete ? kAudioUnitParameterUnit_Indexed
: kAudioUnitParameterUnit_Generic;
if (isParameterDiscrete)
outParameterInfo.unit = kAudioUnitParameterUnit_Indexed;
#endif
}

View file

@ -1082,13 +1082,22 @@ private:
busses: array];
}
// When parameters are discrete we need to use integer values.
float getMaximumParameterValue (int parameterIndex)
{
#if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
ignoreUnused (parameterIndex);
return 1.0f;
#else
auto& processor = getAudioProcessor();
return processor.isParameterDiscrete (parameterIndex) ? (float) (processor.getParameterNumSteps (parameterIndex) - 1) : 1.0f;
#endif
}
void addParameters()
{
ScopedPointer<NSMutableArray<AUParameterNode*>> params = [[NSMutableArray<AUParameterNode*> alloc] init];
paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
auto& processor = getAudioProcessor();
@ -1118,9 +1127,17 @@ private:
if (name.isEmpty() || ! processor.isParameterAutomatable (idx))
flags |= kAudioUnitParameterFlag_NonRealTime;
const bool isParameterDiscrete = processor.isParameterDiscrete (idx);
if (! isParameterDiscrete)
flags |= kAudioUnitParameterFlag_CanRamp;
if (processor.isMetaParameter (idx))
flags |= kAudioUnitParameterFlag_IsGlobalMeta;
auto deleter = [](NSMutableArray* arr) { [arr release]; };
std::unique_ptr<NSMutableArray, decltype (deleter)> valueStrings (nullptr, deleter);
// is this a meter?
if (((processor.getParameterCategory (idx) & 0xffff0000) >> 16) == 2)
{
@ -1128,13 +1145,36 @@ private:
flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
unit = kAudioUnitParameterUnit_LinearGain;
}
else
{
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
if (auto* param = processor.getParameters()[idx])
{
if (param->isDiscrete())
{
unit = kAudioUnitParameterUnit_Indexed;
auto maxValue = getMaximumParameterValue (idx);
auto numSteps = param->getNumSteps();
// Some hosts can't handle the huge numbers of discrete parameter values created when
// using the default number of steps.
jassert (numSteps != AudioProcessor::getDefaultNumParameterSteps());
valueStrings.reset ([NSMutableArray new]);
for (int i = 0; i < numSteps; ++i)
[valueStrings.get() addObject: juceStringToNS (param->getText ((float) i / maxValue, 0))];
}
}
#endif
}
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
AUParameterAddress address = static_cast<AUParameterAddress> (idx);
#else
AUParameterAddress address = generateAUParameterAddressForIndex (idx);
// Consider yourself very unlucky if you hit this assertion. The hash code of your
// Consider yourself very unlucky if you hit this assertion. The hash codes of your
// parameter ids are not unique.
jassert (! paramMap.contains (static_cast<int64> (address)));
@ -1148,13 +1188,15 @@ private:
name: juceStringToNS (name)
address: address
min: 0.0f
max: 1.0f
max: getMaximumParameterValue (idx)
unit: unit
unitName: nullptr
flags: flags
valueStrings: nullptr
valueStrings: valueStrings.get()
dependentParameters: nullptr] retain];
[param.get() setValue: processor.getParameterDefaultValue (idx)];
[params addObject: param];
[overviewParams addObject: [NSNumber numberWithUnsignedLongLong:address]];
}
@ -1162,8 +1204,15 @@ private:
// create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
paramTree = [[AUParameterTree createTreeWithChildren: params] retain];
paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
stringFromValueProvider = CreateObjCBlock (this, &JuceAudioUnitv3::stringFromValue);
valueFromStringProvider = CreateObjCBlock (this, &JuceAudioUnitv3::valueFromString);
[paramTree setImplementorValueObserver: paramObserver];
[paramTree setImplementorValueProvider: paramProvider];
[paramTree setImplementorStringFromValueCallback: stringFromValueProvider];
[paramTree setImplementorValueFromStringCallback: valueFromStringProvider];
if (processor.hasEditor())
{
@ -1375,7 +1424,7 @@ private:
auto& processor = getAudioProcessor();
if (isPositiveAndBelow (idx, processor.getNumParameters()))
processor.setParameter (idx, value);
processor.setParameter (idx, value / getMaximumParameterValue (idx));
}
}
@ -1387,7 +1436,7 @@ private:
auto& processor = getAudioProcessor();
if (isPositiveAndBelow (idx, processor.getNumParameters()))
return processor.getParameter (idx);
return processor.getParameter (idx) * getMaximumParameterValue (idx);
}
return 0;
@ -1398,6 +1447,41 @@ private:
// this will have already been handled by valueChangedFromHost
}
NSString* stringFromValue (AUParameter* param, const AUValue* value)
{
String text;
if (param != nullptr && value != nullptr)
{
const int idx = getJuceParameterIndexForAUAddress ([param address]);
auto& processor = getAudioProcessor();
if (auto* p = processor.getParameters()[idx])
text = p->getText (*value / getMaximumParameterValue (idx), 0);
else
text = String (*value);
}
return juceStringToNS (text);
}
AUValue valueFromString (AUParameter* param, NSString* str)
{
if (param != nullptr && str != nullptr)
{
const int idx = getJuceParameterIndexForAUAddress ([param address]);
auto& processor = getAudioProcessor();
const String text (nsStringToJuce (str));
if (auto* p = processor.getParameters()[idx])
return p->getValueForText (text) * getMaximumParameterValue (idx);
else
return text.getFloatValue();
}
return 0;
}
//==============================================================================
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept { return static_cast<AUParameterAddress> (paramIndex); }
@ -1443,6 +1527,8 @@ private:
ObjCBlock<AUImplementorValueObserver> paramObserver;
ObjCBlock<AUImplementorValueProvider> paramProvider;
ObjCBlock<AUImplementorStringFromValueCallback> stringFromValueProvider;
ObjCBlock<AUImplementorValueFromStringCallback> valueFromStringProvider;
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
bool usingManagedParameter;