clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

commit cea197fb2bc9b9e07a0a79ba9829fecd032a7d8a
parent 87ebfa05273ef685130abb690a6a289b8ac410f5
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date:   Sat, 29 May 2021 15:23:52 +0200

More work on parameters

Diffstat:
Aexamples/plugins/parameters.cc | 28++++++++++++++++++++++++++++
Aexamples/plugins/parameters.hh | 45+++++++++++++++++++++++++++++++++++++++++++++
Minclude/clap/events.h | 27+++++++++++++++++++++------
Minclude/clap/ext/params.h | 40++++++++++++++++++++++++++++++++++++----
4 files changed, 130 insertions(+), 10 deletions(-)

diff --git a/examples/plugins/parameters.cc b/examples/plugins/parameters.cc @@ -0,0 +1,28 @@ +#include <cassert> + +#include "parameters.hh" + +namespace clap { + void clap::Parameters::addParameter(const Parameter &param) { + assert(id2param_.find(param.info.id) == id2param_.end()); + + auto p = std::make_unique<Parameter>(param); + id2param_.emplace(param.info.id, p.get()); + params_.emplace_back(std::move(p)); + } + + size_t Parameters::count() const noexcept { return params_.size(); } + + Parameter *Parameters::getByIndex(size_t index) const noexcept { + if (index > params_.size()) + return nullptr; + return params_[index].get(); + } + + Parameter *Parameters::getById(clap_id id) const noexcept { + auto it = id2param_.find(id); + if (it == id2param_.end()) + return nullptr; + return it->second; + } +} // namespace clap diff --git a/examples/plugins/parameters.hh b/examples/plugins/parameters.hh @@ -0,0 +1,44 @@ +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + +#include <clap/all.h> + +namespace clap { + struct EnumEntry { + std::string name; + int64_t value; + }; + + struct EnumDefinition { + std::vector<EnumEntry> entries; + }; + + struct Parameter { + clap_param_info info; + EnumDefinition enumDefinition; + clap_param_value value; + clap_param_value modulation; + double valueRamp = 0; + double modulationRamp = 0; + }; + + class Parameters { + public: + Parameters() = default; + Parameters(const Parameters &parameters); + + void addParameter(const Parameter &param); + + size_t count() const noexcept; + + Parameter *getByIndex(size_t index) const noexcept; + + Parameter *getById(clap_id id) const noexcept; + + private: + std::vector<std::unique_ptr<Parameter>> params_; + std::unordered_map<clap_id, Parameter *> id2param_; + }; +} // namespace clap +\ No newline at end of file diff --git a/include/clap/events.h b/include/clap/events.h @@ -66,13 +66,28 @@ typedef union clap_param_value { } clap_param_value; typedef struct clap_event_param { - int32_t key; - int32_t channel; - clap_id param_id; // parameter index + // selects if the events targets a specific key or channel, -1 for global; + int32_t key; + int32_t channel; + + // target parameter + clap_id param_id; + + // The value that we hear is value + modulation + // If the plugin receives MIDI CC or overrides the automation playback because of a + // GUI takeover, it should add the modulation and preserve the modulation playback clap_param_value value; - double ramp; // valid until the end of the block or the next event - clap_param_value modulated_value; - double modulation_ramp; + clap_param_value modulation; + + // the ramps are constant value that are added to value every samples + // they are valid until the end of the block or the next event + // If this event happens at time T, the value at time K is value + (K - T) * ramp. + double value_ramp; + double modulation_ramp; + + // only used by the plugin for output events + bool begin_adjust; + bool end_adjust; } clap_event_param; typedef struct clap_event_transport { diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h @@ -9,6 +9,34 @@ extern "C" { /// @page Parameters /// @brief parameters management /// +/// Main idea: +/// +/// The host sees the plugin as an atomic entity; and acts as a controler on top of its parameters. +/// +/// The host can read at any time the parameter value on the [main-thread] using +/// @ref clap_plugin_params.value(). +/// +/// There is a single way at a time for the host to set parameters value. +/// - if the plugin is active, send @ref CLAP_PARAM_SET event during the process call [audio-thread] +/// - if the plugin is not active, call @ref clap_plugin_params.set_value [main-thread] +/// +/// Rationale: sending @ref CLAP_PARAM_SET event during the process call is the natural way to play parameter automation. +/// But, the process call is only possible if the plugin is active. If it is not, then everything happens on the +/// [main-thread] using the clap_plugin_params and clap_host_params interfaces. +/// +/// When the plugin receives a parameter set, it is responsible to keep in sync its GUI and audio processor. +/// +/// When the plugin changes a parameter value because a knob is being adjusted on its GUI or a MIDI CC is mapped to a parameter, +/// the plugin must inform the host. The host can then update its GUI, interrupt automation playback and record new automation points. +/// If the plugin is active, it will send @ref CLAP_PARAM_SET events, it must set the fields begin_adjust on the first parameter set and end_adjust on the last one. +/// If the plugin is inactive, it will use: +/// - @ref clap_host_params.adjust_begin() - marks the begining of automation recording +/// - @ref clap_host_params.adjust() - adds a new point in the automation recording +/// - @ref clap_host_params.adjust_end() - marks the end of automation recording +/// +/// @note it may be convenient for the plugin to let the host knows about the midi mapping table, +/// and translate MIDI CCs to parameter events for the plugin, yet it is not necessary. +/// /// Scenarios: /// /// I. Loading a preset @@ -24,17 +52,21 @@ extern "C" { /// - if the plugin is not active, the host will call plugin_params->set_value(...) /// /// III. Turning a knob on the Plugin interface -/// - host_params->begin_adjust(...) -/// - host_params->adjust(...) many times -> updates host's knob and record automation -/// - host_params->end_adjust(...) +/// - if the plugin is not active +/// - host_params->begin_adjust(...) +/// - host_params->adjust(...) many times -> updates host's knob and record automation +/// - host_params->end_adjust(...) +/// - if the plugin is active +/// - send CLAP_PARAM_SET event and don't forget to set begin_adjust and end_adjust attributes /// - the plugin is responsible to send the parameter value to its audio processor /// /// IV. Turning a knob via automation /// - host sends a CLAP_PARAM_SET event /// - the plugin is responsible to update its GUI /// -/// V. Turning a knob via MIDI mapping +/// V. Turning a knob via internal MIDI mapping /// - the plugin sends a CLAP_PARAM_SET output event +/// - the plugin is responsible to update its GUI /// /// VI. Adding or removing parameters /// - call host_params->rescan(CLAP_PARAM_RESCAN_ALL)