upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)

This commit is contained in:
Alex Birch
2019-06-22 20:41:38 +01:00
parent d22c2cd4fa
commit 9ee566b251
1140 changed files with 67534 additions and 105952 deletions

View File

@ -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.
@ -56,16 +56,20 @@ public:
std::function<bool (const String& text)> boolFromString = nullptr);
/** Destructor. */
~AudioParameterBool();
~AudioParameterBool() override;
/** 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;

View File

@ -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.
@ -60,21 +60,26 @@ public:
std::function<int (const String& text)> indexFromString = nullptr);
/** Destructor. */
~AudioParameterChoice();
~AudioParameterChoice() override;
/** 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;

View File

@ -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,22 +67,27 @@ 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);
/** Destructor. */
~AudioParameterFloat();
~AudioParameterFloat() override;
/** 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;

View File

@ -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.
@ -61,10 +61,11 @@ public:
std::function<int (const String& text)> intFromString = nullptr);
/** Destructor. */
~AudioParameterInt();
~AudioParameterInt() override;
/** 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;

View File

@ -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,
@ -46,7 +46,7 @@ public:
Category category = AudioProcessorParameter::genericParameter);
/** Destructor. */
~AudioProcessorParameterWithID();
~AudioProcessorParameterWithID() override;
/** Provides access to the parameter's ID string. */
const String paramID;

View File

@ -48,55 +48,82 @@ 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)
{
if (stringFromValueFunction == nullptr)
stringFromValueFunction = [] (float v, int length)
{
auto numDecimalPlacesToDisplay = [this]
{
String asText (v, 2);
int numDecimalPlaces = 7;
if (range.interval != 0.0f)
{
if (approximatelyEqual (std::abs (range.interval - (int) range.interval), 0.0f))
return 0;
auto v = std::abs (roundToInt (range.interval * pow (10, numDecimalPlaces)));
while ((v % 10) == 0 && numDecimalPlaces > 0)
{
--numDecimalPlaces;
v /= 10;
}
}
return numDecimalPlaces;
}();
stringFromValueFunction = [numDecimalPlacesToDisplay] (float v, int length)
{
String asText (v, numDecimalPlacesToDisplay);
return length > 0 ? asText.substring (0, length) : asText;
};
}
if (valueFromStringFunction == nullptr)
valueFromStringFunction = [] (const String& text) { return text.getFloatValue(); };
}
AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue, float maxValue, float def)
: AudioParameterFloat (pid, nm, { minValue, maxValue }, def)
: AudioParameterFloat (pid, nm, { minValue, maxValue, 0.01f }, def)
{
}
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 +138,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 +160,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 +232,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 +253,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

View File

@ -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,88 +39,268 @@ 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
To add parameters programatically you can use the iterator-based ParameterLayout
constructor:
@code
AudioProcessorValueTreeState::ParameterLayout createParameterLayout()
{
std::vector<std::unique_ptr<AudioParameterInt>> params;
for (int i = 1; i < 9; ++i)
params.push_back (std::make_unique<AudioParameterInt> (String (i), String (i), 0, i, 0));
return { params.begin(), params.end() };
}
YourAudioProcessor()
: apvts (*this, &undoManager, "PARAMETERS", createParameterLayout())
{
}
@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 Identifier& valueTreeType,
ParameterLayout parameterLayout);
/** This constructor is discouraged and will be deprecated in a future version of JUCE!
Use the other constructor instead.
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();
~AudioProcessorValueTreeState() override;
/** Creates and returns 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!
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
@see AudioProcessorValueTreeState::AudioProcessorValueTreeState
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.
/** Returns a pointer to a floating point representation of a particular parameter which a realtime
process can read to find out its current value.
Note that calling this method from within AudioProcessorValueTreeState::Listener::parameterChanged()
is not guaranteed to return an up-to-date value for the parameter.
*/
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. */
/** This callback method is called by the AudioProcessorValueTreeState when a parameter changes.
Within this call, retrieving the value of the parameter that has changed via the getRawParameterValue()
or getParameter() methods is not guaranteed to return the up-to-date value. If you need this you should
instead use the newValue parameter.
*/
virtual void parameterChanged (const String& parameterID, float newValue) = 0;
};
@ -130,12 +310,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
@ -163,6 +345,7 @@ public:
*/
void replaceState (const ValueTree& newState);
//==============================================================================
/** A reference to the processor with which this state is associated. */
AudioProcessor& processor;
@ -178,6 +361,63 @@ 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);
float getDefaultValue() const override;
int getNumSteps() const override;
bool isMetaParameter() const override;
bool isAutomatable() const override;
bool isDiscrete() const override;
bool isBoolean() const override;
private:
const float unsnappedDefault;
const bool metaParameter, automatable, discrete, boolean;
};
//==============================================================================
/** An object of this class maintains a connection between a Slider and a parameter
in an AudioProcessorValueTreeState.
@ -197,7 +437,6 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment)
};
@ -206,6 +445,11 @@ public:
/** An object of this class maintains a connection between a ComboBox and a parameter
in an AudioProcessorValueTreeState.
Combobox items will be spaced linearly across the range of the parameter. For
example if the range is specified by NormalisableRange<float> (-0.5f, 0.5f, 0.5f)
and you add three items then the first will be mapped to a value of -0.5, the
second to 0, and the third to 0.5.
During the lifetime of this ComboBoxAttachment object, it keeps the two things in
sync, making it easy to connect a combo box to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
@ -221,7 +465,6 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment)
};
@ -245,18 +488,49 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment)
};
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
void addParameterAdapter (RangedAudioParameter&);
ParameterAdapter* getParameterAdapter (StringRef) const;
ValueTree getOrCreateChildValueTree (const String&);
bool flushParameterValuesToValueTree();
void setNewState (ValueTree);
void timerCallback() override;
void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
@ -267,9 +541,14 @@ private:
void valueTreeRedirected (ValueTree&) override;
void updateParameterConnectionsToChildTrees();
Identifier valueType { "PARAM" },
valuePropertyID { "value" },
idPropertyID { "id" };
const Identifier valueType { "PARAM" }, valuePropertyID { "value" }, idPropertyID { "id" };
struct StringRefLessThan final
{
bool operator() (StringRef a, StringRef b) const noexcept { return a.text.compare (b.text) < 0; }
};
std::map<StringRef, std::unique_ptr<ParameterAdapter>, StringRefLessThan> adapterTable;
CriticalSection valueTreeChanging;

View File

@ -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