Browse Source

AudioProcessorParameter: Add new ParameterID and Attributes types

pull/22/head
reuk 3 years ago
parent
commit
afe5199848
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
17 changed files with 692 additions and 221 deletions
  1. +28
    -0
      BREAKING-CHANGES.txt
  2. +1
    -1
      modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  3. +1
    -1
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  4. +28
    -41
      modules/juce_audio_processors/utilities/juce_AudioParameterBool.cpp
  5. +44
    -6
      modules/juce_audio_processors/utilities/juce_AudioParameterBool.h
  6. +12
    -14
      modules/juce_audio_processors/utilities/juce_AudioParameterChoice.cpp
  7. +45
    -6
      modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h
  8. +13
    -12
      modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp
  9. +48
    -8
      modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h
  10. +20
    -25
      modules/juce_audio_processors/utilities/juce_AudioParameterInt.cpp
  11. +51
    -7
      modules/juce_audio_processors/utilities/juce_AudioParameterInt.h
  12. +9
    -8
      modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.cpp
  13. +117
    -6
      modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h
  14. +93
    -66
      modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
  15. +105
    -11
      modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
  16. +61
    -9
      modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h
  17. +16
    -0
      modules/juce_core/misc/juce_Functional.h

+ 28
- 0
BREAKING-CHANGES.txt View File

@@ -1,6 +1,34 @@
JUCE breaking changes
=====================

develop
=======

Change
------
Constructors of AudioParameterBool, AudioParameterChoice, AudioParameterFloat,
AudioParameterInt, and AudioProcessorParameterWithID have been deprecated and
replaced with new constructors taking an 'Attributes' argument.

Possible Issues
---------------
The compiler may issue a deprecation warning upon encountering usages of the
old constructors.

Workaround
----------
Update code to pass an 'Attributes' instance instead. Example usages of the new
constructors are given in the constructor documentation, and in the plugin
example projects.

Rationale
---------
Parameter types have many different properties. Setting a non-default property
using the old constructors required explicitly setting other normally-defaulted
properties, which was redundant. The new Attributes types allow non-default
properties to be set in isolation.


Version 6.1.6
=============



+ 1
- 1
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp View File

@@ -1601,7 +1601,7 @@ namespace AAXClasses
if (bypassParameter == nullptr)
{
ownedBypassParameter.reset (new AudioParameterBool (cDefaultMasterBypassID, "Master Bypass", false, {}, {}, {}));
ownedBypassParameter.reset (new AudioParameterBool (cDefaultMasterBypassID, "Master Bypass", false));
bypassParameter = ownedBypassParameter.get();
}


+ 1
- 1
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -526,7 +526,7 @@ private:
if (bypassParameter == nullptr)
{
vst3WrapperProvidedBypassParam = true;
ownedBypassParameter.reset (new AudioParameterBool ("byps", "Bypass", false, {}, {}, {}));
ownedBypassParameter.reset (new AudioParameterBool ("byps", "Bypass", false));
bypassParameter = ownedBypassParameter.get();
}


+ 28
- 41
modules/juce_audio_processors/utilities/juce_AudioParameterBool.cpp View File

@@ -26,49 +26,36 @@
namespace juce
{
AudioParameterBool::AudioParameterBool (const String& idToUse,
AudioParameterBool::AudioParameterBool (const ParameterID& idToUse,
const String& nameToUse,
bool def,
const String& labelToUse,
std::function<String (bool, int)> stringFromBool,
std::function<bool (const String&)> boolFromString,
int versionHintToUse)
: RangedAudioParameter (idToUse, nameToUse, labelToUse, Category::genericParameter, versionHintToUse),
value (def ? 1.0f : 0.0f),
defaultValue (value),
stringFromBoolFunction (stringFromBool),
boolFromStringFunction (boolFromString)
const AudioParameterBoolAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
value (def ? 1.0f : 0.0f),
valueDefault (def),
stringFromBoolFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [] (bool v, int) { return v ? TRANS("On") : TRANS("Off"); }),
boolFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [] (const String& text)
{
static const StringArray onStrings { TRANS ("on"), TRANS ("yes"), TRANS ("true") };
static const StringArray offStrings { TRANS ("off"), TRANS ("no"), TRANS ("false") };
String lowercaseText (text.toLowerCase());
for (auto& testText : onStrings)
if (lowercaseText == testText)
return true;
for (auto& testText : offStrings)
if (lowercaseText == testText)
return false;
return text.getIntValue() != 0;
})
{
if (stringFromBoolFunction == nullptr)
stringFromBoolFunction = [] (bool v, int) { return v ? TRANS("On") : TRANS("Off"); };
if (boolFromStringFunction == nullptr)
{
StringArray onStrings;
onStrings.add (TRANS("on"));
onStrings.add (TRANS("yes"));
onStrings.add (TRANS("true"));
StringArray offStrings;
offStrings.add (TRANS("off"));
offStrings.add (TRANS("no"));
offStrings.add (TRANS("false"));
boolFromStringFunction = [onStrings, offStrings] (const String& text)
{
String lowercaseText (text.toLowerCase());
for (auto& testText : onStrings)
if (lowercaseText == testText)
return true;
for (auto& testText : offStrings)
if (lowercaseText == testText)
return false;
return text.getIntValue() != 0;
};
}
}
AudioParameterBool::~AudioParameterBool()
@@ -81,7 +68,7 @@ AudioParameterBool::~AudioParameterBool()
float AudioParameterBool::getValue() const { return value; }
void AudioParameterBool::setValue (float newValue) { value = newValue; valueChanged (get()); }
float AudioParameterBool::getDefaultValue() const { return defaultValue; }
float AudioParameterBool::getDefaultValue() const { return valueDefault; }
int AudioParameterBool::getNumSteps() const { return 2; }
bool AudioParameterBool::isDiscrete() const { return true; }
bool AudioParameterBool::isBoolean() const { return true; }


