forked from free-audio/clap
/
params.h
274 lines (236 loc) · 10.5 KB
/
params.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
/// @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 plugin is responsible to keep in sync its audio processor and its GUI.
///
/// The host can read at any time parameters value on the [main-thread] using
/// @ref clap_plugin_params.value().
///
/// There is two options to communicate parameter value change, and they are not concurrent.
/// - send automation points during clap_plugin.process()
/// - send automation points during clap_plugin_params.flush(), this one is used when the plugin is
/// not processing
///
/// When the plugin changes a parameter value, it must inform the host.
/// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush().
/// - set the flag CLAP_EVENT_PARAM_BEGIN_ADJUST to mark the begining of automation recording
/// - set the flag CLAP_EVENT_PARAM_END_ADJUST to mark the end of automation recording
/// - set the flag CLAP_EVENT_PARAM_SHOULD_RECORD if the event should be recorded
///
/// @note MIDI CCs are a tricky because you may not know when the parameter adjustment ends.
/// Also if the hosts records incoming MIDI CC and parameter change automation at the same time,
/// there will be a conflict at playback: MIDI CC vs Automation.
/// The parameter automation will always target the same parameter because the param_id is stable.
/// The MIDI CC may have a different mapping in the future and may result in a different playback.
///
/// When a MIDI CC changes a parameter's value, set @ref clap_event_param.should_record to false.
/// That way the host may record the MIDI CC automation, but not the parameter change and there
/// won't be conflict at playback.
///
/// Scenarios:
///
/// I. Loading a preset
/// - load the preset in a temporary state
/// - call @ref clap_host_params.changed() if anything changed
/// - call @ref clap_host_latency.changed() if latency changed
/// - invalidate any other info that may be cached by the host
/// - if the plugin is activated and the preset will introduce breaking change
/// (latency, audio ports, new parameters, ...) be sure to wait for the host
/// to deactivate the plugin to apply those changes.
/// If there are no breaking changes, the plugin can apply them them right away.
/// The plugin is resonsible to update both its audio processor and its gui.
///
/// II. Turning a knob on the DAW interface
/// - the host will send an automation event to the plugin via a process() or flush()
///
/// III. Turning a knob on the Plugin interface
/// - if the plugin is not processing, call clap_host_params->request_flush() or
/// clap_host->request_process().
/// - send an automation event and don't forget to set begin_adjust, end_adjust and should_record
/// attributes
/// - the plugin is responsible to send the parameter value to its audio processor
///
/// IV. Turning a knob via automation
/// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush().
/// - the plugin is responsible to update its GUI
///
/// V. Turning a knob via plugin's internal MIDI mapping
/// - the plugin sends a CLAP_EVENT_PARAM_SET output event, set should_record to false
/// - the plugin is responsible to update its GUI
///
/// VI. Adding or removing parameters
/// - if the plugin is activated call clap_host->restart()
/// - once the plugin isn't active:
/// - apply the new state
/// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL)
/// - if a parameter is created with an id that may have been used before,
/// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL)
static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params";
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, CLAP_ALIGN)
enum {
// Is this param stepped? (integer values only)
// if so the double value is converted to integer using a cast (equivalent to trunc).
CLAP_PARAM_IS_STEPPED = 1 << 0,
// Does this param supports per note automations?
CLAP_PARAM_IS_PER_NOTE = 1 << 1,
// Does this param supports per channel automations?
CLAP_PARAM_IS_PER_CHANNEL = 1 << 2,
// Does this param supports per port automations?
CLAP_PARAM_IS_PER_PORT = 1 << 3,
// Useful for for periodic parameters like a phase
CLAP_PARAM_IS_PERIODIC = 1 << 4,
// The parameter should not be shown to the user, because it is currently not used.
// It is not necessary to process automation for this parameter.
CLAP_PARAM_IS_HIDDEN = 1 << 5,
// This parameter is used to merge the plugin and host bypass button.
// It implies that the parameter is stepped.
// min: 0 -> bypass off
// max: 1 -> bypass on
CLAP_PARAM_IS_BYPASS = (1 << 6) | CLAP_PARAM_IS_STEPPED,
// The parameter can't be changed by the host.
CLAP_PARAM_IS_READONLY = 1 << 7,
// Does the parameter support the modulation signal?
CLAP_PARAM_IS_MODULATABLE = 1 << 8,
// Any change to this parameter will affect the plugin output and requires to be done via
// process() if the plugin is active.
//
// A simple example would be a DC Offset, changing it will change the output signal and must be
// processed.
CLAP_PARAM_REQUIRES_PROCESS = 1 << 9,
};
typedef uint32_t clap_param_info_flags;
/* This describes a parameter */
typedef struct clap_param_info {
// stable parameter identifier, it must never change.
alignas(4) clap_id id;
alignas(4) clap_param_info_flags flags;
// This value is optional and set by the plugin.
// Its purpose is to provide a fast access to the plugin parameter:
//
// Parameter *p = findParameter(param_id);
// param_info->cookie = p;
//
// /* and later on */
// Parameter *p = (Parameter *)cookie;
//
// It is invalidated on clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) and when the plugin is
// destroyed.
void *cookie;
alignas(1) char name[CLAP_NAME_SIZE]; // the display name
alignas(1) char module[CLAP_MODULE_SIZE]; // the module containing the param, eg:
// "oscillators/wt1"; '/' will be used as a
// separator to show a tree like structure.
alignas(8) double min_value; // minimum plain value
alignas(8) double max_value; // maximum plain value
alignas(8) double default_value; // default plain value
} clap_param_info_t;
typedef struct clap_plugin_params {
// Returns the number of parameters.
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// Copies the parameter's info to param_info and returns true on success.
// [main-thread]
bool (*get_info)(const clap_plugin_t *plugin,
int32_t param_index,
clap_param_info_t *param_info);
// Gets the parameter plain value.
// [main-thread]
bool (*get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value);
// Formats the display text for the given parameter value.
// The host should always format the parameter value to text using this function
// before displaying it to the user.
// [main-thread]
bool (*value_to_text)(
const clap_plugin_t *plugin, clap_id param_id, double value, char *display, uint32_t size);
// Converts the display text to a parameter value.
// [main-thread]
bool (*text_to_value)(const clap_plugin_t *plugin,
clap_id param_id,
const char *display,
double *value);
// Flushes a set of parameter changes.
// This method must not be called concurrently to clap_plugin->process().
// This method must not be used if the plugin is processing.
//
// [active && !processing : audio-thread]
// [!active : main-thread]
void (*flush)(const clap_plugin_t *plugin,
const clap_event_list_t *input_parameter_changes,
const clap_event_list_t *output_parameter_changes);
} clap_plugin_params_t;
enum {
// The parameter values did change, eg. after loading a preset.
// The host will scan all the parameters value.
// The host will not record those changes as automation points.
// New values takes effect immediately.
CLAP_PARAM_RESCAN_VALUES = 1 << 0,
// The value to text conversion changed, and the text needs to be rendered again.
CLAP_PARAM_RESCAN_TEXT = 1 << 1,
// The parameter info did change, use this flag for:
// - name change
// - module change
// - is_periodic (flag)
// - is_hidden (flag)
// New info takes effect immediately.
CLAP_PARAM_RESCAN_INFO = 1 << 2,
// Invalidates everything the host knows about parameters.
// It can only be used while the plugin is deactivated.
// If the plugin is activated use clap_host->restart() and delay any change until the host calls
// clap_plugin->deactivate().
//
// You must use this flag if:
// - some parameters were added or removed.
// - some parameters had critical changes:
// - is_per_note (flag)
// - is_per_channel (flag)
// - is_readonly (flag)
// - is_bypass (flag)
// - is_stepped (flag)
// - is_modulatable (flag)
// - min_value
// - max_value
// - cookie
CLAP_PARAM_RESCAN_ALL = 1 << 3,
};
typedef uint32_t clap_param_rescan_flags;
enum {
// Clears all possible references to a parameter
CLAP_PARAM_CLEAR_ALL = 1 << 0,
// Clears all automations to a parameter
CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1,
// Clears all modulations to a parameter
CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2,
};
typedef uint32_t clap_param_clear_flags;
typedef struct clap_host_params {
// Rescan the full list of parameters according to the flags.
// [main-thread]
void (*rescan)(const clap_host_t *host, clap_param_rescan_flags flags);
// Clears references to a parameter
// [main-thread]
void (*clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags);
// Request the host to call clap_plugin_params->fush().
// This is useful if the plugin has parameters value changes to report to the host but the plugin
// is not processing.
//
// eg. the plugin has a USB socket to some hardware controllers and receives a parameter change
// while it is not processing.
//
// This must not be called on the [audio-thread].
//
// [thread-safe]
void (*request_flush)(const clap_host_t *host);
} clap_host_params_t;
#pragma pack(pop)
#ifdef __cplusplus
}
#endif