6#include "dsp/audio_port.h"
7#include "dsp/cv_port.h"
8#include "dsp/graph_node.h"
9#include "dsp/midi_port.h"
10#include "utils/iobject_registry.h"
11#include "utils/math_utils.h"
12#include "utils/traits.h"
13#include "utils/typed_uuid_reference.h"
14#include "utils/units.h"
15#include "utils/uuid_identifiable_object.h"
17#include <QtQmlIntegration/qqmlintegration.h>
19#include <nlohmann/json_fwd.hpp>
21using namespace std::string_view_literals;
29 QML_VALUE_TYPE (parameterRange)
32 enum class Type : std::uint8_t
76 enum class
Unit : std::uint8_t
98 : type_ (type),
minf_ (min), maxf_ (max),
99 zerof_ (std::clamp (zero, min, max)),
deff_ (std::clamp (def, min, max))
103 static ParameterRange make_toggle (
bool default_val)
105 return {
Type::Toggle, 0.f, 1.f, 0.f, default_val ? 1.f : 0.f };
107 static ParameterRange make_gain (
float max_val)
112 static ParameterRange make_enumeration (
113 std::vector<utils::Utf8String> labels,
114 size_t default_index = 0)
118 throw std::invalid_argument (
119 "Enumeration parameter requires at least one label");
121 if (default_index >= labels.size ())
123 throw std::invalid_argument (
124 "default_index out of range for enumeration labels");
126 const auto count =
static_cast<float> (labels.size ());
127 ParameterRange range{
129 static_cast<float> (default_index)
131 range.enum_labels_ = std::move (labels);
143 Q_INVOKABLE
size_t enumIndex (
float normalized_val)
const
145 const auto real = convertFrom0To1 (normalized_val);
147 const auto idx =
static_cast<size_t> (std::max (std::round (real), 0.f));
159 return convertTo0To1 (
static_cast<float> (index));
170 Q_INVOKABLE QString enumLabel (
int index)
const
172 if (index < 0 ||
static_cast<size_t> (index) >=
enum_labels_.size ())
174 return enum_label (
static_cast<size_t> (index)).to_qstring ();
177 template <utils::EnumType E>
float normalized_from_enum (E value)
const
180 const auto index =
static_cast<size_t> (value);
185 template <utils::EnumType E> E enum_value (
float normalized_val)
const
188 return static_cast<E
> (
enumIndex (normalized_val));
191 constexpr float clamp_to_range (
float val)
const
193 return std::clamp (val,
minf_, maxf_);
196 Q_INVOKABLE
float convertFrom0To1 (
float normalized_val)
const;
197 Q_INVOKABLE
float convertTo0To1 (
float real_val)
const;
199 Q_INVOKABLE
bool isToggled (
float normalized_val)
const
205 friend void to_json (nlohmann::json &j,
const ParameterRange &p);
206 friend void from_json (
const nlohmann::json &j, ParameterRange &p);
237 BOOST_DESCRIBE_CLASS (
252class ProcessorParameter
258 float baseValue READ baseValue WRITE setBaseValue NOTIFY baseValueChanged)
259 Q_PROPERTY (QString label READ label CONSTANT)
260 Q_PROPERTY (QString description READ description CONSTANT)
262 Q_PROPERTY (
bool automatable READ automatable CONSTANT)
267 struct UniqueId final
268 : type_safe::strong_typedef<UniqueId,
utils::Utf8String>,
269 type_safe::strong_typedef_op::equality_comparison<UniqueId>,
270 type_safe::strong_typedef_op::relational_comparison<UniqueId>
274 explicit UniqueId () =
default;
278 std::size_t hash ()
const {
return qHash (type_safe::get (*this).view ()); }
280 static_assert (std::regular<UniqueId>);
283 std::function<QPointer<ProcessorParameter> (
const UniqueId &unique_id)>;
290 QObject * parent =
nullptr);
306 std::function<std::optional<float> (units::sample_t sample_position)>;
312 QString label ()
const {
return label_.to_qstring (); }
313 QString description ()
const {
return description_->to_qstring (); }
314 bool automatable ()
const {
return automatable_; }
316 const auto &range ()
const {
return range_; }
318 float baseValue ()
const {
return base_value_.load (); }
319 void setBaseValue (
float newValue) [[clang::blocking]]
321 newValue = std::clamp (newValue, 0.f, 1.f);
322 if (qFuzzyCompare (base_value_, newValue))
324 base_value_ = newValue;
325 Q_EMIT baseValueChanged (newValue);
327 Q_INVOKABLE
void resetBaseValueToDefault ()
329 setBaseValue (range_.convertTo0To1 (range_.deff_));
331 Q_SIGNAL
void baseValueChanged (
float value);
337 Q_INVOKABLE
float currentValue ()
const {
return last_modulated_value_; }
347 return last_automated_value_.load ();
350 Q_INVOKABLE
void beginUserGesture ()
352 during_gesture_.store (
true);
353 Q_EMIT userGestureStarted ();
355 Q_INVOKABLE
void endUserGesture ()
357 during_gesture_.store (
false);
358 Q_EMIT userGestureFinished ();
360 Q_SIGNAL
void userGestureStarted ();
361 Q_SIGNAL
void userGestureFinished ();
380 const dsp::TempoMap &tempo_map)
noexcept override;
384 units::sample_rate_t sample_rate,
385 units::sample_u32_t max_block_length)
override;
392 automation_value_provider_ = provider;
394 void unset_automation_provider () { automation_value_provider_.reset (); }
396 PortUuidReference get_modulation_input_port_ref ()
const
398 return modulation_input_uuid_;
401 void set_description (utils::Utf8String descr)
403 description_ = std::move (descr);
406 void set_automatable (
bool automatable) { automatable_ = automatable; }
408 bool hidden ()
const {
return hidden_; }
410 const auto &get_unique_id ()
const {
return unique_id_; }
414 static constexpr auto kUniqueIdKey =
"uniqueId"sv;
415 static constexpr auto kRangeKey =
"range"sv;
416 static constexpr auto kLabelKey =
"label"sv;
417 static constexpr auto kSymbolKey =
"symbol"sv;
418 static constexpr auto kDescriptionKey =
"description"sv;
419 static constexpr auto kAutomatableKey =
"automatable"sv;
420 static constexpr auto kHiddenKey =
"hidden"sv;
421 static constexpr auto kBaseValueKey =
"baseValue"sv;
422 static constexpr auto kModulationSourcePortIdKey =
"modulationSourcePortId"sv;
423 friend void to_json (nlohmann::json &j,
const ProcessorParameter &p);
424 friend void from_json (
const nlohmann::json &j, ProcessorParameter &p);
440 ParameterRange range_;
443 utils::Utf8String label_;
448 std::atomic<float> base_value_;
455 std::atomic_bool during_gesture_;
464 std::atomic<float> last_automated_value_;
475 std::atomic<float> last_modulated_value_;
483 PortUuidReference modulation_input_uuid_;
486 dsp::CVPort * modulation_input_{};
493 std::optional<AutomationValueProvider> automation_value_provider_;
496 std::optional<utils::Utf8String> symbol_;
499 std::optional<utils::Utf8String> description_;
502 bool automatable_{
true };
507 BOOST_DESCRIBE_CLASS (
509 (utils::UuidIdentifiableObject<ProcessorParameter>),
516 modulation_input_uuid_,
526 return type_safe::get (
id).view ();
529using ProcessorParameterPtrVariant = std::variant<ProcessorParameter *>;
532DEFINE_UUID_HASH_SPECIALIZATION (zrythm::dsp::ProcessorParameter::Uuid)
537using ProcessorParameterUuidReference =
538 utils::TypedUuidReference<ProcessorParameter>;
544template <>
struct hash<zrythm::dsp::ProcessorParameter::UniqueId>
std::vector< utils::Utf8String > enum_labels_
Labels for Enumeration type parameters.
float minf_
Minimum, maximum and zero values for this parameter.
Q_INVOKABLE size_t enumCount() const
Returns the number of enum entries.
const auto & enum_label(size_t index) const
Returns the label for a given enum index.
Q_INVOKABLE float normalizedEnumValue(size_t index) const
Returns the normalized value for a given enum index.
float zerof_
The zero position of the port.
Unit unit_
Parameter unit.
Q_INVOKABLE size_t enumIndex(float normalized_val) const
Converts a normalized value to an enum index.
@ GainAmplitude
Parameter is a gain amplitude (0-2.0).
@ Enumeration
Port's only reasonable values are its scale points.
@ Logarithmic
Logarithmic-scaled float parameter.
@ Linear
Linearly-scaled float parameter.
@ Integer
Whether the port is an integer.
@ Toggle
Whether the port is a toggle (on/off).
@ Trigger
Trigger parameters are set to on to trigger a change during processing and then turned off at the end...
Unit
Unit to be displayed in the UI.
float deff_
Default value.
std::function< std::optional< float >(units::sample_t sample_position)> AutomationValueProvider
Provides the automation value for a given sample position.
void prepare_for_processing(const graph::GraphNode *node, units::sample_rate_t sample_rate, units::sample_u32_t max_block_length) override
Called to allocate resources required for processing.
void release_resources() override
Called to release resources allocated by prepare_for_processing().
void process_block(dsp::graph::ProcessBlockInfo time_nfo, const dsp::ITransport &transport, const dsp::TempoMap &tempo_map) noexcept override
Processes automation and modulation.
Q_INVOKABLE float currentValue() const
Returns the current (normalized) value after any automation and modulation has been applied.
utils::Utf8String get_node_name() const override
Returns a human friendly name of the node.
Q_INVOKABLE float valueAfterAutomationApplied() const
Returns the value after automation, but before modulation has been applied.
Represents a node in a DSP graph.
Interface for objects that can be processed in the DSP graph.
Abstract interface for a UUID-keyed object registry.
Lightweight UTF-8 string wrapper with safe conversions.
CRTP base that adds a typed UUID strong-typedef to a class hierarchy.
constexpr bool floats_equal(T a, T b)
Checks if 2 floating point numbers are equal.
Common struct to pass around during processing to avoid repeating the data in function arguments.