+ 44
- 6
modules/juce_audio_processors/utilities/juce_AudioParameterBool.h View File

@@ -26,6 +26,13 @@
namespace juce
{
/** Properties of an AudioParameterBool.
@see AudioParameterBool(), RangedAudioParameterAttributes()
*/
class AudioParameterBoolAttributes : public RangedAudioParameterAttributes<AudioParameterBoolAttributes, bool> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used as a boolean value.
@@ -36,6 +43,28 @@ namespace juce
class JUCE_API AudioParameterBool : public RangedAudioParameter
{
public:
/** Creates a AudioParameterBool with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterBoolAttributes().withStringFromValueFunction ([] (auto x, auto) { return x ? "On" : "Off"; })
.withLabel ("enabled");
auto param = std::make_unique<AudioParameterBool> ("paramID", "Parameter Name", false, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param defaultValue The default value
@param attributes Optional characteristics
*/
AudioParameterBool (const ParameterID& parameterID,
const String& parameterName,
bool defaultValue,
const AudioParameterBoolAttributes& attributes = {});
/** Creates a AudioParameterBool with the specified parameters.
@param parameterID The parameter ID to use
@@ -48,13 +77,22 @@ public:
@param boolFromString An optional lambda function that parses a string and
converts it into a bool value. Some hosts use this
to allow users to type in parameter values.
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
AudioParameterBool (const String& parameterID, const String& parameterName, bool defaultValue,
const String& parameterLabel = String(),
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterBool (const ParameterID& parameterID,
const String& parameterName,
bool defaultValue,
const String& parameterLabel,
std::function<String (bool value, int maximumStringLength)> stringFromBool = nullptr,
std::function<bool (const String& text)> boolFromString = nullptr,
int versionHint = 0);
std::function<bool (const String& text)> boolFromString = nullptr)
: AudioParameterBool (parameterID,
parameterName,
defaultValue,
AudioParameterBoolAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromBool))
.withValueFromStringFunction (std::move (boolFromString)))
{
}
/** Destructor. */
~AudioParameterBool() override;
@@ -90,7 +128,7 @@ private:
const NormalisableRange<float> range { 0.0f, 1.0f, 1.0f };
std::atomic<float> value;
const float defaultValue;
const float valueDefault;
std::function<String (bool, int)> stringFromBoolFunction;
std::function<bool (const String&)> boolFromStringFunction;


+ 12
- 14
modules/juce_audio_processors/utilities/juce_AudioParameterChoice.cpp View File

@@ -26,12 +26,12 @@
namespace juce
{
AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String& nameToUse,
const StringArray& c, int def, const String& labelToUse,
std::function<String (int, int)> stringFromIndex,
std::function<int (const String&)> indexFromString,
int versionHintToUse)
: RangedAudioParameter (idToUse, nameToUse, labelToUse, Category::genericParameter, versionHintToUse),
AudioParameterChoice::AudioParameterChoice (const ParameterID& idToUse,
const String& nameToUse,
const StringArray& c,
int def,
const AudioParameterChoiceAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
choices (c),
range ([this]
{
@@ -44,16 +44,14 @@ AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String&
}()),
value ((float) def),
defaultValue (convertTo0to1 ((float) def)),
stringFromIndexFunction (stringFromIndex),
indexFromStringFunction (indexFromString)
stringFromIndexFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [this] (int index, int) { return choices [index]; }),
indexFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [this] (const String& text) { return choices.indexOf (text); })
{
jassert (choices.size() > 1); // you must supply an actual set of items to choose from!
if (stringFromIndexFunction == nullptr)
stringFromIndexFunction = [this] (int index, int) { return choices [index]; };
if (indexFromStringFunction == nullptr)
indexFromStringFunction = [this] (const String& text) { return choices.indexOf (text); };
}
AudioParameterChoice::~AudioParameterChoice()


+ 45
- 6
modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h View File

@@ -26,6 +26,13 @@
namespace juce
{
/** Properties of an AudioParameterChoice.
@see AudioParameterChoice(), RangedAudioParameterAttributes()
*/
class AudioParameterChoiceAttributes : public RangedAudioParameterAttributes<AudioParameterChoiceAttributes, int> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used to select
an indexed, named choice from a list.
@@ -39,10 +46,33 @@ class JUCE_API AudioParameterChoice : public RangedAudioParameter
public:
/** Creates a AudioParameterChoice with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterChoiceAttributes().withLabel ("selected");
auto param = std::make_unique<AudioParameterChoice> ("paramID", "Parameter Name", StringArray { "a", "b", "c" }, 0, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param choices The set of choices to use
@param defaultItemIndex The index of the default choice
@param attributes Optional characteristics
*/
AudioParameterChoice (const ParameterID& parameterID,
const String& parameterName,
const StringArray& choices,
int defaultItemIndex,
const AudioParameterChoiceAttributes& attributes = {});
/** Creates a AudioParameterChoice with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param choicesToUse The set of choices to use
@param defaultItemIndex The index of the default choice
@param parameterLabel An optional label for the parameter's value
@param stringFromIndex An optional lambda function that converts a choice
index to a string with a maximum length. This may
@@ -50,15 +80,24 @@ public:
@param indexFromString An optional lambda function that parses a string and
converts it into a choice index. Some hosts use this
to allow users to type in parameter values.
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
AudioParameterChoice (const String& parameterID, const String& parameterName,
const StringArray& choices,
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterChoice (const ParameterID& parameterID,
const String& parameterName,
const StringArray& choicesToUse,
int defaultItemIndex,
const String& parameterLabel = String(),
const String& parameterLabel,
std::function<String (int index, int maximumStringLength)> stringFromIndex = nullptr,
std::function<int (const String& text)> indexFromString = nullptr,
int versionHint = 0);
std::function<int (const String& text)> indexFromString = nullptr)
: AudioParameterChoice (parameterID,
parameterName,
choicesToUse,
defaultItemIndex,
AudioParameterChoiceAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromIndex))
.withValueFromStringFunction (std::move (indexFromString)))
{
}
/** Destructor. */
~AudioParameterChoice() override;


+ 13
- 12
modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp View File

@@ -26,16 +26,17 @@
namespace juce
{
AudioParameterFloat::AudioParameterFloat (const String& idToUse, const String& nameToUse,
NormalisableRange<float> r, float def,
const String& labelToUse, Category categoryToUse,
std::function<String (float, int)> stringFromValue,
std::function<float (const String&)> valueFromString,
int versionHintToUse)
: RangedAudioParameter (idToUse, nameToUse, labelToUse, categoryToUse, versionHintToUse),
range (r), value (def), defaultValue (def),
stringFromValueFunction (stringFromValue),
valueFromStringFunction (valueFromString)
AudioParameterFloat::AudioParameterFloat (const ParameterID& idToUse,
const String& nameToUse,
NormalisableRange<float> r,
float def,
const AudioParameterFloatAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
range (r),
value (def),
valueDefault (def),
stringFromValueFunction (attributes.getStringFromValueFunction()),
valueFromStringFunction (attributes.getValueFromStringFunction())
{
if (stringFromValueFunction == nullptr)
{
@@ -71,7 +72,7 @@ AudioParameterFloat::AudioParameterFloat (const String& idToUse, const String& n
valueFromStringFunction = [] (const String& text) { return text.getFloatValue(); };
}
AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue, float maxValue, float def)
AudioParameterFloat::AudioParameterFloat (const ParameterID& pid, const String& nm, float minValue, float maxValue, float def)
: AudioParameterFloat (pid, nm, { minValue, maxValue, 0.01f }, def)
{
}
@@ -86,7 +87,7 @@ AudioParameterFloat::~AudioParameterFloat()
float AudioParameterFloat::getValue() const { return convertTo0to1 (value); }
void AudioParameterFloat::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (get()); }
float AudioParameterFloat::getDefaultValue() const { return convertTo0to1 (defaultValue); }
float AudioParameterFloat::getDefaultValue() const { return convertTo0to1 (valueDefault); }
int AudioParameterFloat::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
String AudioParameterFloat::getText (float v, int length) const { return stringFromValueFunction (convertFrom0to1 (v), length); }
float AudioParameterFloat::getValueForText (const String& text) const { return convertTo0to1 (valueFromStringFunction (text)); }


+ 48
- 8
modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h View File

@@ -26,6 +26,13 @@
namespace juce
{
/** Properties of an AudioParameterFloat.
@see AudioParameterFloat(), RangedAudioParameterAttributes()
*/
class AudioParameterFloatAttributes : public RangedAudioParameterAttributes<AudioParameterFloatAttributes, float> {};
//==============================================================================
/**
A subclass of AudioProcessorParameter that provides an easy way to create a
parameter which maps onto a given NormalisableRange.
@@ -37,6 +44,30 @@ namespace juce
class JUCE_API AudioParameterFloat : public RangedAudioParameter
{
public:
/** Creates a AudioParameterFloat with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterFloatAttributes().withStringFromValueFunction ([] (auto x, auto) { return String (x * 100); })
.withLabel ("%");
auto param = std::make_unique<AudioParameterFloat> ("paramID", "Parameter Name", NormalisableRange<float>(), 0.5f, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param normalisableRange The NormalisableRange to use
@param defaultValue The non-normalised default value
@param attributes Optional characteristics
*/
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
NormalisableRange<float> normalisableRange,
float defaultValue,
const AudioParameterFloatAttributes& attributes = {});
/** Creates a AudioParameterFloat with the specified parameters.
@param parameterID The parameter ID to use
@@ -51,25 +82,34 @@ public:
@param valueFromString An optional lambda function that parses a string and
converts it into a non-normalised value. Some hosts use
this to allow users to type in parameter values.
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
AudioParameterFloat (const String& parameterID,
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
NormalisableRange<float> normalisableRange,
float defaultValue,
const String& parameterLabel = String(),
const String& parameterLabel,
Category parameterCategory = AudioProcessorParameter::genericParameter,
std::function<String (float value, int maximumStringLength)> stringFromValue = nullptr,
std::function<float (const String& text)> valueFromString = nullptr,
int versionHint = 0);
std::function<float (const String& text)> valueFromString = nullptr)
: AudioParameterFloat (parameterID,
parameterName,
std::move (normalisableRange),
defaultValue,
AudioParameterFloatAttributes().withLabel (parameterLabel)
.withCategory (parameterCategory)
.withStringFromValueFunction (std::move (stringFromValue))
.withValueFromStringFunction (std::move (valueFromString)))
{
}
/** Creates a AudioParameterFloat with an ID, name, and range.
On creation, its value is set to the default value.
For control over skew factors, you can use the other
constructor and provide a NormalisableRange.
*/
AudioParameterFloat (String parameterID,
String parameterName,
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
float minValue,
float maxValue,
float defaultValue);
@@ -108,7 +148,7 @@ private:
float getValueForText (const String&) const override;
std::atomic<float> value;
const float defaultValue;
const float valueDefault;
std::function<String (float, int)> stringFromValueFunction;
std::function<float (const String&)> valueFromStringFunction;


+ 20
- 25
modules/juce_audio_processors/utilities/juce_AudioParameterInt.cpp View File

@@ -26,34 +26,29 @@
namespace juce
{
AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameToUse,
AudioParameterInt::AudioParameterInt (const ParameterID& idToUse, const String& nameToUse,
int minValue, int maxValue, int def,
const String& labelToUse,
std::function<String (int, int)> stringFromInt,
std::function<int (const String&)> intFromString,
int versionHintToUse)
: RangedAudioParameter (idToUse, nameToUse, labelToUse, Category::genericParameter, versionHintToUse),
range ([minValue, maxValue]
{
NormalisableRange<float> rangeWithInterval { (float) minValue, (float) maxValue,
[] (float start, float end, float v) { return jlimit (start, end, v * (end - start) + start); },
[] (float start, float end, float v) { return jlimit (0.0f, 1.0f, (v - start) / (end - start)); },
[] (float start, float end, float v) { return (float) roundToInt (juce::jlimit (start, end, v)); } };
rangeWithInterval.interval = 1.0f;
return rangeWithInterval;
}()),
value ((float) def),
defaultValue (convertTo0to1 ((float) def)),
stringFromIntFunction (stringFromInt),
intFromStringFunction (intFromString)
const AudioParameterIntAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
range ([minValue, maxValue]
{
NormalisableRange<float> rangeWithInterval { (float) minValue, (float) maxValue,
[] (float start, float end, float v) { return jlimit (start, end, v * (end - start) + start); },
[] (float start, float end, float v) { return jlimit (0.0f, 1.0f, (v - start) / (end - start)); },
[] (float start, float end, float v) { return (float) roundToInt (juce::jlimit (start, end, v)); } };
rangeWithInterval.interval = 1.0f;
return rangeWithInterval;
}()),
value ((float) def),
defaultValue (convertTo0to1 ((float) def)),
stringFromIntFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [] (int v, int) { return String (v); }),
intFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [] (const String& text) { return text.getIntValue(); })
{
jassert (minValue < maxValue); // must have a non-zero range of values!
if (stringFromIntFunction == nullptr)
stringFromIntFunction = [] (int v, int) { return String (v); };
if (intFromStringFunction == nullptr)
intFromStringFunction = [] (const String& text) { return text.getIntValue(); };
}
AudioParameterInt::~AudioParameterInt()


+ 51
- 7
modules/juce_audio_processors/utilities/juce_AudioParameterInt.h View File

@@ -26,6 +26,13 @@
namespace juce
{
/** Properties of an AudioParameterInt.
@see AudioParameterInt(), RangedAudioParameterAttributes()
*/
class AudioParameterIntAttributes : public RangedAudioParameterAttributes<AudioParameterIntAttributes, int> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used as an
integer value with a given range.
@@ -39,11 +46,37 @@ class JUCE_API AudioParameterInt : public RangedAudioParameter
public:
/** Creates a AudioParameterInt with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterIntAttributes().withStringFromValueFunction ([] (auto x, auto) { return String (x); })
.withLabel ("things");
auto param = std::make_unique<AudioParameterInt> ("paramID", "Parameter Name", 0, 100, 50, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param minValue The minimum parameter value
@param maxValue The maximum parameter value
@param defaultValue The default value
@param attributes Optional characteristics
*/
AudioParameterInt (const ParameterID& parameterID,
const String& parameterName,
int minValue,
int maxValue,
int defaultValue,
const AudioParameterIntAttributes& attributes = {});
/** Creates a AudioParameterInt with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param minValue The minimum parameter value
@param maxValue The maximum parameter value
@param defaultValueIn The default value
@param parameterLabel An optional label for the parameter's value
@param stringFromInt An optional lambda function that converts a int
value to a string with a maximum length. This may
@@ -51,15 +84,26 @@ public:
@param intFromString An optional lambda function that parses a string
and converts it into an int. Some hosts use this
to allow users to type in parameter values.
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
AudioParameterInt (const String& parameterID, const String& parameterName,
int minValue, int maxValue,
int defaultValue,
const String& parameterLabel = String(),
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterInt (const ParameterID& parameterID,
const String& parameterName,
int minValue,
int maxValue,
int defaultValueIn,
const String& parameterLabel,
std::function<String (int value, int maximumStringLength)> stringFromInt = nullptr,
std::function<int (const String& text)> intFromString = nullptr,
int versionHint = 0);
std::function<int (const String& text)> intFromString = nullptr)
: AudioParameterInt (parameterID,
parameterName,
minValue,
maxValue,
defaultValueIn,
AudioParameterIntAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromInt))
.withValueFromStringFunction (std::move (intFromString)))
{
}
/** Destructor. */
~AudioParameterInt() override;


+ 9
- 8
modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.cpp View File

@@ -26,16 +26,17 @@
namespace juce
{
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const String& idToUse,
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const ParameterID& idToUse,
const String& nameToUse,
const String& labelToUse,
AudioProcessorParameter::Category categoryToUse,
int versionHintToUse)
: HostedAudioProcessorParameter (versionHintToUse),
paramID (idToUse),
const AudioProcessorParameterWithIDAttributes& attributes)
: HostedAudioProcessorParameter (idToUse.getVersionHint()),
paramID (idToUse.getParamID()),
name (nameToUse),
label (labelToUse),
category (categoryToUse)
label (attributes.getLabel()),
category (attributes.getCategory()),
meta (attributes.getMeta()),
automatable (attributes.getAutomatable()),
inverted (attributes.getInverted())
{
}


+ 117
- 6
modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h View File

@@ -26,6 +26,87 @@
namespace juce
{
/**
Combines a parameter ID and a version hint.
*/
class ParameterID
{
public:
ParameterID() = default;
/** Constructs an instance.
Note that this constructor implicitly converts from Strings and string-like types.
@param identifier A string that uniquely identifies a single parameter
@param versionHint Influences parameter ordering in Audio Unit plugins.
Used to provide backwards compatibility of Audio Unit plugins in
Logic and GarageBand.
@see AudioProcessorParameter(int)
*/
template <typename StringLike, typename = DisableIfSameOrDerived<ParameterID, StringLike>>
ParameterID (StringLike&& identifier, int versionHint = 0)
: paramID (std::forward<StringLike> (identifier)), version (versionHint) {}
/** @see AudioProcessorParameterWithID::paramID */
auto getParamID() const { return paramID; }
/** @see AudioProcessorParameter(int) */
auto getVersionHint() const { return version; }
private:
String paramID;
int version = 0;
};
/**
An instance of this class may be passed to the constructor of an AudioProcessorParameterWithID
to set optional characteristics of that parameter.
*/
class AudioProcessorParameterWithIDAttributes
{
using This = AudioProcessorParameterWithIDAttributes;
public:
using Category = AudioProcessorParameter::Category;
/** An optional label for the parameter's value */
JUCE_NODISCARD auto withLabel (String x) const { return withMember (*this, &This::label, std::move (x)); }
/** The semantics of this parameter */
JUCE_NODISCARD auto withCategory (Category x) const { return withMember (*this, &This::category, std::move (x)); }
/** @see AudioProcessorParameter::isMetaParameter() */
JUCE_NODISCARD auto withMeta (bool x) const { return withMember (*this, &This::meta, std::move (x)); }
/** @see AudioProcessorParameter::isAutomatable() */
JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (*this, &This::automatable, std::move (x)); }
/** @see AudioProcessorParameter::isOrientationInverted() */
JUCE_NODISCARD auto withInverted (bool x) const { return withMember (*this, &This::inverted, std::move (x)); }
/** An optional label for the parameter's value */
JUCE_NODISCARD auto getLabel() const { return label; }
/** The semantics of this parameter */
JUCE_NODISCARD auto getCategory() const { return category; }
/** @see AudioProcessorParameter::isMetaParameter() */
JUCE_NODISCARD auto getMeta() const { return meta; }
/** @see AudioProcessorParameter::isAutomatable() */
JUCE_NODISCARD auto getAutomatable() const { return automatable; }
/** @see AudioProcessorParameter::isOrientationInverted() */
JUCE_NODISCARD auto getInverted() const { return inverted; }
private:
String label;
Category category = AudioProcessorParameter::genericParameter;
bool meta = false, automatable = true, inverted = false;
};
//==============================================================================
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@@ -36,6 +117,26 @@ namespace juce
class JUCE_API AudioProcessorParameterWithID : public HostedAudioProcessorParameter
{
public:
/** The creation of this object requires providing a name and ID which will be constant for its lifetime.
Given that AudioProcessorParameterWithID is abstract, you'll probably call this constructor
from a derived class constructor, e.g.
@code
MyParameterType (String paramID, String name, String label, bool automatable)
: AudioProcessorParameterWithID (paramID, name, AudioProcessorParameterWithIDAttributes().withLabel (label)
.withAutomatable (automatable))
{
}
@endcode
@param parameterID Specifies the identifier, and optionally the parameter's version hint.
@param parameterName The user-facing parameter name.
@param attributes Other parameter properties.
*/
AudioProcessorParameterWithID (const ParameterID& parameterID,
const String& parameterName,
const AudioProcessorParameterWithIDAttributes& attributes = {});
/** The creation of this object requires providing a name and ID which will be
constant for its lifetime.
@@ -43,13 +144,18 @@ public:
@param parameterName The user-facing name of the parameter
@param parameterLabel An optional label for the parameter's value
@param parameterCategory The semantics of this parameter
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
AudioProcessorParameterWithID (const String& parameterID,
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioProcessorParameterWithID (const ParameterID& parameterID,
const String& parameterName,
const String& parameterLabel = {},
Category parameterCategory = AudioProcessorParameter::genericParameter,
int versionHint = 0);
const String& parameterLabel,
Category parameterCategory = AudioProcessorParameter::genericParameter)
: AudioProcessorParameterWithID (parameterID,
parameterName,
AudioProcessorParameterWithIDAttributes().withLabel (parameterLabel)
.withCategory (parameterCategory))
{
}
/** Provides access to the parameter's ID string. */
const String paramID;
@@ -67,9 +173,14 @@ public:
String getLabel() const override;
Category getCategory() const override;
String getParameterID() const override { return paramID; }
String getParameterID() const override { return paramID; }
bool isMetaParameter() const override { return meta; }
bool isAutomatable() const override { return automatable; }
bool isOrientationInverted() const override { return inverted; }
private:
bool meta = false, automatable = true, inverted = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterWithID)
};


+ 93
- 66
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp View File

@@ -27,42 +27,26 @@ namespace juce
{
//==============================================================================
AudioProcessorValueTreeState::Parameter::Parameter (const String& parameterID,
AudioProcessorValueTreeState::Parameter::Parameter (const ParameterID& parameterID,
const String& parameterName,
const String& labelText,
NormalisableRange<float> valueRange,
float defaultParameterValue,
std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter,
bool isAutomatableParameter,
bool isDiscrete,
AudioProcessorParameter::Category parameterCategory,
bool isBoolean,
int versionHintToUse)
const AudioProcessorValueTreeStateParameterAttributes& attributes)
: AudioParameterFloat (parameterID,
parameterName,
valueRange,
defaultParameterValue,
labelText,
parameterCategory,
valueToTextFunction == nullptr ? std::function<String (float v, int)>()
: [valueToTextFunction] (float v, int) { return valueToTextFunction (v); },
std::move (textToValueFunction),
versionHintToUse),
attributes.getAudioParameterFloatAttributes()),
unsnappedDefault (valueRange.convertTo0to1 (defaultParameterValue)),
metaParameter (isMetaParameter),
automatable (isAutomatableParameter),
discrete (isDiscrete),
boolean (isBoolean)
discrete (attributes.getDiscrete()),
boolean (attributes.getBoolean())
{
}
float AudioProcessorValueTreeState::Parameter::getDefaultValue() const { return unsnappedDefault; }
int AudioProcessorValueTreeState::Parameter::getNumSteps() const { return RangedAudioParameter::getNumSteps(); }
bool AudioProcessorValueTreeState::Parameter::isMetaParameter() const { return metaParameter; }
bool AudioProcessorValueTreeState::Parameter::isAutomatable() const { return automatable; }
bool AudioProcessorValueTreeState::Parameter::isDiscrete() const { return discrete; }
bool AudioProcessorValueTreeState::Parameter::isBoolean() const { return boolean; }
@@ -305,18 +289,21 @@ RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (const
AudioProcessorParameter::Category category,
bool isBooleanParameter)
{
auto attributes = AudioProcessorValueTreeStateParameterAttributes()
.withLabel (labelText)
.withStringFromValueFunction ([fn = std::move (valueToTextFunction)] (float v, int) { return fn (v); })
.withValueFromStringFunction (std::move (textToValueFunction))
.withMeta (isMetaParameter)
.withAutomatable (isAutomatableParameter)
.withDiscrete (isDiscreteParameter)
.withCategory (category)
.withBoolean (isBooleanParameter);
return createAndAddParameter (std::make_unique<Parameter> (paramID,
paramName,
labelText,
range,
defaultVal,
std::move (valueToTextFunction),
std::move (textToValueFunction),
isMetaParameter,
isAutomatableParameter,
isDiscreteParameter,
category,
isBooleanParameter));
std::move (attributes)));
}
RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (std::unique_ptr<RangedAudioParameter> param)
@@ -535,7 +522,7 @@ struct ParameterAdapterTests : public UnitTest
{
const auto test = [&] (NormalisableRange<float> range, float value)
{
AudioParameterFloat param ({}, {}, range, value, {});
AudioParameterFloat param ({}, {}, range, value);
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
@@ -550,7 +537,7 @@ struct ParameterAdapterTests : public UnitTest
{
const auto test = [&] (NormalisableRange<float> range, float value)
{
AudioParameterFloat param ({}, {}, range, {}, {});
AudioParameterFloat param ({}, {}, range, {});
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
adapter.setDenormalisedValue (value);
@@ -567,7 +554,7 @@ struct ParameterAdapterTests : public UnitTest
{
const auto test = [&] (NormalisableRange<float> range, float value, String expected)
{
AudioParameterFloat param ({}, {}, range, {}, {});
AudioParameterFloat param ({}, {}, range, {});
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
expectEquals (adapter.getTextForDenormalisedValue (value), expected);
@@ -583,7 +570,7 @@ struct ParameterAdapterTests : public UnitTest
{
const auto test = [&] (NormalisableRange<float> range, String text, float expected)
{
AudioParameterFloat param ({}, {}, range, {}, {});
AudioParameterFloat param ({}, {}, range, {});
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
expectEquals (adapter.getDenormalisedValueForText (text), expected);
@@ -623,6 +610,7 @@ private:
using Parameter = AudioProcessorValueTreeState::Parameter;
using ParameterGroup = AudioProcessorParameterGroup;
using ParameterLayout = AudioProcessorValueTreeState::ParameterLayout;
using Attributes = AudioProcessorValueTreeStateParameterAttributes;
class TestAudioProcessor : public AudioProcessor
{
@@ -679,8 +667,11 @@ public:
{
TestAudioProcessor proc;
proc.state.createAndAddParameter (std::make_unique<Parameter> (String(), String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
proc.state.createAndAddParameter (std::make_unique<Parameter> (
String(),
String(),
NormalisableRange<float>(),
0.0f));
expectEquals (proc.getParameters().size(), 1);
}
@@ -690,8 +681,11 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
expect (proc.state.getParameter (key) == param);
}
@@ -723,8 +717,12 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr, true));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f,
Attributes().withMeta (true)));
expect (param->isMetaParameter());
}
@@ -734,8 +732,12 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr, false, true));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f,
Attributes().withAutomatable (true)));
expect (param->isAutomatable());
}
@@ -745,8 +747,12 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr, false, false, true));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f,
Attributes().withDiscrete (true)));
expect (param->isDiscrete());
}
@@ -756,9 +762,12 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr, false, false, false,
AudioProcessorParameter::Category::inputMeter));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f,
Attributes().withCategory (AudioProcessorParameter::Category::inputMeter)));
expect (param->category == AudioProcessorParameter::Category::inputMeter);
}
@@ -768,9 +777,12 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr, false, false, false,
AudioProcessorParameter::Category::genericParameter, true));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f,
Attributes().withBoolean (true)));
expect (param->isBoolean());
}
@@ -790,11 +802,17 @@ public:
{
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
expectEquals (proc.getParameters().size(), 1);
expect (proc.getParameters().getFirst() == param);
@@ -804,8 +822,11 @@ public:
{
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
const auto value = 0.5f;
param->setValueNotifyingHost (value);
@@ -822,11 +843,8 @@ public:
proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
String(),
NormalisableRange<float> (0.0f, 100.0f, 10.0f),
value,
nullptr,
nullptr));
value));
expectEquals (proc.state.getRawParameterValue (key)->load(), value);
}
@@ -836,8 +854,11 @@ public:
Listener listener;
TestAudioProcessor proc;
const auto key = "id";
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
const auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
proc.state.addParameterListener (key, &listener);
const auto value = 0.5f;
@@ -893,8 +914,11 @@ public:
TestAudioProcessor proc;
const auto key = "id";
const auto initialValue = 0.2f;
auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
initialValue, nullptr, nullptr));
auto param = proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
initialValue));
proc.state.state = ValueTree { "state" };
auto value = proc.state.getParameterAsValue (key);
@@ -928,8 +952,11 @@ public:
Listener listener;
TestAudioProcessor proc;
const auto key = "id";
proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
0.0f, nullptr, nullptr));
proc.state.createAndAddParameter (std::make_unique<Parameter> (
key,
String(),
NormalisableRange<float>(),
0.0f));
proc.state.addParameterListener (key, &listener);
proc.state.state = ValueTree { "state" };


