git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
105
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterBool.cpp
vendored
Normal file
105
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterBool.cpp
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nameToUse,
|
||||
bool def, const String& labelToUse,
|
||||
std::function<String (bool, int)> stringFromBool,
|
||||
std::function<bool (const String&)> boolFromString)
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse),
|
||||
value (def ? 1.0f : 0.0f),
|
||||
defaultValue (value),
|
||||
stringFromBoolFunction (stringFromBool),
|
||||
boolFromStringFunction (boolFromString)
|
||||
{
|
||||
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()
|
||||
{
|
||||
#if __cpp_lib_atomic_is_always_lock_free
|
||||
static_assert (std::atomic<float>::is_always_lock_free,
|
||||
"AudioParameterBool requires a lock-free std::atomic<float>");
|
||||
#endif
|
||||
}
|
||||
|
||||
float AudioParameterBool::getValue() const { return value; }
|
||||
void AudioParameterBool::setValue (float newValue) { value = newValue; valueChanged (get()); }
|
||||
float AudioParameterBool::getDefaultValue() const { return defaultValue; }
|
||||
int AudioParameterBool::getNumSteps() const { return 2; }
|
||||
bool AudioParameterBool::isDiscrete() const { return true; }
|
||||
bool AudioParameterBool::isBoolean() const { return true; }
|
||||
void AudioParameterBool::valueChanged (bool) {}
|
||||
|
||||
float AudioParameterBool::getValueForText (const String& text) const
|
||||
{
|
||||
return boolFromStringFunction (text) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
String AudioParameterBool::getText (float v, int maximumLength) const
|
||||
{
|
||||
return stringFromBoolFunction (v >= 0.5f, maximumLength);
|
||||
}
|
||||
|
||||
AudioParameterBool& AudioParameterBool::operator= (bool newValue)
|
||||
{
|
||||
if (get() != newValue)
|
||||
setValueNotifyingHost (newValue ? 1.0f : 0.0f);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace juce
|
98
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h
vendored
Normal file
98
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/**
|
||||
Provides a class of AudioProcessorParameter that can be used as a boolean value.
|
||||
|
||||
@see AudioParameterFloat, AudioParameterInt, AudioParameterChoice
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterBool : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterBool with the specified parameters.
|
||||
|
||||
@param parameterID The parameter ID to use
|
||||
@param parameterName The parameter name to use
|
||||
@param defaultValue The default value
|
||||
@param parameterLabel An optional label for the parameter's value
|
||||
@param stringFromBool An optional lambda function that converts a bool
|
||||
value to a string with a maximum length. This may
|
||||
be used by hosts to display the parameter's value.
|
||||
@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.
|
||||
*/
|
||||
AudioParameterBool (const String& parameterID, const String& parameterName, bool defaultValue,
|
||||
const String& parameterLabel = String(),
|
||||
std::function<String (bool value, int maximumStringLength)> stringFromBool = nullptr,
|
||||
std::function<bool (const String& text)> boolFromString = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~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.
|
||||
*/
|
||||
virtual void valueChanged (bool newValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
float getValue() const override;
|
||||
void setValue (float newValue) override;
|
||||
float getDefaultValue() const override;
|
||||
int getNumSteps() const override;
|
||||
bool isDiscrete() const override;
|
||||
bool isBoolean() const override;
|
||||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
const NormalisableRange<float> range { 0.0f, 1.0f, 1.0f };
|
||||
std::atomic<float> value;
|
||||
const float defaultValue;
|
||||
std::function<String (bool, int)> stringFromBoolFunction;
|
||||
std::function<bool (const String&)> boolFromStringFunction;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterBool)
|
||||
};
|
||||
|
||||
} // namespace juce
|
136
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.cpp
vendored
Normal file
136
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.cpp
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
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)
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse), choices (c),
|
||||
range ([this]
|
||||
{
|
||||
NormalisableRange<float> rangeWithInterval { 0.0f, (float) 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)); } };
|
||||
rangeWithInterval.interval = 1.0f;
|
||||
return rangeWithInterval;
|
||||
}()),
|
||||
value ((float) def),
|
||||
defaultValue (convertTo0to1 ((float) def)),
|
||||
stringFromIndexFunction (stringFromIndex),
|
||||
indexFromStringFunction (indexFromString)
|
||||
{
|
||||
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()
|
||||
{
|
||||
#if __cpp_lib_atomic_is_always_lock_free
|
||||
static_assert (std::atomic<float>::is_always_lock_free,
|
||||
"AudioParameterChoice requires a lock-free std::atomic<float>");
|
||||
#endif
|
||||
}
|
||||
|
||||
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 ((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 ((float) newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
struct AudioParameterChoiceTests : public UnitTest
|
||||
{
|
||||
AudioParameterChoiceTests()
|
||||
: UnitTest ("AudioParameterChoice", UnitTestCategories::audioProcessorParameters)
|
||||
{}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("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 ("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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static AudioParameterChoiceTests audioParameterChoiceTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
110
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h
vendored
Normal file
110
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/**
|
||||
Provides a class of AudioProcessorParameter that can be used to select
|
||||
an indexed, named choice from a list.
|
||||
|
||||
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterChoice : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterChoice with the specified parameters.
|
||||
|
||||
@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 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
|
||||
be used by hosts to display the parameter's value.
|
||||
@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.
|
||||
*/
|
||||
AudioParameterChoice (const String& parameterID, const String& parameterName,
|
||||
const StringArray& choices,
|
||||
int defaultItemIndex,
|
||||
const String& parameterLabel = String(),
|
||||
std::function<String (int index, int maximumStringLength)> stringFromIndex = nullptr,
|
||||
std::function<int (const String& text)> indexFromString = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioParameterChoice() override;
|
||||
|
||||
/** Returns the current index of the selected item. */
|
||||
int getIndex() const noexcept { return roundToInt (value.load()); }
|
||||
|
||||
/** 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;
|
||||
|
||||
protected:
|
||||
/** Override this method if you are interested in receiving callbacks
|
||||
when the parameter value changes.
|
||||
*/
|
||||
virtual void valueChanged (int newValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
float getValue() const override;
|
||||
void setValue (float newValue) override;
|
||||
float getDefaultValue() const override;
|
||||
int getNumSteps() const override;
|
||||
bool isDiscrete() const override;
|
||||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
const NormalisableRange<float> range;
|
||||
std::atomic<float> value;
|
||||
const float defaultValue;
|
||||
std::function<String (int, int)> stringFromIndexFunction;
|
||||
std::function<int (const String&)> indexFromStringFunction;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterChoice)
|
||||
};
|
||||
|
||||
} // namespace juce
|
102
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp
vendored
Normal file
102
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
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)
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse, categoryToUse),
|
||||
range (r), value (def), defaultValue (def),
|
||||
stringFromValueFunction (stringFromValue),
|
||||
valueFromStringFunction (valueFromString)
|
||||
{
|
||||
if (stringFromValueFunction == nullptr)
|
||||
{
|
||||
auto numDecimalPlacesToDisplay = [this]
|
||||
{
|
||||
int numDecimalPlaces = 7;
|
||||
|
||||
if (range.interval != 0.0f)
|
||||
{
|
||||
if (approximatelyEqual (std::abs (range.interval - std::floor (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, 0.01f }, def)
|
||||
{
|
||||
}
|
||||
|
||||
AudioParameterFloat::~AudioParameterFloat()
|
||||
{
|
||||
#if __cpp_lib_atomic_is_always_lock_free
|
||||
static_assert (std::atomic<float>::is_always_lock_free,
|
||||
"AudioParameterFloat requires a lock-free std::atomic<float>");
|
||||
#endif
|
||||
}
|
||||
|
||||
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 (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 (convertTo0to1 (newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace juce
|
116
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h
vendored
Normal file
116
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/**
|
||||
A subclass of AudioProcessorParameter that provides an easy way to create a
|
||||
parameter which maps onto a given NormalisableRange.
|
||||
|
||||
@see AudioParameterInt, AudioParameterBool, AudioParameterChoice
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterFloat : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** Creates a AudioParameterFloat with the specified parameters.
|
||||
|
||||
@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 parameterLabel An optional label for the parameter's value
|
||||
@param parameterCategory An optional parameter category
|
||||
@param stringFromValue 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.
|
||||
@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.
|
||||
*/
|
||||
AudioParameterFloat (const String& parameterID,
|
||||
const String& parameterName,
|
||||
NormalisableRange<float> normalisableRange,
|
||||
float defaultValue,
|
||||
const String& parameterLabel = String(),
|
||||
Category parameterCategory = AudioProcessorParameter::genericParameter,
|
||||
std::function<String (float value, int maximumStringLength)> stringFromValue = nullptr,
|
||||
std::function<float (const String& text)> valueFromString = nullptr);
|
||||
|
||||
/** 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,
|
||||
float minValue,
|
||||
float maxValue,
|
||||
float defaultValue);
|
||||
|
||||
/** Destructor. */
|
||||
~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;
|
||||
|
||||
protected:
|
||||
/** Override this method if you are interested in receiving callbacks
|
||||
when the parameter value changes.
|
||||
*/
|
||||
virtual void valueChanged (float newValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
float getValue() const override;
|
||||
void setValue (float newValue) override;
|
||||
float getDefaultValue() const override;
|
||||
int getNumSteps() const override;
|
||||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
std::atomic<float> value;
|
||||
const float defaultValue;
|
||||
std::function<String (float, int)> stringFromValueFunction;
|
||||
std::function<float (const String&)> valueFromStringFunction;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterFloat)
|
||||
};
|
||||
|
||||
} // namespace juce
|
141
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterInt.cpp
vendored
Normal file
141
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterInt.cpp
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
AudioParameterInt::AudioParameterInt (const String& 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)
|
||||
: RangedAudioParameter (idToUse, nameToUse, labelToUse),
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
#if __cpp_lib_atomic_is_always_lock_free
|
||||
static_assert (std::atomic<float>::is_always_lock_free,
|
||||
"AudioParameterInt requires a lock-free std::atomic<float>");
|
||||
#endif
|
||||
}
|
||||
|
||||
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 ((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 ((float) newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
struct AudioParameterIntTests : public UnitTest
|
||||
{
|
||||
AudioParameterIntTests()
|
||||
: UnitTest ("AudioParameterInt", UnitTestCategories::audioProcessorParameters)
|
||||
{}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("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 ("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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static AudioParameterIntTests audioParameterIntTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
106
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterInt.h
vendored
Normal file
106
deps/juce/modules/juce_audio_processors/utilities/juce_AudioParameterInt.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/**
|
||||
Provides a class of AudioProcessorParameter that can be used as an
|
||||
integer value with a given range.
|
||||
|
||||
@see AudioParameterFloat, AudioParameterBool, AudioParameterChoice
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioParameterInt : public RangedAudioParameter
|
||||
{
|
||||
public:
|
||||
/** 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 defaultValue 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
|
||||
be used by hosts to display the parameter's value.
|
||||
@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.
|
||||
*/
|
||||
AudioParameterInt (const String& parameterID, const String& parameterName,
|
||||
int minValue, int maxValue,
|
||||
int defaultValue,
|
||||
const String& parameterLabel = String(),
|
||||
std::function<String (int value, int maximumStringLength)> stringFromInt = nullptr,
|
||||
std::function<int (const String& text)> intFromString = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioParameterInt() override;
|
||||
|
||||
/** Returns the parameter's current value as an integer. */
|
||||
int get() const noexcept { return roundToInt (value.load()); }
|
||||
|
||||
/** Returns the parameter's current value as an integer. */
|
||||
operator int() const noexcept { return get(); }
|
||||
|
||||
/** Changes the parameter's current value to a new integer.
|
||||
The value passed in will be snapped to the permitted range before being used.
|
||||
*/
|
||||
AudioParameterInt& operator= (int newValue);
|
||||
|
||||
/** Returns the parameter's range. */
|
||||
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
|
||||
when the parameter value changes.
|
||||
*/
|
||||
virtual void valueChanged (int newValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
float getValue() const override;
|
||||
void setValue (float newValue) override;
|
||||
float getDefaultValue() const override;
|
||||
int getNumSteps() const override;
|
||||
String getText (float, int) const override;
|
||||
float getValueForText (const String&) const override;
|
||||
|
||||
const NormalisableRange<float> range;
|
||||
std::atomic<float> value;
|
||||
const float defaultValue;
|
||||
std::function<String (int, int)> stringFromIntFunction;
|
||||
std::function<int (const String&)> intFromStringFunction;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterInt)
|
||||
};
|
||||
|
||||
} // namespace juce
|
40
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.cpp
vendored
Normal file
40
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.cpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const String& idToUse,
|
||||
const String& nameToUse,
|
||||
const String& labelToUse,
|
||||
AudioProcessorParameter::Category categoryToUse)
|
||||
: paramID (idToUse), name (nameToUse), label (labelToUse), category (categoryToUse) {}
|
||||
AudioProcessorParameterWithID::~AudioProcessorParameterWithID() {}
|
||||
|
||||
String AudioProcessorParameterWithID::getName (int maximumStringLength) const { return name.substring (0, maximumStringLength); }
|
||||
String AudioProcessorParameterWithID::getLabel() const { return label; }
|
||||
AudioProcessorParameter::Category AudioProcessorParameterWithID::getCategory() const { return category; }
|
||||
|
||||
} // namespace juce
|
70
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h
vendored
Normal file
70
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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 AudioProcessorParameterWithID : public AudioProcessorParameter
|
||||
{
|
||||
public:
|
||||
/** The creation of this object requires providing a name and ID which will be
|
||||
constant for its lifetime.
|
||||
*/
|
||||
AudioProcessorParameterWithID (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& parameterLabel = {},
|
||||
Category parameterCategory = AudioProcessorParameter::genericParameter);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioProcessorParameterWithID() override;
|
||||
|
||||
/** Provides access to the parameter's ID string. */
|
||||
const String paramID;
|
||||
|
||||
/** Provides access to the parameter's name. */
|
||||
const String name;
|
||||
|
||||
/** Provides access to the parameter's label. */
|
||||
const String label;
|
||||
|
||||
/** Provides access to the parameter's category. */
|
||||
const Category category;
|
||||
|
||||
String getName (int) const override;
|
||||
String getLabel() const override;
|
||||
Category getCategory() const override;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterWithID)
|
||||
};
|
||||
|
||||
} // namespace juce
|
963
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
vendored
Normal file
963
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
vendored
Normal file
@@ -0,0 +1,963 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorValueTreeState::Parameter::Parameter (const String& 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)
|
||||
: 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)),
|
||||
unsnappedDefault (valueRange.convertTo0to1 (defaultParameterValue)),
|
||||
metaParameter (isMetaParameter),
|
||||
automatable (isAutomatableParameter),
|
||||
discrete (isDiscrete),
|
||||
boolean (isBoolean)
|
||||
{
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
void AudioProcessorValueTreeState::Parameter::valueChanged (float newValue)
|
||||
{
|
||||
if (lastValue == newValue)
|
||||
return;
|
||||
|
||||
lastValue = newValue;
|
||||
|
||||
if (onValueChanged != nullptr)
|
||||
onValueChanged();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class AudioProcessorValueTreeState::ParameterAdapter : private AudioProcessorParameter::Listener
|
||||
{
|
||||
private:
|
||||
using Listener = AudioProcessorValueTreeState::Listener;
|
||||
|
||||
public:
|
||||
explicit ParameterAdapter (RangedAudioParameter& parameterIn)
|
||||
: parameter (parameterIn),
|
||||
// For legacy reasons, the unnormalised value should *not* be snapped on construction
|
||||
unnormalisedValue (getRange().convertFrom0to1 (parameter.getDefaultValue()))
|
||||
{
|
||||
parameter.addListener (this);
|
||||
|
||||
if (auto* ptr = dynamic_cast<Parameter*> (¶meter))
|
||||
ptr->onValueChanged = [this] { parameterValueChanged ({}, {}); };
|
||||
}
|
||||
|
||||
~ParameterAdapter() override { parameter.removeListener (this); }
|
||||
|
||||
void addListener (Listener* l) { listeners.add (l); }
|
||||
void removeListener (Listener* l) { listeners.remove (l); }
|
||||
|
||||
RangedAudioParameter& getParameter() { return parameter; }
|
||||
const RangedAudioParameter& getParameter() const { return parameter; }
|
||||
|
||||
const NormalisableRange<float>& getRange() const { return parameter.getNormalisableRange(); }
|
||||
|
||||
float getDenormalisedDefaultValue() const { return denormalise (parameter.getDefaultValue()); }
|
||||
|
||||
void setDenormalisedValue (float value)
|
||||
{
|
||||
if (value == unnormalisedValue)
|
||||
return;
|
||||
|
||||
setNormalisedValue (normalise (value));
|
||||
}
|
||||
|
||||
float getDenormalisedValueForText (const String& text) const
|
||||
{
|
||||
return denormalise (parameter.getValueForText (text));
|
||||
}
|
||||
|
||||
String getTextForDenormalisedValue (float value) const
|
||||
{
|
||||
return parameter.getText (normalise (value), 0);
|
||||
}
|
||||
|
||||
float getDenormalisedValue() const { return unnormalisedValue; }
|
||||
std::atomic<float>& getRawDenormalisedValue() { return unnormalisedValue; }
|
||||
|
||||
bool flushToTree (const Identifier& key, UndoManager* um)
|
||||
{
|
||||
auto needsUpdateTestValue = true;
|
||||
|
||||
if (! needsUpdate.compare_exchange_strong (needsUpdateTestValue, false))
|
||||
return false;
|
||||
|
||||
if (auto valueProperty = tree.getPropertyPointer (key))
|
||||
{
|
||||
if ((float) *valueProperty != unnormalisedValue)
|
||||
{
|
||||
ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true);
|
||||
tree.setProperty (key, unnormalisedValue.load(), um);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tree.setProperty (key, unnormalisedValue.load(), nullptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueTree tree;
|
||||
|
||||
private:
|
||||
void parameterGestureChanged (int, bool) override {}
|
||||
|
||||
void parameterValueChanged (int, float) override
|
||||
{
|
||||
const auto newValue = denormalise (parameter.getValue());
|
||||
|
||||
if (unnormalisedValue == newValue && ! listenersNeedCalling)
|
||||
return;
|
||||
|
||||
unnormalisedValue = newValue;
|
||||
listeners.call ([this] (Listener& l) { l.parameterChanged (parameter.paramID, unnormalisedValue); });
|
||||
listenersNeedCalling = false;
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
float denormalise (float normalised) const
|
||||
{
|
||||
return getParameter().convertFrom0to1 (normalised);
|
||||
}
|
||||
|
||||
float normalise (float denormalised) const
|
||||
{
|
||||
return getParameter().convertTo0to1 (denormalised);
|
||||
}
|
||||
|
||||
void setNormalisedValue (float value)
|
||||
{
|
||||
if (ignoreParameterChangedCallbacks)
|
||||
return;
|
||||
|
||||
parameter.setValueNotifyingHost (value);
|
||||
}
|
||||
|
||||
class LockedListeners
|
||||
{
|
||||
public:
|
||||
template <typename Fn>
|
||||
void call (Fn&& fn)
|
||||
{
|
||||
const CriticalSection::ScopedLockType lock (mutex);
|
||||
listeners.call (std::forward<Fn> (fn));
|
||||
}
|
||||
|
||||
void add (Listener* l)
|
||||
{
|
||||
const CriticalSection::ScopedLockType lock (mutex);
|
||||
listeners.add (l);
|
||||
}
|
||||
|
||||
void remove (Listener* l)
|
||||
{
|
||||
const CriticalSection::ScopedLockType lock (mutex);
|
||||
listeners.remove (l);
|
||||
}
|
||||
|
||||
private:
|
||||
CriticalSection mutex;
|
||||
ListenerList<Listener> listeners;
|
||||
};
|
||||
|
||||
RangedAudioParameter& parameter;
|
||||
LockedListeners listeners;
|
||||
std::atomic<float> unnormalisedValue { 0.0f };
|
||||
std::atomic<bool> needsUpdate { true }, listenersNeedCalling { true };
|
||||
bool ignoreParameterChangedCallbacks { false };
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo,
|
||||
UndoManager* undoManagerToUse,
|
||||
const Identifier& valueTreeType,
|
||||
ParameterLayout parameterLayout)
|
||||
: AudioProcessorValueTreeState (processorToConnectTo, undoManagerToUse)
|
||||
{
|
||||
struct PushBackVisitor : ParameterLayout::Visitor
|
||||
{
|
||||
explicit PushBackVisitor (AudioProcessorValueTreeState& stateIn)
|
||||
: state (&stateIn) {}
|
||||
|
||||
void visit (std::unique_ptr<RangedAudioParameter> param) const override
|
||||
{
|
||||
if (param == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return;
|
||||
}
|
||||
|
||||
state->addParameterAdapter (*param);
|
||||
state->processor.addParameter (param.release());
|
||||
}
|
||||
|
||||
void visit (std::unique_ptr<AudioProcessorParameterGroup> group) const override
|
||||
{
|
||||
if (group == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto param : group->getParameters (true))
|
||||
{
|
||||
if (const auto rangedParam = dynamic_cast<RangedAudioParameter*> (param))
|
||||
{
|
||||
state->addParameterAdapter (*rangedParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If you hit this assertion then you are attempting to add a parameter that is
|
||||
// not derived from RangedAudioParameter to the AudioProcessorValueTreeState.
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
state->processor.addParameterGroup (move (group));
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState* state;
|
||||
};
|
||||
|
||||
for (auto& item : parameterLayout.parameters)
|
||||
item->accept (PushBackVisitor (*this));
|
||||
|
||||
state = ValueTree (valueTreeType);
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& p, UndoManager* um)
|
||||
: processor (p), undoManager (um)
|
||||
{
|
||||
startTimerHz (10);
|
||||
state.addListener (this);
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::~AudioProcessorValueTreeState()
|
||||
{
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (const String& paramID,
|
||||
const String& paramName,
|
||||
const String& labelText,
|
||||
NormalisableRange<float> range,
|
||||
float defaultVal,
|
||||
std::function<String (float)> valueToTextFunction,
|
||||
std::function<float (const String&)> textToValueFunction,
|
||||
bool isMetaParameter,
|
||||
bool isAutomatableParameter,
|
||||
bool isDiscreteParameter,
|
||||
AudioProcessorParameter::Category category,
|
||||
bool isBooleanParameter)
|
||||
{
|
||||
return createAndAddParameter (std::make_unique<Parameter> (paramID,
|
||||
paramName,
|
||||
labelText,
|
||||
range,
|
||||
defaultVal,
|
||||
std::move (valueToTextFunction),
|
||||
std::move (textToValueFunction),
|
||||
isMetaParameter,
|
||||
isAutomatableParameter,
|
||||
isDiscreteParameter,
|
||||
category,
|
||||
isBooleanParameter));
|
||||
}
|
||||
|
||||
RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (std::unique_ptr<RangedAudioParameter> param)
|
||||
{
|
||||
if (param == nullptr)
|
||||
return nullptr;
|
||||
|
||||
// All parameters must be created before giving this manager a ValueTree state!
|
||||
jassert (! state.isValid());
|
||||
|
||||
if (getParameter (param->paramID) != nullptr)
|
||||
return nullptr;
|
||||
|
||||
addParameterAdapter (*param);
|
||||
|
||||
processor.addParameter (param.get());
|
||||
|
||||
return param.release();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessorValueTreeState::addParameterAdapter (RangedAudioParameter& param)
|
||||
{
|
||||
adapterTable.emplace (param.paramID, std::make_unique<ParameterAdapter> (param));
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::ParameterAdapter* AudioProcessorValueTreeState::getParameterAdapter (StringRef paramID) const
|
||||
{
|
||||
auto it = adapterTable.find (paramID);
|
||||
return it == adapterTable.end() ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::addParameterListener (StringRef paramID, Listener* listener)
|
||||
{
|
||||
if (auto* p = getParameterAdapter (paramID))
|
||||
p->addListener (listener);
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::removeParameterListener (StringRef paramID, Listener* listener)
|
||||
{
|
||||
if (auto* p = getParameterAdapter (paramID))
|
||||
p->removeListener (listener);
|
||||
}
|
||||
|
||||
Value AudioProcessorValueTreeState::getParameterAsValue (StringRef paramID) const
|
||||
{
|
||||
if (auto* adapter = getParameterAdapter (paramID))
|
||||
if (adapter->tree.isValid())
|
||||
return adapter->tree.getPropertyAsValue (valuePropertyID, undoManager);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
NormalisableRange<float> AudioProcessorValueTreeState::getParameterRange (StringRef paramID) const noexcept
|
||||
{
|
||||
if (auto* p = getParameterAdapter (paramID))
|
||||
return p->getRange();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
RangedAudioParameter* AudioProcessorValueTreeState::getParameter (StringRef paramID) const noexcept
|
||||
{
|
||||
if (auto adapter = getParameterAdapter (paramID))
|
||||
return &adapter->getParameter();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::atomic<float>* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept
|
||||
{
|
||||
if (auto* p = getParameterAdapter (paramID))
|
||||
return &p->getRawDenormalisedValue();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ValueTree AudioProcessorValueTreeState::copyState()
|
||||
{
|
||||
ScopedLock lock (valueTreeChanging);
|
||||
flushParameterValuesToValueTree();
|
||||
return state.createCopy();
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::replaceState (const ValueTree& newState)
|
||||
{
|
||||
ScopedLock lock (valueTreeChanging);
|
||||
|
||||
state = newState;
|
||||
|
||||
if (undoManager != nullptr)
|
||||
undoManager->clearUndoHistory();
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::setNewState (ValueTree vt)
|
||||
{
|
||||
jassert (vt.getParent() == state);
|
||||
|
||||
if (auto* p = getParameterAdapter (vt.getProperty (idPropertyID).toString()))
|
||||
{
|
||||
p->tree = vt;
|
||||
p->setDenormalisedValue (p->tree.getProperty (valuePropertyID, p->getDenormalisedDefaultValue()));
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::updateParameterConnectionsToChildTrees()
|
||||
{
|
||||
ScopedLock lock (valueTreeChanging);
|
||||
|
||||
for (auto& p : adapterTable)
|
||||
p.second->tree = ValueTree();
|
||||
|
||||
for (const auto& child : state)
|
||||
setNewState (child);
|
||||
|
||||
for (auto& p : adapterTable)
|
||||
{
|
||||
auto& adapter = *p.second;
|
||||
|
||||
if (! adapter.tree.isValid())
|
||||
{
|
||||
adapter.tree = ValueTree (valueType);
|
||||
adapter.tree.setProperty (idPropertyID, adapter.getParameter().paramID, nullptr);
|
||||
state.appendChild (adapter.tree, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
flushParameterValuesToValueTree();
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::valueTreePropertyChanged (ValueTree& tree, const Identifier&)
|
||||
{
|
||||
if (tree.hasType (valueType) && tree.getParent() == state)
|
||||
setNewState (tree);
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::valueTreeChildAdded (ValueTree& parent, ValueTree& tree)
|
||||
{
|
||||
if (parent == state && tree.hasType (valueType))
|
||||
setNewState (tree);
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::valueTreeRedirected (ValueTree& v)
|
||||
{
|
||||
if (v == state)
|
||||
updateParameterConnectionsToChildTrees();
|
||||
}
|
||||
|
||||
bool AudioProcessorValueTreeState::flushParameterValuesToValueTree()
|
||||
{
|
||||
ScopedLock lock (valueTreeChanging);
|
||||
|
||||
bool anyUpdated = false;
|
||||
|
||||
for (auto& p : adapterTable)
|
||||
anyUpdated |= p.second->flushToTree (valuePropertyID, undoManager);
|
||||
|
||||
return anyUpdated;
|
||||
}
|
||||
|
||||
void AudioProcessorValueTreeState::timerCallback()
|
||||
{
|
||||
auto anythingUpdated = flushParameterValuesToValueTree();
|
||||
|
||||
startTimer (anythingUpdated ? 1000 / 50
|
||||
: jlimit (50, 500, getTimerInterval() + 20));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename Attachment, typename Control>
|
||||
std::unique_ptr<Attachment> makeAttachment (const AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
Control& control)
|
||||
{
|
||||
if (auto* parameter = stateToUse.getParameter (parameterID))
|
||||
return std::make_unique<Attachment> (*parameter, control, stateToUse.undoManager);
|
||||
|
||||
jassertfalse;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::SliderAttachment::SliderAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
Slider& slider)
|
||||
: attachment (makeAttachment<SliderParameterAttachment> (stateToUse, parameterID, slider))
|
||||
{
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::ComboBoxAttachment::ComboBoxAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
ComboBox& combo)
|
||||
: attachment (makeAttachment<ComboBoxParameterAttachment> (stateToUse, parameterID, combo))
|
||||
{
|
||||
}
|
||||
|
||||
AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
Button& button)
|
||||
: attachment (makeAttachment<ButtonParameterAttachment> (stateToUse, parameterID, button))
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
struct ParameterAdapterTests : public UnitTest
|
||||
{
|
||||
ParameterAdapterTests()
|
||||
: UnitTest ("Parameter Adapter", UnitTestCategories::audioProcessorParameters)
|
||||
{}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("The default value is returned correctly");
|
||||
{
|
||||
const auto test = [&] (NormalisableRange<float> range, float value)
|
||||
{
|
||||
AudioParameterFloat param ({}, {}, range, value, {});
|
||||
|
||||
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
||||
|
||||
expectEquals (adapter.getDenormalisedDefaultValue(), value);
|
||||
};
|
||||
|
||||
test ({ -100, 100 }, 0);
|
||||
test ({ -2.5, 12.5 }, 10);
|
||||
}
|
||||
|
||||
beginTest ("Denormalised parameter values can be retrieved");
|
||||
{
|
||||
const auto test = [&] (NormalisableRange<float> range, float value)
|
||||
{
|
||||
AudioParameterFloat param ({}, {}, range, {}, {});
|
||||
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
||||
|
||||
adapter.setDenormalisedValue (value);
|
||||
|
||||
expectEquals (adapter.getDenormalisedValue(), value);
|
||||
expectEquals (adapter.getRawDenormalisedValue().load(), value);
|
||||
};
|
||||
|
||||
test ({ -20, -10 }, -15);
|
||||
test ({ 0, 7.5 }, 2.5);
|
||||
}
|
||||
|
||||
beginTest ("Floats can be converted to text");
|
||||
{
|
||||
const auto test = [&] (NormalisableRange<float> range, float value, String expected)
|
||||
{
|
||||
AudioParameterFloat param ({}, {}, range, {}, {});
|
||||
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
||||
|
||||
expectEquals (adapter.getTextForDenormalisedValue (value), expected);
|
||||
};
|
||||
|
||||
test ({ -100, 100 }, 0, "0.0000000");
|
||||
test ({ -2.5, 12.5 }, 10, "10.0000000");
|
||||
test ({ -20, -10 }, -15, "-15.0000000");
|
||||
test ({ 0, 7.5 }, 2.5, "2.5000000");
|
||||
}
|
||||
|
||||
beginTest ("Text can be converted to floats");
|
||||
{
|
||||
const auto test = [&] (NormalisableRange<float> range, String text, float expected)
|
||||
{
|
||||
AudioParameterFloat param ({}, {}, range, {}, {});
|
||||
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
||||
|
||||
expectEquals (adapter.getDenormalisedValueForText (text), expected);
|
||||
};
|
||||
|
||||
test ({ -100, 100 }, "0.0", 0);
|
||||
test ({ -2.5, 12.5 }, "10.0", 10);
|
||||
test ({ -20, -10 }, "-15.0", -15);
|
||||
test ({ 0, 7.5 }, "2.5", 2.5);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static ParameterAdapterTests parameterAdapterTests;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename ValueType>
|
||||
inline bool operator== (const NormalisableRange<ValueType>& a,
|
||||
const NormalisableRange<ValueType>& b)
|
||||
{
|
||||
return std::tie (a.start, a.end, a.interval, a.skew, a.symmetricSkew)
|
||||
== std::tie (b.start, b.end, b.interval, b.skew, b.symmetricSkew);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
inline bool operator!= (const NormalisableRange<ValueType>& a,
|
||||
const NormalisableRange<ValueType>& b)
|
||||
{
|
||||
return ! (a == b);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class AudioProcessorValueTreeStateTests : public UnitTest
|
||||
{
|
||||
private:
|
||||
using Parameter = AudioProcessorValueTreeState::Parameter;
|
||||
using ParameterGroup = AudioProcessorParameterGroup;
|
||||
using ParameterLayout = AudioProcessorValueTreeState::ParameterLayout;
|
||||
|
||||
class TestAudioProcessor : public AudioProcessor
|
||||
{
|
||||
public:
|
||||
TestAudioProcessor() = default;
|
||||
|
||||
explicit TestAudioProcessor (ParameterLayout layout)
|
||||
: state (*this, nullptr, "state", std::move (layout)) {}
|
||||
|
||||
const String getName() const override { return {}; }
|
||||
void prepareToPlay (double, int) override {}
|
||||
void releaseResources() override {}
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}
|
||||
using AudioProcessor::processBlock;
|
||||
double getTailLengthSeconds() const override { return {}; }
|
||||
bool acceptsMidi() const override { return {}; }
|
||||
bool producesMidi() const override { return {}; }
|
||||
AudioProcessorEditor* createEditor() override { return {}; }
|
||||
bool hasEditor() const override { return {}; }
|
||||
int getNumPrograms() override { return 1; }
|
||||
int getCurrentProgram() override { return {}; }
|
||||
void setCurrentProgram (int) override {}
|
||||
const String getProgramName (int) override { return {}; }
|
||||
void changeProgramName (int, const String&) override {}
|
||||
void getStateInformation (MemoryBlock&) override {}
|
||||
void setStateInformation (const void*, int) override {}
|
||||
|
||||
AudioProcessorValueTreeState state { *this, nullptr };
|
||||
};
|
||||
|
||||
struct Listener final : public AudioProcessorValueTreeState::Listener
|
||||
{
|
||||
void parameterChanged (const String& idIn, float valueIn) override
|
||||
{
|
||||
id = idIn;
|
||||
value = valueIn;
|
||||
}
|
||||
|
||||
String id;
|
||||
float value{};
|
||||
};
|
||||
|
||||
public:
|
||||
AudioProcessorValueTreeStateTests()
|
||||
: UnitTest ("Audio Processor Value Tree State", UnitTestCategories::audioProcessorParameters)
|
||||
{}
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6262)
|
||||
void runTest() override
|
||||
{
|
||||
ScopedJuceInitialiser_GUI scopedJuceInitialiser_gui;
|
||||
|
||||
beginTest ("After calling createAndAddParameter, the number of parameters increases by one");
|
||||
{
|
||||
TestAudioProcessor proc;
|
||||
|
||||
proc.state.createAndAddParameter (std::make_unique<Parameter> (String(), String(), String(), NormalisableRange<float>(),
|
||||
0.0f, nullptr, nullptr));
|
||||
|
||||
expectEquals (proc.getParameters().size(), 1);
|
||||
}
|
||||
|
||||
beginTest ("After creating a normal named parameter, we can later retrieve that parameter");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (proc.state.getParameter (key) == param);
|
||||
}
|
||||
|
||||
beginTest ("After construction, the value tree has the expected format");
|
||||
{
|
||||
TestAudioProcessor proc ({
|
||||
std::make_unique<AudioProcessorParameterGroup> ("A", "", "",
|
||||
std::make_unique<AudioParameterBool> ("a", "", false),
|
||||
std::make_unique<AudioParameterFloat> ("b", "", NormalisableRange<float>{}, 0.0f)),
|
||||
std::make_unique<AudioProcessorParameterGroup> ("B", "", "",
|
||||
std::make_unique<AudioParameterInt> ("c", "", 0, 1, 0),
|
||||
std::make_unique<AudioParameterChoice> ("d", "", StringArray { "foo", "bar" }, 0)) });
|
||||
|
||||
const auto valueTree = proc.state.copyState();
|
||||
|
||||
expectEquals (valueTree.getNumChildren(), 4);
|
||||
|
||||
for (auto child : valueTree)
|
||||
{
|
||||
expect (child.hasType ("PARAM"));
|
||||
expect (child.hasProperty ("id"));
|
||||
expect (child.hasProperty ("value"));
|
||||
}
|
||||
}
|
||||
|
||||
beginTest ("Meta parameters can be created");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (param->isMetaParameter());
|
||||
}
|
||||
|
||||
beginTest ("Automatable parameters can be created");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (param->isAutomatable());
|
||||
}
|
||||
|
||||
beginTest ("Discrete parameters can be created");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (param->isDiscrete());
|
||||
}
|
||||
|
||||
beginTest ("Custom category parameters can be created");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (param->category == AudioProcessorParameter::Category::inputMeter);
|
||||
}
|
||||
|
||||
beginTest ("Boolean parameters can be created");
|
||||
{
|
||||
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));
|
||||
|
||||
expect (param->isBoolean());
|
||||
}
|
||||
|
||||
beginTest ("After creating a custom named parameter, we can later retrieve that parameter");
|
||||
{
|
||||
const auto key = "id";
|
||||
auto param = std::make_unique<AudioParameterBool> (key, "", false);
|
||||
const auto paramPtr = param.get();
|
||||
|
||||
TestAudioProcessor proc (std::move (param));
|
||||
|
||||
expect (proc.state.getParameter (key) == paramPtr);
|
||||
}
|
||||
|
||||
beginTest ("After adding a normal parameter that already exists, the AudioProcessor parameters are unchanged");
|
||||
{
|
||||
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));
|
||||
|
||||
proc.state.createAndAddParameter (std::make_unique<Parameter> (key, String(), String(), NormalisableRange<float>(),
|
||||
0.0f, nullptr, nullptr));
|
||||
|
||||
expectEquals (proc.getParameters().size(), 1);
|
||||
expect (proc.getParameters().getFirst() == param);
|
||||
}
|
||||
|
||||
beginTest ("After setting a parameter value, that value is reflected in the state");
|
||||
{
|
||||
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 value = 0.5f;
|
||||
param->setValueNotifyingHost (value);
|
||||
|
||||
expectEquals (proc.state.getRawParameterValue (key)->load(), value);
|
||||
}
|
||||
|
||||
beginTest ("After adding an APVTS::Parameter, its value is the default value");
|
||||
{
|
||||
TestAudioProcessor proc;
|
||||
const auto key = "id";
|
||||
const auto value = 5.0f;
|
||||
|
||||
proc.state.createAndAddParameter (std::make_unique<Parameter> (
|
||||
key,
|
||||
String(),
|
||||
String(),
|
||||
NormalisableRange<float> (0.0f, 100.0f, 10.0f),
|
||||
value,
|
||||
nullptr,
|
||||
nullptr));
|
||||
|
||||
expectEquals (proc.state.getRawParameterValue (key)->load(), value);
|
||||
}
|
||||
|
||||
beginTest ("Listeners receive notifications when parameters change");
|
||||
{
|
||||
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));
|
||||
proc.state.addParameterListener (key, &listener);
|
||||
|
||||
const auto value = 0.5f;
|
||||
param->setValueNotifyingHost (value);
|
||||
|
||||
expectEquals (listener.id, String { key });
|
||||
expectEquals (listener.value, value);
|
||||
}
|
||||
|
||||
beginTest ("Bool parameters have a range of 0-1");
|
||||
{
|
||||
const auto key = "id";
|
||||
|
||||
TestAudioProcessor proc (std::make_unique<AudioParameterBool> (key, "", false));
|
||||
|
||||
expect (proc.state.getParameterRange (key) == NormalisableRange<float> (0.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
beginTest ("Float parameters retain their specified range");
|
||||
{
|
||||
const auto key = "id";
|
||||
const auto range = NormalisableRange<float> { -100, 100, 0.7f, 0.2f, true };
|
||||
|
||||
TestAudioProcessor proc (std::make_unique<AudioParameterFloat> (key, "", range, 0.0f));
|
||||
|
||||
expect (proc.state.getParameterRange (key) == range);
|
||||
}
|
||||
|
||||
beginTest ("Int parameters retain their specified range");
|
||||
{
|
||||
const auto key = "id";
|
||||
const auto min = -27;
|
||||
const auto max = 53;
|
||||
|
||||
TestAudioProcessor proc (std::make_unique<AudioParameterInt> (key, "", min, max, 0));
|
||||
|
||||
expect (proc.state.getParameterRange (key) == NormalisableRange<float> (float (min), float (max), 1.0f));
|
||||
}
|
||||
|
||||
beginTest ("Choice parameters retain their specified range");
|
||||
{
|
||||
const auto key = "id";
|
||||
const auto choices = StringArray { "", "", "" };
|
||||
|
||||
TestAudioProcessor proc (std::make_unique<AudioParameterChoice> (key, "", choices, 0));
|
||||
|
||||
expect (proc.state.getParameterRange (key) == NormalisableRange<float> (0.0f, (float) (choices.size() - 1), 1.0f));
|
||||
expect (proc.state.getParameter (key)->getNumSteps() == choices.size());
|
||||
}
|
||||
|
||||
beginTest ("When the parameter value is changed, normal parameter values are updated");
|
||||
{
|
||||
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));
|
||||
proc.state.state = ValueTree { "state" };
|
||||
|
||||
auto value = proc.state.getParameterAsValue (key);
|
||||
expectEquals (float (value.getValue()), initialValue);
|
||||
|
||||
const auto newValue = 0.75f;
|
||||
value = newValue;
|
||||
|
||||
expectEquals (param->getValue(), newValue);
|
||||
expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);
|
||||
}
|
||||
|
||||
beginTest ("When the parameter value is changed, custom parameter values are updated");
|
||||
{
|
||||
const auto key = "id";
|
||||
const auto choices = StringArray ("foo", "bar", "baz");
|
||||
auto param = std::make_unique<AudioParameterChoice> (key, "", choices, 0);
|
||||
const auto paramPtr = param.get();
|
||||
TestAudioProcessor proc (std::move (param));
|
||||
|
||||
const auto newValue = 2.0f;
|
||||
auto value = proc.state.getParameterAsValue (key);
|
||||
value = newValue;
|
||||
|
||||
expectEquals (paramPtr->getCurrentChoiceName(), choices[int (newValue)]);
|
||||
expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);
|
||||
}
|
||||
|
||||
beginTest ("When the parameter value is changed, listeners are notified");
|
||||
{
|
||||
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.addParameterListener (key, &listener);
|
||||
proc.state.state = ValueTree { "state" };
|
||||
|
||||
const auto newValue = 0.75f;
|
||||
proc.state.getParameterAsValue (key) = newValue;
|
||||
|
||||
expectEquals (listener.value, newValue);
|
||||
expectEquals (listener.id, String { key });
|
||||
}
|
||||
|
||||
beginTest ("When the parameter value is changed, listeners are notified");
|
||||
{
|
||||
const auto key = "id";
|
||||
const auto choices = StringArray { "foo", "bar", "baz" };
|
||||
Listener listener;
|
||||
TestAudioProcessor proc (std::make_unique<AudioParameterChoice> (key, "", choices, 0));
|
||||
proc.state.addParameterListener (key, &listener);
|
||||
|
||||
const auto newValue = 2.0f;
|
||||
proc.state.getParameterAsValue (key) = newValue;
|
||||
|
||||
expectEquals (listener.value, newValue);
|
||||
expectEquals (listener.id, String (key));
|
||||
}
|
||||
}
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
};
|
||||
|
||||
static AudioProcessorValueTreeStateTests audioProcessorValueTreeStateTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
563
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
vendored
Normal file
563
deps/juce/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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 class contains a ValueTree that is used to manage an AudioProcessor's entire state.
|
||||
|
||||
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,
|
||||
so you can add extra properties to it as necessary.
|
||||
|
||||
It also provides some utility child classes for connecting parameters directly to
|
||||
GUI controls like sliders.
|
||||
|
||||
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,
|
||||
private ValueTree::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** A class to contain a set of RangedAudioParameters and AudioProcessorParameterGroups
|
||||
containing RangedAudioParameters.
|
||||
|
||||
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 call `add` repeatedly on a
|
||||
ParameterLayout instance:
|
||||
|
||||
@code
|
||||
AudioProcessorValueTreeState::ParameterLayout createParameterLayout()
|
||||
{
|
||||
AudioProcessorValueTreeState::ParameterLayout layout;
|
||||
|
||||
for (int i = 1; i < 9; ++i)
|
||||
layout.add (std::make_unique<AudioParameterInt> (String (i), String (i), 0, i, 0));
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
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,
|
||||
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() override;
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
/** 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.
|
||||
*/
|
||||
[[deprecated ("This function is deprecated and will be removed in a future version of JUCE! "
|
||||
"See the method docs for a code example of the replacement methods.")]]
|
||||
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 parameterCategory = AudioProcessorParameter::genericParameter,
|
||||
bool isBoolean = false);
|
||||
#endif
|
||||
|
||||
/** 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. */
|
||||
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.
|
||||
|
||||
Note that calling this method from within AudioProcessorValueTreeState::Listener::parameterChanged()
|
||||
is not guaranteed to return an up-to-date value for the parameter.
|
||||
*/
|
||||
std::atomic<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
|
||||
{
|
||||
virtual ~Listener() = default;
|
||||
|
||||
/** 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;
|
||||
};
|
||||
|
||||
/** Attaches a callback to one of the parameters, which will be called when the parameter changes. */
|
||||
void addParameterListener (StringRef parameterID, Listener* listener);
|
||||
|
||||
/** 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
|
||||
message thread, but there may be cases when you may want to access the state
|
||||
from a different thread (getStateInformation is a good example). This method
|
||||
flushes all pending audio parameter value updates and returns a copy of the
|
||||
state in a thread safe way.
|
||||
|
||||
Note: This method uses locks to synchronise thread access, so whilst it is
|
||||
thread-safe, it is not realtime-safe. Do not call this method from within
|
||||
your audio processing code!
|
||||
*/
|
||||
ValueTree copyState();
|
||||
|
||||
/** Replaces the state value tree.
|
||||
|
||||
The AudioProcessorValueTreeState's ValueTree is updated internally on the
|
||||
message thread, but there may be cases when you may want to modify the state
|
||||
from a different thread (setStateInformation is a good example). This method
|
||||
allows you to replace the state in a thread safe way.
|
||||
|
||||
Note: This method uses locks to synchronise thread access, so whilst it is
|
||||
thread-safe, it is not realtime-safe. Do not call this method from within
|
||||
your audio processing code!
|
||||
*/
|
||||
void replaceState (const ValueTree& newState);
|
||||
|
||||
//==============================================================================
|
||||
/** A reference to the processor with which this state is associated. */
|
||||
AudioProcessor& processor;
|
||||
|
||||
/** The state of the whole processor.
|
||||
|
||||
This must be initialised after all calls to createAndAddParameter().
|
||||
You can replace this with your own ValueTree object, and can add properties and
|
||||
children to the tree. This class will automatically add children for each of the
|
||||
parameter objects that are created by createAndAddParameter().
|
||||
*/
|
||||
ValueTree state;
|
||||
|
||||
/** Provides access to the undo manager that this object is using. */
|
||||
UndoManager* const undoManager;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class ParameterAdapter;
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
/** 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 parameterCategory = 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:
|
||||
void valueChanged (float) override;
|
||||
|
||||
std::function<void()> onValueChanged;
|
||||
|
||||
const float unsnappedDefault;
|
||||
const bool metaParameter, automatable, discrete, boolean;
|
||||
std::atomic<float> lastValue { -1.0f };
|
||||
|
||||
friend class AudioProcessorValueTreeState::ParameterAdapter;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a Slider and a parameter
|
||||
in an AudioProcessorValueTreeState.
|
||||
|
||||
During the lifetime of this SliderAttachment object, it keeps the two things in
|
||||
sync, making it easy to connect a slider to a parameter. When this object is
|
||||
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
|
||||
and Slider aren't deleted before this object!
|
||||
*/
|
||||
class JUCE_API SliderAttachment
|
||||
{
|
||||
public:
|
||||
SliderAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
Slider& slider);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SliderParameterAttachment> attachment;
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** 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
|
||||
and ComboBox aren't deleted before this object!
|
||||
*/
|
||||
class JUCE_API ComboBoxAttachment
|
||||
{
|
||||
public:
|
||||
ComboBoxAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
ComboBox& combo);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ComboBoxParameterAttachment> attachment;
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a Button and a parameter
|
||||
in an AudioProcessorValueTreeState.
|
||||
|
||||
During the lifetime of this ButtonAttachment object, it keeps the two things in
|
||||
sync, making it easy to connect a button to a parameter. When this object is
|
||||
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
|
||||
and Button aren't deleted before this object!
|
||||
*/
|
||||
class JUCE_API ButtonAttachment
|
||||
{
|
||||
public:
|
||||
ButtonAttachment (AudioProcessorValueTreeState& stateToUse,
|
||||
const String& parameterID,
|
||||
Button& button);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ButtonParameterAttachment> attachment;
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment)
|
||||
};
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
/** 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
|
||||
*/
|
||||
[[deprecated ("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. See the "
|
||||
"method docs for a code example.")]]
|
||||
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);
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
friend struct ParameterAdapterTests;
|
||||
#endif
|
||||
|
||||
void addParameterAdapter (RangedAudioParameter&);
|
||||
ParameterAdapter* getParameterAdapter (StringRef) const;
|
||||
|
||||
bool flushParameterValuesToValueTree();
|
||||
void setNewState (ValueTree);
|
||||
void timerCallback() override;
|
||||
|
||||
void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
|
||||
void valueTreeChildAdded (ValueTree&, ValueTree&) override;
|
||||
void valueTreeRedirected (ValueTree&) override;
|
||||
void updateParameterConnectionsToChildTrees();
|
||||
|
||||
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;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorValueTreeState)
|
||||
};
|
||||
|
||||
} // namespace juce
|
88
deps/juce/modules/juce_audio_processors/utilities/juce_ExtensionsVisitor.h
vendored
Normal file
88
deps/juce/modules/juce_audio_processors/utilities/juce_ExtensionsVisitor.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Create a derived implementation of this class and pass it to
|
||||
AudioPluginInstance::getExtensions() to retrieve format-specific
|
||||
information about a plugin instance.
|
||||
|
||||
Note that the references passed to the visit member functions are only
|
||||
guaranteed to live for the duration of the function call, so don't
|
||||
store pointers to these objects! If you need to store and reuse
|
||||
format-specific information, it is recommended to copy the result
|
||||
of the function calls that you care about. For example, you should
|
||||
store the result of VST::getAEffectPtr() rather than storing a pointer
|
||||
to the VST instance.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct ExtensionsVisitor
|
||||
{
|
||||
/** Indicates that there is no platform specific information available. */
|
||||
struct Unknown {};
|
||||
|
||||
/** Can be used to retrieve information about a VST3 that is wrapped by an AudioProcessor. */
|
||||
struct VST3Client
|
||||
{
|
||||
virtual ~VST3Client() = default;
|
||||
virtual void* getIComponentPtr() const noexcept = 0;
|
||||
|
||||
virtual MemoryBlock getPreset() const = 0;
|
||||
virtual bool setPreset (const MemoryBlock&) const = 0;
|
||||
};
|
||||
|
||||
/** Can be used to retrieve information about an AudioUnit that is wrapped by an AudioProcessor. */
|
||||
struct AudioUnitClient
|
||||
{
|
||||
virtual ~AudioUnitClient() = default;
|
||||
virtual void* getAudioUnitHandle() const noexcept = 0;
|
||||
};
|
||||
|
||||
/** Can be used to retrieve information about a VST that is wrapped by an AudioProcessor. */
|
||||
struct VSTClient
|
||||
{
|
||||
virtual ~VSTClient() = default;
|
||||
virtual void* getAEffectPtr() const noexcept = 0;
|
||||
};
|
||||
|
||||
virtual ~ExtensionsVisitor() = default;
|
||||
|
||||
/** Will be called if there is no platform specific information available. */
|
||||
virtual void visitUnknown (const Unknown&) {}
|
||||
|
||||
/** Called with VST3-specific information. */
|
||||
virtual void visitVST3Client (const VST3Client&) {}
|
||||
|
||||
/** Called with VST-specific information. */
|
||||
virtual void visitVSTClient (const VSTClient&) {}
|
||||
|
||||
/** Called with AU-specific information. */
|
||||
virtual void visitAudioUnitClient (const AudioUnitClient&) {}
|
||||
};
|
||||
|
||||
} // namespace juce
|
271
deps/juce/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp
vendored
Normal file
271
deps/juce/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
ParameterAttachment::ParameterAttachment (RangedAudioParameter& param,
|
||||
std::function<void (float)> parameterChangedCallback,
|
||||
UndoManager* um)
|
||||
: parameter (param),
|
||||
undoManager (um),
|
||||
setValue (std::move (parameterChangedCallback))
|
||||
{
|
||||
parameter.addListener (this);
|
||||
}
|
||||
|
||||
ParameterAttachment::~ParameterAttachment()
|
||||
{
|
||||
parameter.removeListener (this);
|
||||
cancelPendingUpdate();
|
||||
}
|
||||
|
||||
void ParameterAttachment::sendInitialUpdate()
|
||||
{
|
||||
parameterValueChanged ({}, parameter.getValue());
|
||||
}
|
||||
|
||||
void ParameterAttachment::setValueAsCompleteGesture (float newDenormalisedValue)
|
||||
{
|
||||
callIfParameterValueChanged (newDenormalisedValue, [this] (float f)
|
||||
{
|
||||
beginGesture();
|
||||
parameter.setValueNotifyingHost (f);
|
||||
endGesture();
|
||||
});
|
||||
}
|
||||
|
||||
void ParameterAttachment::beginGesture()
|
||||
{
|
||||
if (undoManager != nullptr)
|
||||
undoManager->beginNewTransaction();
|
||||
|
||||
parameter.beginChangeGesture();
|
||||
}
|
||||
|
||||
void ParameterAttachment::setValueAsPartOfGesture (float newDenormalisedValue)
|
||||
{
|
||||
callIfParameterValueChanged (newDenormalisedValue, [this] (float f)
|
||||
{
|
||||
parameter.setValueNotifyingHost (f);
|
||||
});
|
||||
}
|
||||
|
||||
void ParameterAttachment::endGesture()
|
||||
{
|
||||
parameter.endChangeGesture();
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void ParameterAttachment::callIfParameterValueChanged (float newDenormalisedValue,
|
||||
Callback&& callback)
|
||||
{
|
||||
const auto newValue = normalise (newDenormalisedValue);
|
||||
|
||||
if (parameter.getValue() != newValue)
|
||||
callback (newValue);
|
||||
}
|
||||
|
||||
void ParameterAttachment::parameterValueChanged (int, float newValue)
|
||||
{
|
||||
lastValue = newValue;
|
||||
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
{
|
||||
cancelPendingUpdate();
|
||||
handleAsyncUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterAttachment::handleAsyncUpdate()
|
||||
{
|
||||
if (setValue != nullptr)
|
||||
setValue (parameter.convertFrom0to1 (lastValue));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
SliderParameterAttachment::SliderParameterAttachment (RangedAudioParameter& param,
|
||||
Slider& s,
|
||||
UndoManager* um)
|
||||
: slider (s),
|
||||
attachment (param, [this] (float f) { setValue (f); }, um)
|
||||
{
|
||||
slider.valueFromTextFunction = [¶m] (const String& text) { return (double) param.convertFrom0to1 (param.getValueForText (text)); };
|
||||
slider.textFromValueFunction = [¶m] (double value) { return param.getText (param.convertTo0to1 ((float) value), 0); };
|
||||
slider.setDoubleClickReturnValue (true, param.convertFrom0to1 (param.getDefaultValue()));
|
||||
|
||||
auto range = param.getNormalisableRange();
|
||||
|
||||
auto convertFrom0To1Function = [range] (double currentRangeStart,
|
||||
double currentRangeEnd,
|
||||
double normalisedValue) mutable
|
||||
{
|
||||
range.start = (float) currentRangeStart;
|
||||
range.end = (float) currentRangeEnd;
|
||||
return (double) range.convertFrom0to1 ((float) normalisedValue);
|
||||
};
|
||||
|
||||
auto convertTo0To1Function = [range] (double currentRangeStart,
|
||||
double currentRangeEnd,
|
||||
double mappedValue) mutable
|
||||
{
|
||||
range.start = (float) currentRangeStart;
|
||||
range.end = (float) currentRangeEnd;
|
||||
return (double) range.convertTo0to1 ((float) mappedValue);
|
||||
};
|
||||
|
||||
auto snapToLegalValueFunction = [range] (double currentRangeStart,
|
||||
double currentRangeEnd,
|
||||
double mappedValue) mutable
|
||||
{
|
||||
range.start = (float) currentRangeStart;
|
||||
range.end = (float) currentRangeEnd;
|
||||
return (double) range.snapToLegalValue ((float) mappedValue);
|
||||
};
|
||||
|
||||
NormalisableRange<double> newRange { (double) range.start,
|
||||
(double) range.end,
|
||||
std::move (convertFrom0To1Function),
|
||||
std::move (convertTo0To1Function),
|
||||
std::move (snapToLegalValueFunction) };
|
||||
newRange.interval = range.interval;
|
||||
newRange.skew = range.skew;
|
||||
newRange.symmetricSkew = range.symmetricSkew;
|
||||
|
||||
slider.setNormalisableRange (newRange);
|
||||
|
||||
sendInitialUpdate();
|
||||
slider.valueChanged();
|
||||
slider.addListener (this);
|
||||
}
|
||||
|
||||
SliderParameterAttachment::~SliderParameterAttachment()
|
||||
{
|
||||
slider.removeListener (this);
|
||||
}
|
||||
|
||||
void SliderParameterAttachment::sendInitialUpdate() { attachment.sendInitialUpdate(); }
|
||||
|
||||
void SliderParameterAttachment::setValue (float newValue)
|
||||
{
|
||||
const ScopedValueSetter<bool> svs (ignoreCallbacks, true);
|
||||
slider.setValue (newValue, sendNotificationSync);
|
||||
}
|
||||
|
||||
void SliderParameterAttachment::sliderValueChanged (Slider*)
|
||||
{
|
||||
if (ignoreCallbacks || ModifierKeys::currentModifiers.isRightButtonDown())
|
||||
return;
|
||||
|
||||
attachment.setValueAsPartOfGesture ((float) slider.getValue());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ComboBoxParameterAttachment::ComboBoxParameterAttachment (RangedAudioParameter& param,
|
||||
ComboBox& c,
|
||||
UndoManager* um)
|
||||
: comboBox (c),
|
||||
storedParameter (param),
|
||||
attachment (param, [this] (float f) { setValue (f); }, um)
|
||||
{
|
||||
sendInitialUpdate();
|
||||
comboBox.addListener (this);
|
||||
}
|
||||
|
||||
ComboBoxParameterAttachment::~ComboBoxParameterAttachment()
|
||||
{
|
||||
comboBox.removeListener (this);
|
||||
}
|
||||
|
||||
void ComboBoxParameterAttachment::sendInitialUpdate()
|
||||
{
|
||||
attachment.sendInitialUpdate();
|
||||
}
|
||||
|
||||
void ComboBoxParameterAttachment::setValue (float newValue)
|
||||
{
|
||||
const auto normValue = storedParameter.convertTo0to1 (newValue);
|
||||
const auto index = roundToInt (normValue * (float) (comboBox.getNumItems() - 1));
|
||||
|
||||
if (index == comboBox.getSelectedItemIndex())
|
||||
return;
|
||||
|
||||
const ScopedValueSetter<bool> svs (ignoreCallbacks, true);
|
||||
comboBox.setSelectedItemIndex (index, sendNotificationSync);
|
||||
}
|
||||
|
||||
void ComboBoxParameterAttachment::comboBoxChanged (ComboBox*)
|
||||
{
|
||||
if (ignoreCallbacks)
|
||||
return;
|
||||
|
||||
const auto numItems = comboBox.getNumItems();
|
||||
const auto selected = (float) comboBox.getSelectedItemIndex();
|
||||
const auto newValue = numItems > 1 ? selected / (float) (numItems - 1)
|
||||
: 0.0f;
|
||||
|
||||
attachment.setValueAsCompleteGesture (storedParameter.convertFrom0to1 (newValue));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ButtonParameterAttachment::ButtonParameterAttachment (RangedAudioParameter& param,
|
||||
Button& b,
|
||||
UndoManager* um)
|
||||
: button (b),
|
||||
attachment (param, [this] (float f) { setValue (f); }, um)
|
||||
{
|
||||
sendInitialUpdate();
|
||||
button.addListener (this);
|
||||
}
|
||||
|
||||
ButtonParameterAttachment::~ButtonParameterAttachment()
|
||||
{
|
||||
button.removeListener (this);
|
||||
}
|
||||
|
||||
void ButtonParameterAttachment::sendInitialUpdate()
|
||||
{
|
||||
attachment.sendInitialUpdate();
|
||||
}
|
||||
|
||||
void ButtonParameterAttachment::setValue (float newValue)
|
||||
{
|
||||
const ScopedValueSetter<bool> svs (ignoreCallbacks, true);
|
||||
button.setToggleState (newValue >= 0.5f, sendNotificationSync);
|
||||
}
|
||||
|
||||
void ButtonParameterAttachment::buttonClicked (Button*)
|
||||
{
|
||||
if (ignoreCallbacks)
|
||||
return;
|
||||
|
||||
attachment.setValueAsCompleteGesture (button.getToggleState() ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
} // namespace juce
|
251
deps/juce/modules/juce_audio_processors/utilities/juce_ParameterAttachments.h
vendored
Normal file
251
deps/juce/modules/juce_audio_processors/utilities/juce_ParameterAttachments.h
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/** Used to implement 'attachments' or 'controllers' that link a plug-in
|
||||
parameter to a UI element.
|
||||
|
||||
To implement a new attachment type, create a new class which includes an
|
||||
instance of this class as a data member. Your class should pass a function
|
||||
to the constructor of the ParameterAttachment, which will then be called on
|
||||
the message thread when the parameter changes. You can use this function to
|
||||
update the state of the UI control. Your class should also register as a
|
||||
listener of the UI control and respond to respond to changes in the UI element
|
||||
by calling either setValueAsCompleteGesture or beginGesture,
|
||||
setValueAsPartOfGesture and endGesture.
|
||||
|
||||
Make sure to call `sendInitialUpdate` at the end of your new attachment's
|
||||
constructor, so that the UI immediately reflects the state of the parameter.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class ParameterAttachment : private AudioProcessorParameter::Listener,
|
||||
private AsyncUpdater
|
||||
{
|
||||
public:
|
||||
/** Listens to a parameter and calls the the provided function in response to
|
||||
parameter changes. If an undoManager is supplied `beginNewTransaction` will
|
||||
be called on it whenever the UI requests a parameter change via this attachment.
|
||||
|
||||
@param parameter The parameter to which this attachment will listen
|
||||
@param parameterChangedCallback The function that will be called on the message thread in response
|
||||
to parameter changes
|
||||
@param undoManager The UndoManager that will be used to begin transactions when the UI
|
||||
requests a parameter change.
|
||||
*/
|
||||
ParameterAttachment (RangedAudioParameter& parameter,
|
||||
std::function<void (float)> parameterChangedCallback,
|
||||
UndoManager* undoManager = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~ParameterAttachment() override;
|
||||
|
||||
/** Calls the parameterChangedCallback function that was registered in
|
||||
the constructor, making the UI reflect the current parameter state.
|
||||
|
||||
This function should be called after doing any necessary setup on
|
||||
the UI control that is being managed (e.g. adding ComboBox entries,
|
||||
making buttons toggle-able).
|
||||
*/
|
||||
void sendInitialUpdate();
|
||||
|
||||
/** Triggers a full gesture message on the managed parameter.
|
||||
|
||||
Call this in the listener callback of the UI control in response
|
||||
to a one-off change in the UI like a button-press.
|
||||
*/
|
||||
void setValueAsCompleteGesture (float newDenormalisedValue);
|
||||
|
||||
/** Begins a gesture on the managed parameter.
|
||||
|
||||
Call this when the UI is about to begin a continuous interaction,
|
||||
like when the mouse button is pressed on a slider.
|
||||
*/
|
||||
void beginGesture();
|
||||
|
||||
/** Updates the parameter value during a gesture.
|
||||
|
||||
Call this during a continuous interaction, like a slider value
|
||||
changed callback.
|
||||
*/
|
||||
void setValueAsPartOfGesture (float newDenormalisedValue);
|
||||
|
||||
/** Ends a gesture on the managed parameter.
|
||||
|
||||
Call this when the UI has finished a continuous interaction,
|
||||
like when the mouse button is released on a slider.
|
||||
*/
|
||||
void endGesture();
|
||||
|
||||
private:
|
||||
float normalise (float f) const { return parameter.convertTo0to1 (f); }
|
||||
|
||||
template <typename Callback>
|
||||
void callIfParameterValueChanged (float newDenormalisedValue, Callback&& callback);
|
||||
|
||||
void parameterValueChanged (int, float) override;
|
||||
void parameterGestureChanged (int, bool) override {}
|
||||
void handleAsyncUpdate() override;
|
||||
|
||||
RangedAudioParameter& parameter;
|
||||
std::atomic<float> lastValue { 0.0f };
|
||||
UndoManager* undoManager = nullptr;
|
||||
std::function<void (float)> setValue;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterAttachment)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a Slider and a
|
||||
plug-in parameter.
|
||||
|
||||
During the lifetime of this object it keeps the two things in sync, making
|
||||
it easy to connect a slider to a parameter. When this object is deleted, the
|
||||
connection is broken. Make sure that your parameter and Slider are not
|
||||
deleted before this object!
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class SliderParameterAttachment : private Slider::Listener
|
||||
{
|
||||
public:
|
||||
/** Creates a connection between a plug-in parameter and a Slider.
|
||||
|
||||
@param parameter The parameter to use
|
||||
@param slider The Slider to use
|
||||
@param undoManager An optional UndoManager
|
||||
*/
|
||||
SliderParameterAttachment (RangedAudioParameter& parameter, Slider& slider,
|
||||
UndoManager* undoManager = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~SliderParameterAttachment() override;
|
||||
|
||||
/** Call this after setting up your slider in the case where you need to do
|
||||
extra setup after constructing this attachment.
|
||||
*/
|
||||
void sendInitialUpdate();
|
||||
|
||||
private:
|
||||
void setValue (float newValue);
|
||||
void sliderValueChanged (Slider*) override;
|
||||
|
||||
void sliderDragStarted (Slider*) override { attachment.beginGesture(); }
|
||||
void sliderDragEnded (Slider*) override { attachment.endGesture(); }
|
||||
|
||||
Slider& slider;
|
||||
ParameterAttachment attachment;
|
||||
bool ignoreCallbacks = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a ComboBox and a
|
||||
plug-in parameter.
|
||||
|
||||
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 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 parameter and ComboBox are not deleted
|
||||
before this object!
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class ComboBoxParameterAttachment : private ComboBox::Listener
|
||||
{
|
||||
public:
|
||||
/** Creates a connection between a plug-in parameter and a ComboBox.
|
||||
|
||||
@param parameter The parameter to use
|
||||
@param combo The ComboBox to use
|
||||
@param undoManager An optional UndoManager
|
||||
*/
|
||||
ComboBoxParameterAttachment (RangedAudioParameter& parameter, ComboBox& combo,
|
||||
UndoManager* undoManager = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~ComboBoxParameterAttachment() override;
|
||||
|
||||
/** Call this after setting up your combo box in the case where you need to do
|
||||
extra setup after constructing this attachment.
|
||||
*/
|
||||
void sendInitialUpdate();
|
||||
|
||||
private:
|
||||
void setValue (float newValue);
|
||||
void comboBoxChanged (ComboBox*) override;
|
||||
|
||||
ComboBox& comboBox;
|
||||
RangedAudioParameter& storedParameter;
|
||||
ParameterAttachment attachment;
|
||||
bool ignoreCallbacks = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An object of this class maintains a connection between a Button and a
|
||||
plug-in parameter.
|
||||
|
||||
During the lifetime of this object it keeps the two things in sync, making it
|
||||
easy to connect a button to a parameter. When this object is deleted, the
|
||||
connection is broken. Make sure that your parameter and Button are not deleted
|
||||
before this object!
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class ButtonParameterAttachment : private Button::Listener
|
||||
{
|
||||
public:
|
||||
/** Creates a connection between a plug-in parameter and a Button.
|
||||
|
||||
@param parameter The parameter to use
|
||||
@param button The Button to use
|
||||
@param undoManager An optional UndoManager
|
||||
*/
|
||||
ButtonParameterAttachment (RangedAudioParameter& parameter, Button& button,
|
||||
UndoManager* undoManager = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~ButtonParameterAttachment() override;
|
||||
|
||||
/** Call this after setting up your button in the case where you need to do
|
||||
extra setup after constructing this attachment.
|
||||
*/
|
||||
void sendInitialUpdate();
|
||||
|
||||
private:
|
||||
void setValue (float newValue);
|
||||
void buttonClicked (Button*) override;
|
||||
|
||||
Button& button;
|
||||
ParameterAttachment attachment;
|
||||
bool ignoreCallbacks = false;
|
||||
};
|
||||
|
||||
} // namespace juce
|
315
deps/juce/modules/juce_audio_processors/utilities/juce_PluginHostType.cpp
vendored
Normal file
315
deps/juce/modules/juce_audio_processors/utilities/juce_PluginHostType.cpp
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)
|
||||
bool JUCE_CALLTYPE juce_isInterAppAudioConnected();
|
||||
void JUCE_CALLTYPE juce_switchToHostApplication();
|
||||
juce::Image JUCE_CALLTYPE juce_getIAAHostIcon (int);
|
||||
#endif
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
Image JUCE_API getIconFromApplication (const String&, const int);
|
||||
|
||||
AudioProcessor::WrapperType PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Undefined;
|
||||
std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudioSuiteFn = nullptr;
|
||||
String PluginHostType::hostIdReportedByWrapper;
|
||||
|
||||
bool PluginHostType::isInterAppAudioConnected() const
|
||||
{
|
||||
#if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)
|
||||
if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone)
|
||||
return juce_isInterAppAudioConnected();
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PluginHostType::switchToHostApplication() const
|
||||
{
|
||||
#if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)
|
||||
if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone)
|
||||
juce_switchToHostApplication();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor)
|
||||
{
|
||||
#if JucePlugin_Build_AAX
|
||||
if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX
|
||||
&& jucePlugInIsRunningInAudioSuiteFn != nullptr)
|
||||
{
|
||||
return jucePlugInIsRunningInAudioSuiteFn (processor);
|
||||
}
|
||||
#endif
|
||||
|
||||
ignoreUnused (processor);
|
||||
return false;
|
||||
}
|
||||
|
||||
Image PluginHostType::getHostIcon (int size) const
|
||||
{
|
||||
ignoreUnused (size);
|
||||
|
||||
#if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)
|
||||
if (isInterAppAudioConnected())
|
||||
return juce_getIAAHostIcon (size);
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
String bundlePath (getHostPath().upToLastOccurrenceOf (".app", true, true));
|
||||
return getIconFromApplication (bundlePath, size);
|
||||
#endif
|
||||
|
||||
return Image();
|
||||
}
|
||||
|
||||
const char* PluginHostType::getHostDescription() const noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AbletonLive6: return "Ableton Live 6";
|
||||
case AbletonLive7: return "Ableton Live 7";
|
||||
case AbletonLive8: return "Ableton Live 8";
|
||||
case AbletonLive9: return "Ableton Live 9";
|
||||
case AbletonLive10: return "Ableton Live 10";
|
||||
case AbletonLive11: return "Ableton Live 11";
|
||||
case AbletonLiveGeneric: return "Ableton Live";
|
||||
case AdobeAudition: return "Adobe Audition";
|
||||
case AdobePremierePro: return "Adobe Premiere";
|
||||
case AppleGarageBand: return "Apple GarageBand";
|
||||
case AppleLogic: return "Apple Logic";
|
||||
case AppleMainStage: return "Apple MainStage";
|
||||
case Ardour: return "Ardour";
|
||||
case AULab: return "AU Lab";
|
||||
case AvidProTools: return "ProTools";
|
||||
case BitwigStudio: return "Bitwig Studio";
|
||||
case CakewalkSonar8: return "Cakewalk Sonar 8";
|
||||
case CakewalkSonarGeneric: return "Cakewalk Sonar";
|
||||
case CakewalkByBandlab: return "Cakewalk by Bandlab";
|
||||
case DaVinciResolve: return "DaVinci Resolve";
|
||||
case DigitalPerformer: return "DigitalPerformer";
|
||||
case FinalCut: return "Final Cut";
|
||||
case FruityLoops: return "FruityLoops";
|
||||
case JUCEPluginHost: return "JUCE AudioPluginHost";
|
||||
case MagixSamplitude: return "Magix Samplitude";
|
||||
case MagixSequoia: return "Magix Sequoia";
|
||||
case pluginval: return "pluginval";
|
||||
case MergingPyramix: return "Pyramix";
|
||||
case MuseReceptorGeneric: return "Muse Receptor";
|
||||
case Reaper: return "Reaper";
|
||||
case Reason: return "Reason";
|
||||
case Renoise: return "Renoise";
|
||||
case SADiE: return "SADiE";
|
||||
case SteinbergCubase4: return "Steinberg Cubase 4";
|
||||
case SteinbergCubase5: return "Steinberg Cubase 5";
|
||||
case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged";
|
||||
case SteinbergCubase6: return "Steinberg Cubase 6";
|
||||
case SteinbergCubase7: return "Steinberg Cubase 7";
|
||||
case SteinbergCubase8: return "Steinberg Cubase 8";
|
||||
case SteinbergCubase8_5: return "Steinberg Cubase 8.5";
|
||||
case SteinbergCubase9: return "Steinberg Cubase 9";
|
||||
case SteinbergCubase9_5: return "Steinberg Cubase 9.5";
|
||||
case SteinbergCubase10: return "Steinberg Cubase 10";
|
||||
case SteinbergCubase10_5: return "Steinberg Cubase 10.5";
|
||||
case SteinbergCubaseGeneric: return "Steinberg Cubase";
|
||||
case SteinbergNuendo3: return "Steinberg Nuendo 3";
|
||||
case SteinbergNuendo4: return "Steinberg Nuendo 4";
|
||||
case SteinbergNuendo5: return "Steinberg Nuendo 5";
|
||||
case SteinbergNuendoGeneric: return "Steinberg Nuendo";
|
||||
case SteinbergWavelab5: return "Steinberg Wavelab 5";
|
||||
case SteinbergWavelab6: return "Steinberg Wavelab 6";
|
||||
case SteinbergWavelab7: return "Steinberg Wavelab 7";
|
||||
case SteinbergWavelab8: return "Steinberg Wavelab 8";
|
||||
case SteinbergWavelabGeneric: return "Steinberg Wavelab";
|
||||
case SteinbergTestHost: return "Steinberg TestHost";
|
||||
case StudioOne: return "Studio One";
|
||||
case Tracktion3: return "Tracktion 3";
|
||||
case TracktionGeneric: return "Tracktion";
|
||||
case TracktionWaveform: return "Tracktion Waveform";
|
||||
case VBVSTScanner: return "VBVSTScanner";
|
||||
case ViennaEnsemblePro: return "Vienna Ensemble Pro";
|
||||
case WaveBurner: return "WaveBurner";
|
||||
case UnknownHost:
|
||||
default: break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
PluginHostType::HostType PluginHostType::getHostType()
|
||||
{
|
||||
auto hostPath = getHostPath();
|
||||
auto hostFilename = File (hostPath).getFileName();
|
||||
|
||||
#if JUCE_MAC
|
||||
if (hostPath.containsIgnoreCase ("Final Cut Pro.app")) return FinalCut;
|
||||
if (hostPath.containsIgnoreCase ("Final Cut Pro Trial.app")) return FinalCut;
|
||||
if (hostPath.containsIgnoreCase ("Live 6")) return AbletonLive6;
|
||||
if (hostPath.containsIgnoreCase ("Live 7")) return AbletonLive7;
|
||||
if (hostPath.containsIgnoreCase ("Live 8")) return AbletonLive8;
|
||||
if (hostPath.containsIgnoreCase ("Live 9")) return AbletonLive9;
|
||||
if (hostPath.containsIgnoreCase ("Live 10")) return AbletonLive10;
|
||||
if (hostPath.containsIgnoreCase ("Live 11")) return AbletonLive11;
|
||||
if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition;
|
||||
if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro;
|
||||
if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand;
|
||||
if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic;
|
||||
if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage;
|
||||
if (hostFilename.containsIgnoreCase ("AU Lab")) return AULab;
|
||||
if (hostFilename.containsIgnoreCase ("Pro Tools")) return AvidProTools;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 3")) return SteinbergNuendo3;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 4")) return SteinbergNuendo4;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 5")) return SteinbergNuendo5;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 6")) return SteinbergCubase6;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 7")) return SteinbergCubase7;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 8.app")) return SteinbergCubase8;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 8.5.app")) return SteinbergCubase8_5;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 9.app")) return SteinbergCubase9;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 9.5.app")) return SteinbergCubase9_5;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 10.app")) return SteinbergCubase10;
|
||||
if (hostPath.containsIgnoreCase ("Cubase 10.5.app")) return SteinbergCubase10_5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner;
|
||||
if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer;
|
||||
if (hostFilename.containsIgnoreCase ("reaper")) return Reaper;
|
||||
if (hostFilename.containsIgnoreCase ("Reason")) return Reason;
|
||||
if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne;
|
||||
if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform;
|
||||
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
|
||||
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise;
|
||||
if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve;
|
||||
if (hostFilename.startsWith ("Bitwig")) return BitwigStudio;
|
||||
if (hostFilename.containsIgnoreCase ("OsxFL")) return FruityLoops;
|
||||
if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval;
|
||||
if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost;
|
||||
if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro;
|
||||
|
||||
if (hostIdReportedByWrapper == "com.apple.logic.pro") return AppleLogic;
|
||||
if (hostIdReportedByWrapper == "com.apple.garageband") return AppleGarageBand;
|
||||
if (hostIdReportedByWrapper == "com.apple.mainstage") return AppleMainStage;
|
||||
|
||||
const auto procName = nsStringToJuce ([[NSRunningApplication currentApplication] localizedName]);
|
||||
|
||||
const auto matchesInOrder = [&] (const StringArray& strings)
|
||||
{
|
||||
return procName.matchesWildcard ("AUHostingService*(" + strings.joinIntoString ("*") + ")", false);
|
||||
};
|
||||
|
||||
// Depending on localization settings, spaces are not always plain ascii spaces
|
||||
if (matchesInOrder ({ "Logic", "Pro" })) return AppleLogic;
|
||||
if (matchesInOrder ({ "GarageBand" })) return AppleGarageBand;
|
||||
if (matchesInOrder ({ "MainStage" })) return AppleMainStage;
|
||||
if (matchesInOrder ({ "Final", "Cut", "Pro" })) return FinalCut;
|
||||
|
||||
#elif JUCE_WINDOWS
|
||||
if (hostFilename.containsIgnoreCase ("Live 6")) return AbletonLive6;
|
||||
if (hostFilename.containsIgnoreCase ("Live 7")) return AbletonLive7;
|
||||
if (hostFilename.containsIgnoreCase ("Live 8")) return AbletonLive8;
|
||||
if (hostFilename.containsIgnoreCase ("Live 9")) return AbletonLive9;
|
||||
if (hostFilename.containsIgnoreCase ("Live 10")) return AbletonLive10;
|
||||
if (hostFilename.containsIgnoreCase ("Live 11")) return AbletonLive11;
|
||||
if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition;
|
||||
if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro;
|
||||
if (hostFilename.containsIgnoreCase ("ProTools")) return AvidProTools;
|
||||
if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8;
|
||||
if (hostFilename.containsIgnoreCase ("SONAR")) return CakewalkSonarGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Cakewalk.exe")) return CakewalkByBandlab;
|
||||
if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand;
|
||||
if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic;
|
||||
if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage;
|
||||
if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform;
|
||||
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
|
||||
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("reaper")) return Reaper;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase4")) return SteinbergCubase4;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase5")) return SteinbergCubase5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase6")) return SteinbergCubase6;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase7")) return SteinbergCubase7;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase8.exe")) return SteinbergCubase8;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase8.5.exe")) return SteinbergCubase8_5;
|
||||
// Later version of Cubase scan plug-ins with a separate executable "vst2xscanner"
|
||||
if (hostFilename.containsIgnoreCase ("Cubase9.5.exe")
|
||||
|| hostPath.containsIgnoreCase ("Cubase 9.5")) return SteinbergCubase9_5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase9.exe")
|
||||
|| hostPath.containsIgnoreCase ("Cubase 9")) return SteinbergCubase9;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase10.5.exe")
|
||||
|| hostPath.containsIgnoreCase ("Cubase 10.5")) return SteinbergCubase10_5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase10.exe")
|
||||
|| hostPath.containsIgnoreCase ("Cubase 10")) return SteinbergCubase10;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("VSTBridgeApp")) return SteinbergCubase5Bridged;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 5")) return SteinbergWavelab5;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 6")) return SteinbergWavelab6;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8;
|
||||
if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("TestHost")) return SteinbergTestHost;
|
||||
if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric;
|
||||
if (hostFilename.startsWith ("FL")) return FruityLoops;
|
||||
if (hostFilename.contains ("ilbridge.")) return FruityLoops;
|
||||
if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne;
|
||||
if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer;
|
||||
if (hostFilename.containsIgnoreCase ("VST_Scanner")) return VBVSTScanner;
|
||||
if (hostPath.containsIgnoreCase ("Merging Technologies")) return MergingPyramix;
|
||||
if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude;
|
||||
if (hostFilename.startsWithIgnoreCase ("Sequoia")) return MagixSequoia;
|
||||
if (hostFilename.containsIgnoreCase ("Reason")) return Reason;
|
||||
if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise;
|
||||
if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve;
|
||||
if (hostPath.containsIgnoreCase ("Bitwig Studio")) return BitwigStudio;
|
||||
if (hostFilename.containsIgnoreCase ("Sadie")) return SADiE;
|
||||
if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval;
|
||||
if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost;
|
||||
if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro;
|
||||
|
||||
#elif JUCE_LINUX || JUCE_BSD
|
||||
if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour;
|
||||
if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform;
|
||||
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
|
||||
if (hostFilename.startsWith ("Bitwig")) return BitwigStudio;
|
||||
if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval;
|
||||
if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost;
|
||||
|
||||
#elif JUCE_IOS
|
||||
#elif JUCE_ANDROID
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
return UnknownHost;
|
||||
}
|
||||
|
||||
} // namespace juce
|
247
deps/juce/modules/juce_audio_processors/utilities/juce_PluginHostType.h
vendored
Normal file
247
deps/juce/modules/juce_audio_processors/utilities/juce_PluginHostType.h
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A useful utility class to determine the host or DAW in which your plugin is
|
||||
loaded.
|
||||
|
||||
Declare a PluginHostType object in your class to use it.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class PluginHostType
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PluginHostType() : type (getHostType()) {}
|
||||
PluginHostType (const PluginHostType& other) = default;
|
||||
PluginHostType& operator= (const PluginHostType& other) = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Represents the host type and also its version for some hosts. */
|
||||
enum HostType
|
||||
{
|
||||
UnknownHost, /**< Represents an unknown host. */
|
||||
AbletonLive6, /**< Represents Ableton Live 6. */
|
||||
AbletonLive7, /**< Represents Ableton Live 7. */
|
||||
AbletonLive8, /**< Represents Ableton Live 8. */
|
||||
AbletonLive9, /**< Represents Ableton Live 9. */
|
||||
AbletonLive10, /**< Represents Ableton Live 10. */
|
||||
AbletonLive11, /**< Represents Ableton Live 11. */
|
||||
AbletonLiveGeneric, /**< Represents Ableton Live. */
|
||||
AdobeAudition, /**< Represents Adobe Audition. */
|
||||
AdobePremierePro, /**< Represents Adobe Premiere Pro. */
|
||||
AppleGarageBand, /**< Represents Apple GarageBand. */
|
||||
AppleLogic, /**< Represents Apple Logic Pro. */
|
||||
AppleMainStage, /**< Represents Apple Main Stage. */
|
||||
Ardour, /**< Represents Ardour. */
|
||||
AULab, /**< Represents AU Lab. */
|
||||
AvidProTools, /**< Represents Avid Pro Tools. */
|
||||
BitwigStudio, /**< Represents Bitwig Studio. */
|
||||
CakewalkSonar8, /**< Represents Cakewalk Sonar 8. */
|
||||
CakewalkSonarGeneric, /**< Represents Cakewalk Sonar. */
|
||||
CakewalkByBandlab, /**< Represents Cakewalk by Bandlab. */
|
||||
DaVinciResolve, /**< Represents DaVinci Resolve. */
|
||||
DigitalPerformer, /**< Represents Digital Performer. */
|
||||
FinalCut, /**< Represents Apple Final Cut Pro. */
|
||||
FruityLoops, /**< Represents Fruity Loops. */
|
||||
JUCEPluginHost, /**< Represents the JUCE AudioPluginHost */
|
||||
MagixSamplitude, /**< Represents Magix Samplitude. */
|
||||
MagixSequoia, /**< Represents Magix Sequoia. */
|
||||
MergingPyramix, /**< Represents Merging Pyramix. */
|
||||
MuseReceptorGeneric, /**< Represents Muse Receptor. */
|
||||
pluginval, /**< Represents pluginval. */
|
||||
Reaper, /**< Represents Cockos Reaper. */
|
||||
Reason, /**< Represents Reason. */
|
||||
Renoise, /**< Represents Renoise. */
|
||||
SADiE, /**< Represents SADiE. */
|
||||
SteinbergCubase4, /**< Represents Steinberg Cubase 4. */
|
||||
SteinbergCubase5, /**< Represents Steinberg Cubase 5. */
|
||||
SteinbergCubase5Bridged, /**< Represents Steinberg Cubase 5 Bridged. */
|
||||
SteinbergCubase6, /**< Represents Steinberg Cubase 6. */
|
||||
SteinbergCubase7, /**< Represents Steinberg Cubase 7. */
|
||||
SteinbergCubase8, /**< Represents Steinberg Cubase 8. */
|
||||
SteinbergCubase8_5, /**< Represents Steinberg Cubase 8.5. */
|
||||
SteinbergCubase9, /**< Represents Steinberg Cubase 9. */
|
||||
SteinbergCubase9_5, /**< Represents Steinberg Cubase 9.5. */
|
||||
SteinbergCubase10, /**< Represents Steinberg Cubase 10. */
|
||||
SteinbergCubase10_5, /**< Represents Steinberg Cubase 10.5. */
|
||||
SteinbergCubaseGeneric, /**< Represents Steinberg Cubase. */
|
||||
SteinbergNuendo3, /**< Represents Steinberg Nuendo 3. */
|
||||
SteinbergNuendo4, /**< Represents Steinberg Nuendo 4. */
|
||||
SteinbergNuendo5, /**< Represents Steinberg Nuendo 5. */
|
||||
SteinbergNuendoGeneric, /**< Represents Steinberg Nuendo. */
|
||||
SteinbergWavelab5, /**< Represents Steinberg Wavelab 5. */
|
||||
SteinbergWavelab6, /**< Represents Steinberg Wavelab 6. */
|
||||
SteinbergWavelab7, /**< Represents Steinberg Wavelab 7. */
|
||||
SteinbergWavelab8, /**< Represents Steinberg Wavelab 8. */
|
||||
SteinbergWavelabGeneric, /**< Represents Steinberg Wavelab. */
|
||||
SteinbergTestHost, /**< Represents Steinberg's VST3 Test Host. */
|
||||
StudioOne, /**< Represents PreSonus Studio One. */
|
||||
Tracktion3, /**< Represents Tracktion 3. */
|
||||
TracktionGeneric, /**< Represents Tracktion. */
|
||||
TracktionWaveform, /**< Represents Tracktion Waveform. */
|
||||
VBVSTScanner, /**< Represents VB Audio VST Scanner. */
|
||||
ViennaEnsemblePro, /**< Represents Vienna Ensemble Pro. */
|
||||
WaveBurner /**< Represents Apple WaveBurner. */
|
||||
};
|
||||
|
||||
HostType type;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the host is any version of Ableton Live. */
|
||||
bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8
|
||||
|| type == AbletonLive9 || type == AbletonLive10 || type == AbletonLive11
|
||||
|| type == AbletonLiveGeneric; }
|
||||
/** Returns true if the host is Adobe Audition. */
|
||||
bool isAdobeAudition() const noexcept { return type == AdobeAudition; }
|
||||
/** Returns true if the host is Ardour. */
|
||||
bool isArdour() const noexcept { return type == Ardour; }
|
||||
/** Returns true if the host is AU Lab. */
|
||||
bool isAULab() const noexcept { return type == AULab; }
|
||||
/** Returns true if the host is Bitwig Studio. */
|
||||
bool isBitwigStudio() const noexcept { return type == BitwigStudio; }
|
||||
/** Returns true if the host is any version of Steinberg Cubase. */
|
||||
bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6
|
||||
|| type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9
|
||||
|| type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubase10_5 || type == SteinbergCubaseGeneric; }
|
||||
/** Returns true if the host is Steinberg Cubase 7 or later. */
|
||||
bool isCubase7orLater() const noexcept { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); }
|
||||
/** Returns true if the host is Steinberg Cubase 5 Bridged. */
|
||||
bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; }
|
||||
/** Returns true if the host is DaVinci Resolve. */
|
||||
bool isDaVinciResolve() const noexcept { return type == DaVinciResolve; }
|
||||
/** Returns true if the host is Digital Performer. */
|
||||
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; }
|
||||
/** Returns true if the host is Apple Final Cut Pro. */
|
||||
bool isFinalCut() const noexcept { return type == FinalCut; }
|
||||
/** Returns true if the host is Fruity Loops. */
|
||||
bool isFruityLoops() const noexcept { return type == FruityLoops; }
|
||||
/** Returns true if the host is Apple GarageBand. */
|
||||
bool isGarageBand() const noexcept { return type == AppleGarageBand; }
|
||||
/** Returns true if the host is the JUCE AudioPluginHost */
|
||||
bool isJUCEPluginHost() const noexcept { return type == JUCEPluginHost; }
|
||||
/** Returns true if the host is Apple Logic Pro. */
|
||||
bool isLogic() const noexcept { return type == AppleLogic; }
|
||||
/** Returns true if the host is Apple MainStage. */
|
||||
bool isMainStage() const noexcept { return type == AppleMainStage; }
|
||||
/** Returns true if the host is any version of Steinberg Nuendo. */
|
||||
bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; }
|
||||
/** Returns true if the host is pluginval. */
|
||||
bool isPluginval() const noexcept { return type == pluginval; }
|
||||
/** Returns true if the host is Adobe Premiere Pro. */
|
||||
bool isPremiere() const noexcept { return type == AdobePremierePro; }
|
||||
/** Returns true if the host is Avid Pro Tools. */
|
||||
bool isProTools() const noexcept { return type == AvidProTools; }
|
||||
/** Returns true if the host is Merging Pyramix. */
|
||||
bool isPyramix() const noexcept { return type == MergingPyramix; }
|
||||
/** Returns true if the host is Muse Receptor. */
|
||||
bool isReceptor() const noexcept { return type == MuseReceptorGeneric; }
|
||||
/** Returns true if the host is Cockos Reaper. */
|
||||
bool isReaper() const noexcept { return type == Reaper; }
|
||||
/** Returns true if the host is Reason. */
|
||||
bool isReason() const noexcept { return type == Reason; }
|
||||
/** Returns true if the host is Renoise. */
|
||||
bool isRenoise() const noexcept { return type == Renoise; }
|
||||
/** Returns true if the host is SADiE. */
|
||||
bool isSADiE() const noexcept { return type == SADiE; }
|
||||
/** Returns true if the host is Magix Samplitude. */
|
||||
bool isSamplitude() const noexcept { return type == MagixSamplitude; }
|
||||
/** Returns true if the host is Magix Sequoia. */
|
||||
bool isSequoia() const noexcept { return type == MagixSequoia; }
|
||||
/** Returns true if the host is any version of Cakewalk Sonar. */
|
||||
bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric || type == CakewalkByBandlab; }
|
||||
/** Returns true if the host is Steinberg's VST3 Test Host. */
|
||||
bool isSteinbergTestHost() const noexcept { return type == SteinbergTestHost; }
|
||||
/** Returns true if the host is any product from Steinberg. */
|
||||
bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab() || isSteinbergTestHost(); }
|
||||
/** Returns true if the host is PreSonus Studio One. */
|
||||
bool isStudioOne() const noexcept { return type == StudioOne; }
|
||||
/** Returns true if the host is any version of Tracktion. */
|
||||
bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric || isTracktionWaveform(); }
|
||||
/** Returns true if the host is Tracktion Waveform. */
|
||||
bool isTracktionWaveform() const noexcept { return type == TracktionWaveform; }
|
||||
/** Returns true if the host is VB Audio VST Scanner. */
|
||||
bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; }
|
||||
/** Returns true if the host is Vienna Ensemble Pro. */
|
||||
bool isViennaEnsemblePro() const noexcept { return type == ViennaEnsemblePro; }
|
||||
/** Returns true if the host is Apple WaveBurner. */
|
||||
bool isWaveBurner() const noexcept { return type == WaveBurner; }
|
||||
/** Returns true if the host is any version of Steinberg WaveLab. */
|
||||
bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; }
|
||||
/** Returns true if the host is Steinberg WaveLab 6 or below. */
|
||||
bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a human-readable description of the host. */
|
||||
const char* getHostDescription() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the plugin is connected with Inter-App Audio on iOS. */
|
||||
bool isInterAppAudioConnected() const;
|
||||
/** Switches to the host application when Inter-App Audio is used on iOS. */
|
||||
void switchToHostApplication() const;
|
||||
/** Gets the host app's icon when Inter-App Audio is used on iOS. */
|
||||
Image getHostIcon (int size) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the complete absolute path of the host application executable. */
|
||||
static String getHostPath()
|
||||
{
|
||||
return File::getSpecialLocation (File::hostApplicationPath).getFullPathName();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Returns the plug-in format via which the plug-in file was loaded. This value is
|
||||
identical to AudioProcessor::wrapperType of the main audio processor of this
|
||||
plug-in. This function is useful for code that does not have access to the
|
||||
plug-in's main audio processor.
|
||||
|
||||
@see AudioProcessor::wrapperType
|
||||
*/
|
||||
static AudioProcessor::WrapperType getPluginLoadedAs() noexcept { return jucePlugInClientCurrentWrapperType; }
|
||||
|
||||
/** Returns true if the AudioProcessor instance is an AAX plug-in running in AudioSuite. */
|
||||
static bool isInAAXAudioSuite (AudioProcessor&);
|
||||
|
||||
//==============================================================================
|
||||
|
||||
#ifndef DOXYGEN
|
||||
// @internal
|
||||
static AudioProcessor::WrapperType jucePlugInClientCurrentWrapperType;
|
||||
static std::function<bool (AudioProcessor&)> jucePlugInIsRunningInAudioSuiteFn;
|
||||
static String hostIdReportedByWrapper;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static HostType getHostType();
|
||||
};
|
||||
|
||||
} // namespace juce
|
59
deps/juce/modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp
vendored
Normal file
59
deps/juce/modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
RangedAudioParameter::RangedAudioParameter (const String& parameterID,
|
||||
const String& parameterName,
|
||||
const String& parameterLabel,
|
||||
Category parameterCategory)
|
||||
: AudioProcessorParameterWithID (parameterID, parameterName, parameterLabel, parameterCategory)
|
||||
{
|
||||
}
|
||||
|
||||
int RangedAudioParameter::getNumSteps() const
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
|
||||
if (range.interval > 0)
|
||||
return (static_cast<int> ((range.end - range.start) / range.interval) + 1);
|
||||
|
||||
return AudioProcessor::getDefaultNumParameterSteps();
|
||||
}
|
||||
|
||||
float RangedAudioParameter::convertTo0to1 (float v) const noexcept
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
return range.convertTo0to1 (range.snapToLegalValue (v));
|
||||
}
|
||||
|
||||
float RangedAudioParameter::convertFrom0to1 (float v) const noexcept
|
||||
{
|
||||
const auto& range = getNormalisableRange();
|
||||
return range.snapToLegalValue (range.convertFrom0to1 (jlimit (0.0f, 1.0f, v)));
|
||||
}
|
||||
|
||||
} // namespace juce
|
63
deps/juce/modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h
vendored
Normal file
63
deps/juce/modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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& parameterName,
|
||||
const String& parameterLabel = {},
|
||||
Category parameterCategory = AudioProcessorParameter::genericParameter);
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Normalises and snaps a value based on the normalisable range. */
|
||||
float convertTo0to1 (float v) const noexcept;
|
||||
|
||||
/** Denormalises and snaps a value based on the normalisable range. */
|
||||
float convertFrom0to1 (float v) const noexcept;
|
||||
};
|
||||
|
||||
} // namespace juce
|
95
deps/juce/modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h
vendored
Normal file
95
deps/juce/modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Forward declaration to avoid leaking implementation details.
|
||||
namespace Steinberg
|
||||
{
|
||||
class FUnknown;
|
||||
using TUID = char[16];
|
||||
}
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/** An interface to allow an AudioProcessor to implement extended VST3-specific
|
||||
functionality.
|
||||
|
||||
To use this class, ensure that your AudioProcessor publicly inherits
|
||||
from VST3ClientExtensions.
|
||||
|
||||
@see VSTCallbackHandler
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct VST3ClientExtensions
|
||||
{
|
||||
virtual ~VST3ClientExtensions() = default;
|
||||
|
||||
/** This function may be used by implementations of queryInterface()
|
||||
in the VST3's implementation of IEditController to return
|
||||
additional supported interfaces.
|
||||
*/
|
||||
virtual int32_t queryIEditController (const Steinberg::TUID, void** obj)
|
||||
{
|
||||
*obj = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** This function may be used by implementations of queryInterface()
|
||||
in the VST3's implementation of IAudioProcessor to return
|
||||
additional supported interfaces.
|
||||
*/
|
||||
virtual int32_t queryIAudioProcessor (const Steinberg::TUID, void** obj)
|
||||
{
|
||||
*obj = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** This may be called by the VST3 wrapper when the host sets an
|
||||
IComponentHandler for the plugin to use.
|
||||
|
||||
You should not make any assumptions about how and when this will be
|
||||
called - this function may not be called at all!
|
||||
*/
|
||||
virtual void setIComponentHandler (Steinberg::FUnknown*) {}
|
||||
|
||||
/** This may be called shortly after the AudioProcessor is constructed
|
||||
with the current IHostApplication.
|
||||
|
||||
You should not make any assumptions about how and when this will be
|
||||
called - this function may not be called at all!
|
||||
*/
|
||||
virtual void setIHostApplication (Steinberg::FUnknown*) {}
|
||||
|
||||
/** This function will be called to check whether the first input bus
|
||||
should be designated as "kMain" or "kAux". Return true if the
|
||||
first bus should be kMain, or false if the bus should be kAux.
|
||||
|
||||
All other input buses will always be designated kAux.
|
||||
*/
|
||||
virtual bool getPluginHasMainInput() const { return true; }
|
||||
};
|
||||
|
||||
} // namespace juce
|
80
deps/juce/modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h
vendored
Normal file
80
deps/juce/modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
/** An interface to allow an AudioProcessor to send and receive VST specific calls from
|
||||
the host.
|
||||
|
||||
To use this class, ensure that your AudioProcessor publicly inherits
|
||||
from VSTCallbackHandler.
|
||||
|
||||
@see VST3ClientExtensions
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct VSTCallbackHandler
|
||||
{
|
||||
virtual ~VSTCallbackHandler() = default;
|
||||
|
||||
/** This is called by the VST plug-in wrapper when it receives unhandled
|
||||
plug-in "can do" calls from the host.
|
||||
*/
|
||||
virtual pointer_sized_int handleVstPluginCanDo (int32 index,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt)
|
||||
{
|
||||
ignoreUnused (index, value, ptr, opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** This is called by the VST plug-in wrapper when it receives unhandled
|
||||
vendor specific calls from the host.
|
||||
*/
|
||||
virtual pointer_sized_int handleVstManufacturerSpecific (int32 index,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt) = 0;
|
||||
|
||||
// Note: VS2013 prevents a "using" declaration here
|
||||
/** The host callback function type. */
|
||||
typedef pointer_sized_int (VstHostCallbackType) (int32 opcode,
|
||||
int32 index,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt);
|
||||
|
||||
/** This is called once by the VST plug-in wrapper after its constructor.
|
||||
You can use the supplied function to query the VST host.
|
||||
*/
|
||||
virtual void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& callback)
|
||||
{
|
||||
ignoreUnused (callback);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user