mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Allowed an AudioProcessorValueTreeState to manage RangedAudioParameter subclasses
This commit is contained in:
parent
768139a298
commit
1f63493031
14 changed files with 1249 additions and 389 deletions
|
|
@ -4,6 +4,39 @@ JUCE breaking changes
|
|||
Develop
|
||||
=======
|
||||
|
||||
Change
|
||||
------
|
||||
The AudioProcessorValueTreeState::createAndAddParameter function has been
|
||||
deprecated.
|
||||
|
||||
Possible Issues
|
||||
---------------
|
||||
Deprecation warnings will be seen when compiling code which uses this function
|
||||
and eventually builds will fail when it is later removed from the API.
|
||||
|
||||
Workaround
|
||||
----------
|
||||
Previous calls to
|
||||
|
||||
createAndAddParameter (paramID, paramName, ...);
|
||||
|
||||
can be directly replaced with
|
||||
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
createAndAddParameter (std::make_unique<Parameter> (paramID, paramName, ...));
|
||||
|
||||
but an even better approach is to use the new AudioProcessorValueTreeState
|
||||
constructor where you can pass both RangedAudioParameters and
|
||||
AudioProcessorParameterGroups of RangedAudioParameters to the
|
||||
AudioProcessorValueTreeState and initialise the ValueTree simultaneously.
|
||||
|
||||
Rationale
|
||||
---------
|
||||
The new createAndAddParameter method is much more flexible and enables any
|
||||
parameter types derived from RangedAudioParameter to be managed by the
|
||||
AudioProcessorValueTreeState.
|
||||
|
||||
|
||||
Change
|
||||
------
|
||||
The Projucer's per-exporter Android SDK/NDK path options have been removed.
|
||||
|
|
@ -15,7 +48,7 @@ Projects that previously used these fields may no longer build.
|
|||
Workaround
|
||||
----------
|
||||
Use the Projucer's global paths settings to point to these directories, either
|
||||
by opening the "Projucer/File->Global Paths..." menu item or using the
|
||||
by opening the "Projucer/File->Global Paths..." menu item or using the
|
||||
"--set-global-search-path" command-line option.
|
||||
|
||||
Rationale
|
||||
|
|
|
|||
|
|
@ -175,19 +175,14 @@ public:
|
|||
//==============================================================================
|
||||
JuceDemoPluginAudioProcessor()
|
||||
: AudioProcessor (getBusesProperties()),
|
||||
state (*this, nullptr)
|
||||
state (*this, nullptr, "state",
|
||||
{ std::make_unique<AudioParameterFloat> ("gain", "Gain", NormalisableRange<float> (0.0f, 1.0f), 0.9f),
|
||||
std::make_unique<AudioParameterFloat> ("delay", "Delay Feedback", NormalisableRange<float> (0.0f, 1.0f), 0.5f) })
|
||||
{
|
||||
lastPosInfo.resetToDefault();
|
||||
|
||||
// This creates our parameters
|
||||
state.createAndAddParameter ("gain", "Gain", {}, {}, 0.9f, {}, {});
|
||||
state.createAndAddParameter ("delay", "Delay Feedback", {}, {}, 0.5f, {}, {});
|
||||
|
||||
state.state = ValueTree ("state", {},
|
||||
{
|
||||
// add a sub-tree to store the state of our UI
|
||||
{"uiState", {{"width", 400}, {"height", 200}}, {}}
|
||||
});
|
||||
// Add a sub-tree to store the state of our UI
|
||||
state.state.addChild ({ "uiState", { { "width", 400 }, { "height", 200 } }, {} }, -1, nullptr);
|
||||
|
||||
initialiseSynth();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,17 +152,9 @@ public:
|
|||
: AudioProcessor (BusesProperties()
|
||||
.withInput ("Input", AudioChannelSet::stereo(), true)
|
||||
.withOutput ("Output", AudioChannelSet::stereo(), true)),
|
||||
parameters (*this, nullptr)
|
||||
parameters (*this, nullptr, "InterAppAudioEffect",
|
||||
{ std::make_unique<AudioParameterFloat> ("gain", "Gain", NormalisableRange<float> (0.0f, 1.0f), 1.0f / 3.14f) })
|
||||
{
|
||||
parameters.createAndAddParameter ("gain",
|
||||
"Gain",
|
||||
{},
|
||||
NormalisableRange<float> (0.0f, 1.0f),
|
||||
(float) (1.0 / 3.14),
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
parameters.state = ValueTree (Identifier ("InterAppAudioEffect"));
|
||||
}
|
||||
|
||||
~IAAEffectProcessor() {}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
#include "juce_audio_processors.h"
|
||||
#include <juce_gui_extra/juce_gui_extra.h>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC
|
||||
#if JUCE_SUPPORT_CARBON \
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@
|
|||
#include "scanning/juce_PluginDirectoryScanner.h"
|
||||
#include "scanning/juce_PluginListComponent.h"
|
||||
#include "utilities/juce_AudioProcessorParameterWithID.h"
|
||||
#include "utilities/juce_RangedAudioParameter.h"
|
||||
#include "utilities/juce_AudioParameterFloat.h"
|
||||
#include "utilities/juce_AudioParameterInt.h"
|
||||
#include "utilities/juce_AudioParameterBool.h"
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace juce
|
|||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterBool : public AudioProcessorParameterWithID
|
||||
class JUCE_API AudioParameterBool : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterBool with the specified parameters.
|
||||
|
|
@ -60,12 +60,16 @@ public:
|
|||
|
||||
/** Returns the parameter's current boolean value. */
|
||||
bool get() const noexcept { return value >= 0.5f; }
|
||||
|
||||
/** Returns the parameter's current boolean value. */
|
||||
operator bool() const noexcept { return get(); }
|
||||
|
||||
/** Changes the parameter's current value to a new boolean. */
|
||||
AudioParameterBool& operator= (bool newValue);
|
||||
|
||||
/** Returns the range of values that the parameter can take. */
|
||||
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
|
||||
|
||||
protected:
|
||||
/** Override this method if you are interested in receiving callbacks
|
||||
when the parameter value changes.
|
||||
|
|
@ -83,6 +87,7 @@ private:
|
|||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
const NormalisableRange<float> range { 0.0f, 1.0f, 1.0f };
|
||||
float value;
|
||||
const float defaultValue;
|
||||
std::function<String (bool, int)> stringFromBoolFunction;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace juce
|
|||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterChoice : public AudioProcessorParameterWithID
|
||||
class JUCE_API AudioParameterChoice : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterChoice with the specified parameters.
|
||||
|
|
@ -64,17 +64,22 @@ public:
|
|||
|
||||
/** Returns the current index of the selected item. */
|
||||
int getIndex() const noexcept { return roundToInt (value); }
|
||||
|
||||
/** Returns the current index of the selected item. */
|
||||
operator int() const noexcept { return getIndex(); }
|
||||
|
||||
/** Returns the name of the currently selected item. */
|
||||
String getCurrentChoiceName() const noexcept { return choices[getIndex()]; }
|
||||
|
||||
/** Returns the name of the currently selected item. */
|
||||
operator String() const noexcept { return getCurrentChoiceName(); }
|
||||
|
||||
/** Changes the selected item to a new index. */
|
||||
AudioParameterChoice& operator= (int newValue);
|
||||
|
||||
/** Returns the range of values that the parameter can take. */
|
||||
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
|
||||
|
||||
/** Provides access to the list of choices that this parameter is working with. */
|
||||
const StringArray choices;
|
||||
|
||||
|
|
@ -94,12 +99,8 @@ private:
|
|||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
int limitRange (int) const noexcept;
|
||||
float convertTo0to1 (int) const noexcept;
|
||||
int convertFrom0to1 (float) const noexcept;
|
||||
|
||||
const NormalisableRange<float> range;
|
||||
float value;
|
||||
const int maxIndex;
|
||||
const float defaultValue;
|
||||
std::function<String (int, int)> stringFromIndexFunction;
|
||||
std::function<int (const String&)> indexFromStringFunction;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace juce
|
|||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterFloat : public AudioProcessorParameterWithID
|
||||
class JUCE_API AudioParameterFloat : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterFloat with the specified parameters.
|
||||
|
|
@ -53,7 +53,8 @@ public:
|
|||
converts it into a non-normalised value. Some hosts use
|
||||
this to allow users to type in parameter values.
|
||||
*/
|
||||
AudioParameterFloat (const String& parameterID, const String& name,
|
||||
AudioParameterFloat (const String& parameterID,
|
||||
const String& name,
|
||||
NormalisableRange<float> normalisableRange,
|
||||
float defaultValue,
|
||||
const String& label = String(),
|
||||
|
|
@ -66,7 +67,8 @@ public:
|
|||
For control over skew factors, you can use the other
|
||||
constructor and provide a NormalisableRange.
|
||||
*/
|
||||
AudioParameterFloat (String parameterID, String name,
|
||||
AudioParameterFloat (String parameterID,
|
||||
String name,
|
||||
float minValue,
|
||||
float maxValue,
|
||||
float defaultValue);
|
||||
|
|
@ -76,12 +78,16 @@ public:
|
|||
|
||||
/** Returns the parameter's current value. */
|
||||
float get() const noexcept { return value; }
|
||||
|
||||
/** Returns the parameter's current value. */
|
||||
operator float() const noexcept { return value; }
|
||||
|
||||
/** Changes the parameter's current value. */
|
||||
AudioParameterFloat& operator= (float newValue);
|
||||
|
||||
/** Returns the range of values that the parameter can take. */
|
||||
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
|
||||
|
||||
/** Provides access to the parameter's range. */
|
||||
NormalisableRange<float> range;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace juce
|
|||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterInt : public AudioProcessorParameterWithID
|
||||
class JUCE_API AudioParameterInt : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterInt with the specified parameters.
|
||||
|
|
@ -65,6 +65,7 @@ public:
|
|||
|
||||
/** Returns the parameter's current value as an integer. */
|
||||
int get() const noexcept { return roundToInt (value); }
|
||||
|
||||
/** Returns the parameter's current value as an integer. */
|
||||
operator int() const noexcept { return get(); }
|
||||
|
||||
|
|
@ -74,7 +75,10 @@ public:
|
|||
AudioParameterInt& operator= (int newValue);
|
||||
|
||||
/** Returns the parameter's range. */
|
||||
Range<int> getRange() const noexcept { return Range<int> (minValue, maxValue); }
|
||||
Range<int> getRange() const noexcept { return { (int) getNormalisableRange().start, (int) getNormalisableRange().end }; }
|
||||
|
||||
/** Returns the range of values that the parameter can take. */
|
||||
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
|
||||
|
||||
protected:
|
||||
/** Override this method if you are interested in receiving callbacks
|
||||
|
|
@ -91,11 +95,7 @@ private:
|
|||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
int limitRange (int) const noexcept;
|
||||
float convertTo0to1 (int) const noexcept;
|
||||
int convertFrom0to1 (float) const noexcept;
|
||||
|
||||
const int minValue, maxValue, rangeOfValues;
|
||||
const NormalisableRange<float> range;
|
||||
float value;
|
||||
const float defaultValue;
|
||||
std::function<String (int, int)> stringFromIntFunction;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace juce
|
|||
class JUCE_API AudioProcessorParameterWithID : public AudioProcessorParameter
|
||||
{
|
||||
public:
|
||||
/** Creation of this object requires providing a name and ID which will be
|
||||
/** The creation of this object requires providing a name and ID which will be
|
||||
constant for its lifetime.
|
||||
*/
|
||||
AudioProcessorParameterWithID (const String& parameterID,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ AudioParameterFloat::AudioParameterFloat (const String& idToUse, const String& n
|
|||
const String& labelToUse, Category categoryToUse,
|
||||
std::function<String (float, int)> stringFromValue,
|
||||
std::function<float (const String&)> valueFromString)
|
||||
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse, categoryToUse),
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse, categoryToUse),
|
||||
range (r), value (def), defaultValue (def),
|
||||
stringFromValueFunction (stringFromValue),
|
||||
valueFromStringFunction (valueFromString)
|
||||
|
|
@ -71,32 +71,36 @@ AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue,
|
|||
|
||||
AudioParameterFloat::~AudioParameterFloat() {}
|
||||
|
||||
float AudioParameterFloat::getValue() const { return range.convertTo0to1 (value); }
|
||||
void AudioParameterFloat::setValue (float newValue) { value = range.convertFrom0to1 (newValue); valueChanged (get()); }
|
||||
float AudioParameterFloat::getDefaultValue() const { return range.convertTo0to1 (defaultValue); }
|
||||
float AudioParameterFloat::getValue() const { return convertTo0to1 (value); }
|
||||
void AudioParameterFloat::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (get()); }
|
||||
float AudioParameterFloat::getDefaultValue() const { return convertTo0to1 (defaultValue); }
|
||||
int AudioParameterFloat::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
|
||||
String AudioParameterFloat::getText (float v, int length) const { return stringFromValueFunction (range.convertFrom0to1 (v), length); }
|
||||
float AudioParameterFloat::getValueForText (const String& text) const { return range.convertTo0to1 (valueFromStringFunction (text)); }
|
||||
String AudioParameterFloat::getText (float v, int length) const { return stringFromValueFunction (convertFrom0to1 (v), length); }
|
||||
float AudioParameterFloat::getValueForText (const String& text) const { return convertTo0to1 (valueFromStringFunction (text)); }
|
||||
void AudioParameterFloat::valueChanged (float) {}
|
||||
|
||||
AudioParameterFloat& AudioParameterFloat::operator= (float newValue)
|
||||
{
|
||||
if (value != newValue)
|
||||
setValueNotifyingHost (range.convertTo0to1 (newValue));
|
||||
setValueNotifyingHost (convertTo0to1 (newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameToUse,
|
||||
int mn, int mx, int def,
|
||||
int minValue, int maxValue, int def,
|
||||
const String& labelToUse,
|
||||
std::function<String (int, int)> stringFromInt,
|
||||
std::function<int (const String&)> intFromString)
|
||||
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
|
||||
minValue (mn), maxValue (mx), rangeOfValues (maxValue - minValue),
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse),
|
||||
range ((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)); }),
|
||||
value ((float) def),
|
||||
defaultValue (convertTo0to1 (def)),
|
||||
defaultValue (convertTo0to1 ((float) def)),
|
||||
stringFromIntFunction (stringFromInt),
|
||||
intFromStringFunction (intFromString)
|
||||
{
|
||||
|
|
@ -111,22 +115,18 @@ AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameT
|
|||
|
||||
AudioParameterInt::~AudioParameterInt() {}
|
||||
|
||||
int AudioParameterInt::limitRange (int v) const noexcept { return jlimit (minValue, maxValue, v); }
|
||||
float AudioParameterInt::convertTo0to1 (int v) const noexcept { return (limitRange (v) - minValue) / (float) rangeOfValues; }
|
||||
int AudioParameterInt::convertFrom0to1 (float v) const noexcept { return limitRange (roundToInt ((v * (float) rangeOfValues) + minValue)); }
|
||||
|
||||
float AudioParameterInt::getValue() const { return convertTo0to1 (roundToInt (value)); }
|
||||
void AudioParameterInt::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); valueChanged (get()); }
|
||||
float AudioParameterInt::getValue() const { return convertTo0to1 (value); }
|
||||
void AudioParameterInt::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (get()); }
|
||||
float AudioParameterInt::getDefaultValue() const { return defaultValue; }
|
||||
int AudioParameterInt::getNumSteps() const { return rangeOfValues + 1; }
|
||||
float AudioParameterInt::getValueForText (const String& text) const { return convertTo0to1 (intFromStringFunction (text)); }
|
||||
String AudioParameterInt::getText (float v, int length) const { return stringFromIntFunction (convertFrom0to1 (v), length); }
|
||||
int AudioParameterInt::getNumSteps() const { return ((int) getNormalisableRange().getRange().getLength()) + 1; }
|
||||
float AudioParameterInt::getValueForText (const String& text) const { return convertTo0to1 ((float) intFromStringFunction (text)); }
|
||||
String AudioParameterInt::getText (float v, int length) const { return stringFromIntFunction ((int) convertFrom0to1 (v), length); }
|
||||
void AudioParameterInt::valueChanged (int) {}
|
||||
|
||||
AudioParameterInt& AudioParameterInt::operator= (int newValue)
|
||||
{
|
||||
if (get() != newValue)
|
||||
setValueNotifyingHost (convertTo0to1 (newValue));
|
||||
setValueNotifyingHost (convertTo0to1 ((float) newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nam
|
|||
bool def, const String& labelToUse,
|
||||
std::function<String (bool, int)> stringFromBool,
|
||||
std::function<bool (const String&)> boolFromString)
|
||||
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse),
|
||||
value (def ? 1.0f : 0.0f),
|
||||
defaultValue (value),
|
||||
stringFromBoolFunction (stringFromBool),
|
||||
|
|
@ -209,10 +209,13 @@ AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String&
|
|||
const StringArray& c, int def, const String& labelToUse,
|
||||
std::function<String (int, int)> stringFromIndex,
|
||||
std::function<int (const String&)> indexFromString)
|
||||
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse), choices (c),
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse), choices (c),
|
||||
range (0.0f, choices.size() - 1.0f,
|
||||
[](float, float end, float v) { return jlimit (0.0f, end, v * end); },
|
||||
[](float, float end, float v) { return jlimit (0.0f, 1.0f, v / end); },
|
||||
[](float start, float end, float v) { return (float) roundToInt (juce::jlimit (start, end, v)); }),
|
||||
value ((float) def),
|
||||
maxIndex (choices.size() - 1),
|
||||
defaultValue (convertTo0to1 (def)),
|
||||
defaultValue (convertTo0to1 ((float) def)),
|
||||
stringFromIndexFunction (stringFromIndex),
|
||||
indexFromStringFunction (indexFromString)
|
||||
{
|
||||
|
|
@ -227,25 +230,108 @@ AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String&
|
|||
|
||||
AudioParameterChoice::~AudioParameterChoice() {}
|
||||
|
||||
int AudioParameterChoice::limitRange (int v) const noexcept { return jlimit (0, maxIndex, v); }
|
||||
float AudioParameterChoice::convertTo0to1 (int v) const noexcept { return jlimit (0.0f, 1.0f, v / (float) maxIndex); }
|
||||
int AudioParameterChoice::convertFrom0to1 (float v) const noexcept { return limitRange (roundToInt (v * (float) maxIndex)); }
|
||||
|
||||
float AudioParameterChoice::getValue() const { return convertTo0to1 (roundToInt (value)); }
|
||||
void AudioParameterChoice::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); valueChanged (getIndex()); }
|
||||
float AudioParameterChoice::getValue() const { return convertTo0to1 (value); }
|
||||
void AudioParameterChoice::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (getIndex()); }
|
||||
float AudioParameterChoice::getDefaultValue() const { return defaultValue; }
|
||||
int AudioParameterChoice::getNumSteps() const { return choices.size(); }
|
||||
bool AudioParameterChoice::isDiscrete() const { return true; }
|
||||
float AudioParameterChoice::getValueForText (const String& text) const { return convertTo0to1 (indexFromStringFunction (text)); }
|
||||
String AudioParameterChoice::getText (float v, int length) const { return stringFromIndexFunction (convertFrom0to1 (v), length); }
|
||||
float AudioParameterChoice::getValueForText (const String& text) const { return convertTo0to1 ((float) indexFromStringFunction (text)); }
|
||||
String AudioParameterChoice::getText (float v, int length) const { return stringFromIndexFunction ((int) convertFrom0to1 (v), length); }
|
||||
void AudioParameterChoice::valueChanged (int) {}
|
||||
|
||||
AudioParameterChoice& AudioParameterChoice::operator= (int newValue)
|
||||
{
|
||||
if (getIndex() != newValue)
|
||||
setValueNotifyingHost (convertTo0to1 (newValue));
|
||||
setValueNotifyingHost (convertTo0to1 ((float) newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
static struct SpecialisedAudioParameterTests final : public UnitTest
|
||||
{
|
||||
SpecialisedAudioParameterTests() : UnitTest ("Specialised Audio Parameters", "AudioProcessor parameters") {}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("A choice parameter with three options switches at the correct points");
|
||||
{
|
||||
AudioParameterChoice choice ({}, {}, { "a", "b", "c" }, {});
|
||||
|
||||
choice.setValueNotifyingHost (0.0f);
|
||||
expectEquals (choice.getIndex(), 0);
|
||||
|
||||
choice.setValueNotifyingHost (0.2f);
|
||||
expectEquals (choice.getIndex(), 0);
|
||||
|
||||
choice.setValueNotifyingHost (0.3f);
|
||||
expectEquals (choice.getIndex(), 1);
|
||||
|
||||
choice.setValueNotifyingHost (0.7f);
|
||||
expectEquals (choice.getIndex(), 1);
|
||||
|
||||
choice.setValueNotifyingHost (0.8f);
|
||||
expectEquals (choice.getIndex(), 2);
|
||||
|
||||
choice.setValueNotifyingHost (1.0f);
|
||||
expectEquals (choice.getIndex(), 2);
|
||||
}
|
||||
|
||||
beginTest ("An int parameter with three options switches at the correct points");
|
||||
{
|
||||
AudioParameterInt intParam ({}, {}, 1, 3, 1);
|
||||
|
||||
intParam.setValueNotifyingHost (0.0f);
|
||||
expectEquals (intParam.get(), 1);
|
||||
|
||||
intParam.setValueNotifyingHost (0.2f);
|
||||
expectEquals (intParam.get(), 1);
|
||||
|
||||
intParam.setValueNotifyingHost (0.3f);
|
||||
expectEquals (intParam.get(), 2);
|
||||
|
||||
intParam.setValueNotifyingHost (0.7f);
|
||||
expectEquals (intParam.get(), 2);
|
||||
|
||||
intParam.setValueNotifyingHost (0.8f);
|
||||
expectEquals (intParam.get(), 3);
|
||||
|
||||
intParam.setValueNotifyingHost (1.0f);
|
||||
expectEquals (intParam.get(), 3);
|
||||
}
|
||||
|
||||
|
||||
beginTest ("Choice parameters handle out-of-bounds input");
|
||||
{
|
||||
AudioParameterChoice choiceParam ({}, {}, { "a", "b", "c" }, {});
|
||||
|
||||
choiceParam.setValueNotifyingHost (-0.5f);
|
||||
expectEquals (choiceParam.getIndex(), 0);
|
||||
|
||||
choiceParam.setValueNotifyingHost (1.5f);
|
||||
expectEquals (choiceParam.getIndex(), 2);
|
||||
}
|
||||
|
||||
beginTest ("Int parameters handle out-of-bounds input");
|
||||
{
|
||||
AudioParameterInt intParam ({}, {}, -1, 2, 0);
|
||||
|
||||
intParam.setValueNotifyingHost (-0.5f);
|
||||
expectEquals (intParam.get(), -1);
|
||||
|
||||
intParam.setValueNotifyingHost (1.5f);
|
||||
expectEquals (intParam.get(), 2);
|
||||
|
||||
intParam = -5;
|
||||
expectEquals (intParam.get(), -1);
|
||||
|
||||
intParam = 5;
|
||||
expectEquals (intParam.get(), 2);
|
||||
}
|
||||
}
|
||||
} specialisedAudioParameterTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,9 +28,9 @@ namespace juce
|
|||
{
|
||||
|
||||
/**
|
||||
This class contains a ValueTree which is used to manage an AudioProcessor's entire state.
|
||||
This class contains a ValueTree that is used to manage an AudioProcessor's entire state.
|
||||
|
||||
It has its own internal class of parameter object which are linked to values
|
||||
It has its own internal class of parameter object that is linked to values
|
||||
within its ValueTree, and which are each identified by a string ID.
|
||||
|
||||
You can get access to the underlying ValueTree object via the state member variable,
|
||||
|
|
@ -39,127 +39,231 @@ namespace juce
|
|||
It also provides some utility child classes for connecting parameters directly to
|
||||
GUI controls like sliders.
|
||||
|
||||
To use:
|
||||
The favoured constructor of this class takes a collection of RangedAudioParameters or
|
||||
AudioProcessorParameterGroups of RangedAudioParameters and adds them to the attached
|
||||
AudioProcessor directly.
|
||||
|
||||
The deprecated way of using this class is as follows:
|
||||
|
||||
1) Create an AudioProcessorValueTreeState, and give it some parameters using createAndAddParameter().
|
||||
2) Initialise the state member variable with a type name.
|
||||
|
||||
The deprecated constructor will be removed from the API in a future version of JUCE!
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioProcessorValueTreeState : private Timer,
|
||||
class JUCE_API AudioProcessorValueTreeState : private Timer,
|
||||
private ValueTree::Listener
|
||||
{
|
||||
public:
|
||||
/** Creates a state object for a given processor.
|
||||
//==============================================================================
|
||||
/** A class to contain a set of RangedAudioParameters and AudioProcessorParameterGroups
|
||||
containing RangedAudioParameters.
|
||||
|
||||
The UndoManager is optional and can be a nullptr.
|
||||
After creating your state object, you should add parameters with the
|
||||
createAndAddParameter() method. Note that each AudioProcessorValueTreeState
|
||||
should be attached to only one processor, and must have the same lifetime as the
|
||||
processor, as they will have dependencies on each other.
|
||||
This class is used in the AudioProcessorValueTreeState constructor to allow
|
||||
arbitrarily grouped RangedAudioParameters to be passed to an AudioProcessor.
|
||||
*/
|
||||
class JUCE_API ParameterLayout final
|
||||
{
|
||||
private:
|
||||
//==============================================================================
|
||||
template <typename It>
|
||||
using ValidIfIterator = decltype (std::next (std::declval<It>()));
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
template <typename... Items>
|
||||
ParameterLayout (std::unique_ptr<Items>... items) { add (std::move (items)...); }
|
||||
|
||||
template <typename It, typename = ValidIfIterator<It>>
|
||||
ParameterLayout (It begin, It end) { add (begin, end); }
|
||||
|
||||
template <typename... Items>
|
||||
void add (std::unique_ptr<Items>... items)
|
||||
{
|
||||
parameters.reserve (parameters.size() + sizeof... (items));
|
||||
|
||||
// We can replace this with some nicer code once generic lambdas become available. A
|
||||
// sequential context like an array initialiser is required to ensure we get the correct
|
||||
// order from the parameter pack.
|
||||
int unused[] { (parameters.emplace_back (MakeContents() (std::move (items))), 0)... };
|
||||
ignoreUnused (unused);
|
||||
}
|
||||
|
||||
template <typename It, typename = ValidIfIterator<It>>
|
||||
void add (It begin, It end)
|
||||
{
|
||||
parameters.reserve (parameters.size() + std::size_t (std::distance (begin, end)));
|
||||
std::transform (std::make_move_iterator (begin),
|
||||
std::make_move_iterator (end),
|
||||
std::back_inserter (parameters),
|
||||
MakeContents());
|
||||
}
|
||||
|
||||
ParameterLayout (const ParameterLayout& other) = delete;
|
||||
ParameterLayout (ParameterLayout&& other) noexcept { swap (other); }
|
||||
|
||||
ParameterLayout& operator= (const ParameterLayout& other) = delete;
|
||||
ParameterLayout& operator= (ParameterLayout&& other) noexcept { swap (other); return *this; }
|
||||
|
||||
void swap (ParameterLayout& other) noexcept { std::swap (other.parameters, parameters); }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct Visitor
|
||||
{
|
||||
virtual ~Visitor() = default;
|
||||
|
||||
// If you have a compiler error telling you that there is no matching
|
||||
// member function to call for 'visit', then you are probably attempting
|
||||
// to add a parameter that is not derived from RangedAudioParameter to
|
||||
// the AudioProcessorValueTreeState.
|
||||
virtual void visit (std::unique_ptr<RangedAudioParameter>) const = 0;
|
||||
virtual void visit (std::unique_ptr<AudioProcessorParameterGroup>) const = 0;
|
||||
};
|
||||
|
||||
struct ParameterStorageBase
|
||||
{
|
||||
virtual ~ParameterStorageBase() = default;
|
||||
virtual void accept (const Visitor& visitor) = 0;
|
||||
};
|
||||
|
||||
template <typename Contents>
|
||||
struct ParameterStorage : ParameterStorageBase
|
||||
{
|
||||
explicit ParameterStorage (std::unique_ptr<Contents> input) : contents (std::move (input)) {}
|
||||
|
||||
void accept (const Visitor& visitor) override { visitor.visit (std::move (contents)); }
|
||||
|
||||
std::unique_ptr<Contents> contents;
|
||||
};
|
||||
|
||||
struct MakeContents final
|
||||
{
|
||||
template <typename Item>
|
||||
std::unique_ptr<ParameterStorageBase> operator() (std::unique_ptr<Item> item) const
|
||||
{
|
||||
return std::unique_ptr<ParameterStorageBase> (new ParameterStorage<Item> (std::move (item)));
|
||||
}
|
||||
};
|
||||
|
||||
void add() {}
|
||||
|
||||
friend class AudioProcessorValueTreeState;
|
||||
|
||||
std::vector<std::unique_ptr<ParameterStorageBase>> parameters;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a state object for a given processor, and sets up all the parameters
|
||||
that will control that processor.
|
||||
|
||||
You should *not* assign a new ValueTree to the state, or call
|
||||
createAndAddParameter, after using this constructor.
|
||||
|
||||
Note that each AudioProcessorValueTreeState should be attached to only one
|
||||
processor, and must have the same lifetime as the processor, as they will
|
||||
have dependencies on each other.
|
||||
|
||||
The ParameterLayout parameter has a set of constructors that allow you to
|
||||
add multiple RangedAudioParameters and AudioProcessorParameterGroups containing
|
||||
RangedAudioParameters to the AudioProcessorValueTreeState inside this constructor.
|
||||
|
||||
@code
|
||||
YourAudioProcessor()
|
||||
: apvts (*this, &undoManager, "PARAMETERS",
|
||||
{ std::make_unique<AudioParameterFloat> ("a", "Parameter A", NormalisableRange<float> (-100.0f, 100.0f), 0),
|
||||
std::make_unique<AudioParameterInt> ("b", "Parameter B", 0, 5, 2) })
|
||||
@endcode
|
||||
|
||||
@param processorToConnectTo The Processor that will be managed by this object
|
||||
@param undoManagerToUse An optional UndoManager to use; pass nullptr if no UndoManager is required
|
||||
@param valueTreeType The identifier used to initialise the internal ValueTree
|
||||
@param parameterLayout An object that holds all parameters and parameter groups that the
|
||||
AudioProcessor should use.
|
||||
*/
|
||||
AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo,
|
||||
UndoManager* undoManagerToUse);
|
||||
UndoManager* undoManagerToUse,
|
||||
const juce::Identifier& valueTreeType,
|
||||
ParameterLayout parameterLayout);
|
||||
|
||||
/** This constructor is discouraged and will be deprecated in a future version of JUCE!
|
||||
|
||||
Creates a state object for a given processor.
|
||||
|
||||
The UndoManager is optional and can be a nullptr. After creating your state object,
|
||||
you should add parameters with the createAndAddParameter() method. Note that each
|
||||
AudioProcessorValueTreeState should be attached to only one processor, and must have
|
||||
the same lifetime as the processor, as they will have dependencies on each other.
|
||||
*/
|
||||
AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo, UndoManager* undoManagerToUse);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioProcessorValueTreeState();
|
||||
|
||||
/** Creates a new parameter object for controlling a parameter with the given ID.
|
||||
//==============================================================================
|
||||
/** This function is deprecated and will be removed in a future version of JUCE!
|
||||
|
||||
The parameter returned by this function should be added to the AudioProcessor
|
||||
managed by this AudioProcessorValueTreeState via AudioProcessor::addParameter
|
||||
or AudioProcessor::addParameterGroup.
|
||||
Previous calls to
|
||||
@code
|
||||
createAndAddParameter (paramID1, paramName1, ...);
|
||||
@endcode
|
||||
can be replaced with
|
||||
@code
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
createAndAddParameter (std::make_unique<Parameter> (paramID1, paramName1, ...));
|
||||
@endcode
|
||||
|
||||
@param parameterID A unique string ID for the new parameter
|
||||
@param parameterName The name that the parameter will return from AudioProcessorParameter::getName()
|
||||
@param labelText The label that the parameter will return from AudioProcessorParameter::getLabel()
|
||||
@param valueRange A mapping that will be used to determine the value range which this parameter uses
|
||||
@param defaultValue A default value for the parameter (in non-normalised units)
|
||||
@param valueToTextFunction A function that will convert a non-normalised value to a string for the
|
||||
AudioProcessorParameter::getText() method. This can be nullptr to use the
|
||||
default implementation
|
||||
@param textToValueFunction The inverse of valueToTextFunction
|
||||
@param isMetaParameter Set this value to true if this should be a meta parameter
|
||||
@param isAutomatableParameter Set this value to false if this parameter should not be automatable
|
||||
@param isDiscrete Set this value to true to make this parameter take discrete values in a host.
|
||||
@see AudioProcessorParameter::isDiscrete
|
||||
@param category Which category the parameter should use.
|
||||
@see AudioProcessorParameter::Category
|
||||
@param isBoolean Set this value to true to make this parameter appear as a boolean toggle in
|
||||
a hosts view of your plug-ins parameters
|
||||
@see AudioProcessorParameter::isBoolean
|
||||
However, a much better approach is to use the AudioProcessorValueTreeState
|
||||
constructor directly
|
||||
@code
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
YourAudioProcessor()
|
||||
: apvts (*this, &undoManager, "PARAMETERS", { std::make_unique<Parameter> (paramID1, paramName1, ...),
|
||||
std::make_unique<Parameter> (paramID2, paramName2, ...),
|
||||
... })
|
||||
@endcode
|
||||
|
||||
@returns the parameter object that was created
|
||||
*/
|
||||
std::unique_ptr<AudioProcessorParameterWithID> createParameter (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& labelText,
|
||||
NormalisableRange<float> valueRange,
|
||||
float defaultValue,
|
||||
std::function<String (float)> valueToTextFunction,
|
||||
std::function<float (const String&)> textToValueFunction,
|
||||
bool isMetaParameter = false,
|
||||
bool isAutomatableParameter = true,
|
||||
bool isDiscrete = false,
|
||||
AudioProcessorParameter::Category category
|
||||
= AudioProcessorParameter::genericParameter,
|
||||
bool isBoolean = false);
|
||||
|
||||
/** Creates and returns a new parameter object for controlling a parameter
|
||||
with the given ID.
|
||||
This function creates and returns a new parameter object for controlling a
|
||||
parameter with the given ID.
|
||||
|
||||
Calling this will create and add a special type of AudioProcessorParameter to the
|
||||
AudioProcessor to which this state is attached.
|
||||
|
||||
@param parameterID A unique string ID for the new parameter
|
||||
@param parameterName The name that the parameter will return from AudioProcessorParameter::getName()
|
||||
@param labelText The label that the parameter will return from AudioProcessorParameter::getLabel()
|
||||
@param valueRange A mapping that will be used to determine the value range which this parameter uses
|
||||
@param defaultValue A default value for the parameter (in non-normalised units)
|
||||
@param valueToTextFunction A function that will convert a non-normalised value to a string for the
|
||||
AudioProcessorParameter::getText() method. This can be nullptr to use the
|
||||
default implementation
|
||||
@param textToValueFunction The inverse of valueToTextFunction
|
||||
@param isMetaParameter Set this value to true if this should be a meta parameter
|
||||
@param isAutomatableParameter Set this value to false if this parameter should not be automatable
|
||||
@param isDiscrete Set this value to true to make this parameter take discrete values in a host.
|
||||
@see AudioProcessorParameter::isDiscrete
|
||||
@param category Which category the parameter should use.
|
||||
@see AudioProcessorParameter::Category
|
||||
@param isBoolean Set this value to true to make this parameter appear as a boolean toggle in
|
||||
a hosts view of your plug-ins parameters
|
||||
@see AudioProcessorParameter::isBoolean
|
||||
|
||||
@returns the parameter object that was created
|
||||
*/
|
||||
AudioProcessorParameterWithID* createAndAddParameter (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& labelText,
|
||||
NormalisableRange<float> valueRange,
|
||||
float defaultValue,
|
||||
std::function<String (float)> valueToTextFunction,
|
||||
std::function<float (const String&)> textToValueFunction,
|
||||
bool isMetaParameter = false,
|
||||
bool isAutomatableParameter = true,
|
||||
bool isDiscrete = false,
|
||||
AudioProcessorParameter::Category category
|
||||
= AudioProcessorParameter::genericParameter,
|
||||
bool isBoolean = false);
|
||||
JUCE_DEPRECATED (RangedAudioParameter* createAndAddParameter (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& labelText,
|
||||
NormalisableRange<float> valueRange,
|
||||
float defaultValue,
|
||||
std::function<String (float)> valueToTextFunction,
|
||||
std::function<float (const String&)> textToValueFunction,
|
||||
bool isMetaParameter = false,
|
||||
bool isAutomatableParameter = true,
|
||||
bool isDiscrete = false,
|
||||
AudioProcessorParameter::Category category = AudioProcessorParameter::genericParameter,
|
||||
bool isBoolean = false));
|
||||
|
||||
/** This function adds a parameter to the attached AudioProcessor and that parameter will
|
||||
be managed by this AudioProcessorValueTreeState object.
|
||||
*/
|
||||
RangedAudioParameter* createAndAddParameter (std::unique_ptr<RangedAudioParameter> parameter);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a parameter by its ID string. */
|
||||
AudioProcessorParameterWithID* getParameter (StringRef parameterID) const noexcept;
|
||||
RangedAudioParameter* getParameter (StringRef parameterID) const noexcept;
|
||||
|
||||
/** Returns a pointer to a floating point representation of a particular
|
||||
parameter which a realtime process can read to find out its current value.
|
||||
*/
|
||||
float* getRawParameterValue (StringRef parameterID) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** A listener class that can be attached to an AudioProcessorValueTreeState.
|
||||
Use AudioProcessorValueTreeState::addParameterListener() to register a callback.
|
||||
*/
|
||||
struct JUCE_API Listener
|
||||
{
|
||||
Listener();
|
||||
virtual ~Listener();
|
||||
virtual ~Listener() = default;
|
||||
|
||||
/** This callback method is called by the AudioProcessorValueTreeState when a parameter changes. */
|
||||
virtual void parameterChanged (const String& parameterID, float newValue) = 0;
|
||||
|
|
@ -171,12 +275,14 @@ public:
|
|||
/** Removes a callback that was previously added with addParameterCallback(). */
|
||||
void removeParameterListener (StringRef parameterID, Listener* listener);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a Value object that can be used to control a particular parameter. */
|
||||
Value getParameterAsValue (StringRef parameterID) const;
|
||||
|
||||
/** Returns the range that was set when the given parameter was created. */
|
||||
NormalisableRange<float> getParameterRange (StringRef parameterID) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a copy of the state value tree.
|
||||
|
||||
The AudioProcessorValueTreeState's ValueTree is updated internally on the
|
||||
|
|
@ -204,6 +310,7 @@ public:
|
|||
*/
|
||||
void replaceState (const ValueTree& newState);
|
||||
|
||||
//==============================================================================
|
||||
/** A reference to the processor with which this state is associated. */
|
||||
AudioProcessor& processor;
|
||||
|
||||
|
|
@ -219,6 +326,57 @@ public:
|
|||
/** Provides access to the undo manager that this object is using. */
|
||||
UndoManager* const undoManager;
|
||||
|
||||
//==============================================================================
|
||||
/** A parameter class that maintains backwards compatibility with deprecated
|
||||
AudioProcessorValueTreeState functionality.
|
||||
|
||||
Previous calls to
|
||||
@code
|
||||
createAndAddParameter (paramID1, paramName1, ...);
|
||||
@endcode
|
||||
can be replaced with
|
||||
@code
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
createAndAddParameter (std::make_unique<Parameter> (paramID1, paramName1, ...));
|
||||
@endcode
|
||||
|
||||
However, a much better approach is to use the AudioProcessorValueTreeState
|
||||
constructor directly
|
||||
@code
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
YourAudioProcessor()
|
||||
: apvts (*this, &undoManager, "PARAMETERS", { std::make_unique<Parameter> (paramID1, paramName1, ...),
|
||||
std::make_unique<Parameter> (paramID2, paramName2, ...),
|
||||
... })
|
||||
@endcode
|
||||
*/
|
||||
class Parameter final : public AudioParameterFloat
|
||||
{
|
||||
public:
|
||||
Parameter (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& labelText,
|
||||
NormalisableRange<float> valueRange,
|
||||
float defaultValue,
|
||||
std::function<String(float)> valueToTextFunction,
|
||||
std::function<float(const String&)> textToValueFunction,
|
||||
bool isMetaParameter = false,
|
||||
bool isAutomatableParameter = true,
|
||||
bool isDiscrete = false,
|
||||
AudioProcessorParameter::Category category = AudioProcessorParameter::genericParameter,
|
||||
bool isBoolean = false);
|
||||
|
||||
int getNumSteps() const override;
|
||||
|
||||
bool isMetaParameter() const override;
|
||||
bool isAutomatable() const override;
|
||||
bool isDiscrete() const override;
|
||||
bool isBoolean() const override;
|
||||
|
||||
private:
|
||||
const bool metaParameter, automatable, discrete, boolean;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a Slider and a parameter
|
||||
in an AudioProcessorValueTreeState.
|
||||
|
|
@ -295,11 +453,44 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct Parameter;
|
||||
friend struct Parameter;
|
||||
/** This method was introduced to allow you to use AudioProcessorValueTreeState parameters in
|
||||
an AudioProcessorParameterGroup, but there is now a much nicer way to achieve this.
|
||||
|
||||
Code that looks like this
|
||||
@code
|
||||
auto paramA = apvts.createParameter ("a", "Parameter A", {}, { -100, 100 }, ...);
|
||||
auto paramB = apvts.createParameter ("b", "Parameter B", {}, { 0, 5 }, ...);
|
||||
addParameterGroup (std::make_unique<AudioProcessorParameterGroup> ("g1", "Group 1", " | ", std::move (paramA), std::move (paramB)));
|
||||
apvts.state = ValueTree (Identifier ("PARAMETERS"));
|
||||
@endcode
|
||||
can instead create the APVTS like this, avoiding the two-step initialization process and leveraging one of JUCE's
|
||||
pre-built parameter types (or your own custom type derived from RangedAudioParameter)
|
||||
@code
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
YourAudioProcessor()
|
||||
: apvts (*this, &undoManager, "PARAMETERS",
|
||||
{ std::make_unique<AudioProcessorParameterGroup> ("g1", "Group 1", " | ",
|
||||
std::make_unique<Parameter> ("a", "Parameter A", "", NormalisableRange<float> (-100, 100), ...),
|
||||
std::make_unique<Parameter> ("b", "Parameter B", "", NormalisableRange<float> (0, 5), ...)) })
|
||||
@endcode
|
||||
*/
|
||||
JUCE_DEPRECATED (std::unique_ptr<RangedAudioParameter> createParameter (const String&, const String&, const String&, NormalisableRange<float>,
|
||||
float, std::function<String (float)>, std::function<float (const String&)>,
|
||||
bool, bool, bool, AudioProcessorParameter::Category, bool));
|
||||
|
||||
//==============================================================================
|
||||
class ParameterAdapter;
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
friend struct ParameterAdapterTests;
|
||||
#endif
|
||||
|
||||
ParameterAdapter* getParameterAdapter (StringRef) const;
|
||||
|
||||
ValueTree getChildValueTree (const String&) const;
|
||||
ValueTree getOrCreateChildValueTree (const String&);
|
||||
bool flushParameterValuesToValueTree();
|
||||
void setNewState (ParameterAdapter&);
|
||||
void timerCallback() override;
|
||||
|
||||
void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
|
||||
|
|
@ -310,9 +501,9 @@ private:
|
|||
void valueTreeRedirected (ValueTree&) override;
|
||||
void updateParameterConnectionsToChildTrees();
|
||||
|
||||
Identifier valueType { "PARAM" },
|
||||
valuePropertyID { "value" },
|
||||
idPropertyID { "id" };
|
||||
const Identifier valueType { "PARAM" }, valuePropertyID { "value" }, idPropertyID { "id" };
|
||||
|
||||
std::vector<std::unique_ptr<ParameterAdapter>> parameters;
|
||||
|
||||
CriticalSection valueTreeChanging;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
This abstract base class is used by some AudioProcessorParameter helper classes.
|
||||
|
||||
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool, AudioParameterChoice
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
RangedAudioParameter (const String& parameterID,
|
||||
const String& name,
|
||||
const String& label = {},
|
||||
Category category = AudioProcessorParameter::genericParameter)
|
||||
: AudioProcessorParameterWithID (parameterID, name, label, category) {}
|
||||
|
||||
/** Returns the range of values that the parameter can take. */
|
||||
virtual const NormalisableRange<float>& getNormalisableRange() const = 0;
|
||||
|
||||
/** Returns the number of steps for this parameter based on the normalisable range's interval.
|
||||
If you are using lambda functions to define the normalisable range's snapping behaviour
|
||||
then you should override this function so that it returns the number of snapping points.
|
||||
*/
|
||||
int getNumSteps() const override
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
|
||||
if (range.interval > 0)
|
||||
return (static_cast<int> ((range.end - range.start) / range.interval) + 1);
|
||||
|
||||
return AudioProcessor::getDefaultNumParameterSteps();
|
||||
}
|
||||
|
||||
/** Normalises and snaps a value based on the normalisable range. */
|
||||
float convertTo0to1 (float v) const noexcept
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
return range.convertTo0to1 (range.snapToLegalValue (v));
|
||||
}
|
||||
|
||||
/** Denormalises and snaps a value based on the normalisable range. */
|
||||
float convertFrom0to1 (float v) const noexcept
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
return range.snapToLegalValue (range.convertFrom0to1 (jlimit (0.0f, 1.0f, v)));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
Loading…
Add table
Add a link
Reference in a new issue