+ 105
- 11
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h View File

@@ -26,6 +26,60 @@
namespace juce
{
/** Advanced properties of an AudioProcessorValueTreeState::Parameter.
The members here have the same meaning as the similarly-named member functions of
AudioParameterFloatAttributes.
@see AudioParameterFloatAttributes, RangedAudioParameterAttributes
*/
class AudioProcessorValueTreeStateParameterAttributes
{
using This = AudioProcessorValueTreeStateParameterAttributes;
using StringFromValue = AudioParameterFloatAttributes::StringFromValue;
using ValueFromString = AudioParameterFloatAttributes::ValueFromString;
using Category = AudioParameterFloatAttributes::Category;
public:
/** @see RangedAudioParameterAttributes::withStringFromValueFunction() */
JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x) const { return withMember (*this, &This::attributes, attributes.withStringFromValueFunction (std::move (x))); }
/** @see RangedAudioParameterAttributes::withValueFromStringFunction() */
JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x) const { return withMember (*this, &This::attributes, attributes.withValueFromStringFunction (std::move (x))); }
/** @see RangedAudioParameterAttributes::withLabel() */
JUCE_NODISCARD auto withLabel (String x) const { return withMember (*this, &This::attributes, attributes.withLabel (std::move (x))); }
/** @see RangedAudioParameterAttributes::withCategory() */
JUCE_NODISCARD auto withCategory (Category x) const { return withMember (*this, &This::attributes, attributes.withCategory (std::move (x))); }
/** @see RangedAudioParameterAttributes::withMeta() */
JUCE_NODISCARD auto withMeta (bool x) const { return withMember (*this, &This::attributes, attributes.withMeta (std::move (x))); }
/** @see RangedAudioParameterAttributes::withAutomatable() */
JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (*this, &This::attributes, attributes.withAutomatable (std::move (x))); }
/** @see RangedAudioParameterAttributes::withInverted() */
JUCE_NODISCARD auto withInverted (bool x) const { return withMember (*this, &This::attributes, attributes.withInverted (std::move (x))); }
/** Pass 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous.
Using an AudioParameterChoice or AudioParameterInt might be a better choice than setting this flag.
*/
JUCE_NODISCARD auto withDiscrete (bool x) const { return withMember (*this, &This::discrete, std::move (x)); }
/** Pass 'true' if this parameter only has two valid states.
Using an AudioParameterBool might be a better choice than setting this flag.
*/
JUCE_NODISCARD auto withBoolean (bool x) const { return withMember (*this, &This::boolean, std::move (x)); }
/** @returns all attributes that might also apply to an AudioParameterFloat */
JUCE_NODISCARD const auto& getAudioParameterFloatAttributes() const { return attributes; }
/** @returns 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous. */
JUCE_NODISCARD const auto& getDiscrete() const { return discrete; }
/** @returns 'true' if this parameter only has two valid states. */
JUCE_NODISCARD const auto& getBoolean() const { return boolean; }
private:
AudioParameterFloatAttributes attributes;
bool discrete = false, boolean = false;
};
/**
This class contains a ValueTree that is used to manage an AudioProcessor's entire state.
@@ -398,25 +452,65 @@ public:
class Parameter final : public AudioParameterFloat
{
public:
Parameter (const String& parameterID,
/** Constructs a parameter instance.
Example usage:
@code
using Parameter = AudioProcessorValueTreeState::Parameter;
using Attributes = AudioProcessorValueTreeStateParameterAttributes;
auto parameter = std::make_unique<Parameter> (ParameterID { "uniqueID", 1 },
"Name",
NormalisableRange<float> { 0.0f, 100.0f },
50.0f,
Attributes().withStringFromValueFunction (myStringFromValueFunction)
.withValueFromStringFunction (myValueFromStringFunction)
.withLabel ("%"));
@endcode
@param parameterID The globally-unique identifier of this parameter
@param parameterName The user-facing name of this parameter
@param valueRange The valid range of values for this parameter
@param defaultValue The initial parameter value
@param attributes Further advanced settings to customise the behaviour of this parameter
*/
Parameter (const ParameterID& parameterID,
const String& parameterName,
const String& labelText,
NormalisableRange<float> valueRange,
float defaultValue,
const AudioProcessorValueTreeStateParameterAttributes& attributes = {});
[[deprecated ("Prefer the signature taking an Attributes argument")]]
Parameter (const ParameterID& parameterID,
const String& parameterName,
const String& labelText,
NormalisableRange<float> valueRange,
float defaultParameterValue,
std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter = false,
bool isAutomatableParameter = true,
bool isDiscrete = false,
AudioProcessorParameter::Category parameterCategory = AudioProcessorParameter::genericParameter,
bool isBoolean = false,
int versionHint = 0);
bool isMetaParameter,
bool isAutomatableParameter,
bool isDiscrete,
AudioProcessorParameter::Category parameterCategory,
bool isBoolean)
: Parameter (parameterID,
parameterName,
valueRange,
defaultParameterValue,
AudioProcessorValueTreeStateParameterAttributes().withLabel (labelText)
.withStringFromValueFunction ([valueToTextFunction] (float v, int) { return valueToTextFunction (v); })
.withValueFromStringFunction (std::move (textToValueFunction))
.withMeta (isMetaParameter)
.withAutomatable (isAutomatableParameter)
.withDiscrete (isDiscrete)
.withCategory (parameterCategory)
.withBoolean (isBoolean))
{
}
float getDefaultValue() const override;
int getNumSteps() const override;
bool isMetaParameter() const override;
bool isAutomatable() const override;
bool isDiscrete() const override;
bool isBoolean() const override;
@@ -426,7 +520,7 @@ public:
std::function<void()> onValueChanged;
const float unsnappedDefault;
const bool metaParameter, automatable, discrete, boolean;
const bool discrete, boolean;
std::atomic<float> lastValue { -1.0f };
friend class AudioProcessorValueTreeState::ParameterAdapter;


+ 61
- 9
modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h View File

@@ -26,6 +26,67 @@
namespace juce
{
/**
@internal
Holds common attributes of audio parameters.
CRTP is used here because we want the Attributes types for each parameter
(Float, Bool, Choice, Int) to be distinct and extensible in the future.
i.e. the identifiers AudioParameterFloatAttributes and RangedAudioParameterAttributes<float>
should not be interchangable because we might need to add float-specific attributes in
the future. Users should not refer directly to RangedAudioParameterAttributes.
*/
template <typename Derived, typename Value>
class RangedAudioParameterAttributes
{
using This = RangedAudioParameterAttributes;
public:
using Category = AudioProcessorParameter::Category;
using StringFromValue = std::function<String (Value, int)>;
using ValueFromString = std::function<Value (const String&)>;
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */
JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x) const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */
JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x) const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }
/** See AudioProcessorParameterWithIDAttributes::withLabel() */
JUCE_NODISCARD auto withLabel (String x) const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }
/** See AudioProcessorParameterWithIDAttributes::withCategory() */
JUCE_NODISCARD auto withCategory (Category x) const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }
/** See AudioProcessorParameter::isMetaParameter() */
JUCE_NODISCARD auto withMeta (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }
/** See AudioProcessorParameter::isAutomatable() */
JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }
/** See AudioProcessorParameter::isOrientationInverted() */
JUCE_NODISCARD auto withInverted (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */
JUCE_NODISCARD const auto& getStringFromValueFunction() const { return stringFromValue; }
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */
JUCE_NODISCARD const auto& getValueFromStringFunction() const { return valueFromString; }
/** Gets attributes that would also apply to an AudioProcessorParameterWithID */
JUCE_NODISCARD const auto& getAudioProcessorParameterWithIDAttributes() const { return attributes; }
private:
auto& asDerived() const { return *static_cast<const Derived*> (this); }
AudioProcessorParameterWithIDAttributes attributes;
StringFromValue stringFromValue;
ValueFromString valueFromString;
};
//==============================================================================
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@@ -36,15 +97,6 @@ namespace juce
class JUCE_API RangedAudioParameter : public AudioProcessorParameterWithID
{
public:
/** The creation of this object requires providing a name and ID which will be
constant for its lifetime.
@param parameterID Used to uniquely identify the parameter
@param parameterName The user-facing name of the parameter
@param parameterLabel An optional label for the parameter's value
@param parameterCategory The semantics of this parameter
@param versionHint See AudioProcessorParameter::getVersionHint()
*/
using AudioProcessorParameterWithID::AudioProcessorParameterWithID;
/** Returns the range of values that the parameter can take. */


+ 16
- 0
modules/juce_core/misc/juce_Functional.h View File

@@ -69,4 +69,20 @@ struct NullCheckedInvocation
static void invoke (std::nullptr_t, Args&&...) {}
};
/** Can be used to disable template constructors that would otherwise cause ambiguity with
compiler-generated copy and move constructors.
Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
*/
template <typename A, typename B>
using DisableIfSameOrDerived = typename std::enable_if_t<! std::is_base_of<A, std::remove_reference_t<B>>::value>;
/** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */
template <typename Object, typename OtherObject, typename Member>
Object withMember (Object copy, Member OtherObject::* member, Member&& value)
{
copy.*member = std::forward<Member> (value);
return copy;
}
} // namespace juce

Loading…
Cancel
Save