params.h (12910B)
1 #pragma once 2 3 #include "../plugin.h" 4 #include "../string-sizes.h" 5 6 /// @page Parameters 7 /// @brief parameters management 8 /// 9 /// Main idea: 10 /// 11 /// The host sees the plugin as an atomic entity; and acts as a controller on top of its parameters. 12 /// The plugin is responsible for keeping its audio processor and its GUI in sync. 13 /// 14 /// The host can at any time read parameters' value on the [main-thread] using 15 /// @ref clap_plugin_params.value(). 16 /// 17 /// There are two options to communicate parameter value changes, and they are not concurrent. 18 /// - send automation points during clap_plugin.process() 19 /// - send automation points during clap_plugin_params.flush(), for parameter changes 20 /// without processing audio 21 /// 22 /// When the plugin changes a parameter value, it must inform the host. 23 /// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush(). 24 /// If the user is adjusting the value, don't forget to mark the begining and end 25 /// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END 26 /// events. 27 /// 28 /// @note MIDI CCs are tricky because you may not know when the parameter adjustment ends. 29 /// Also if the host records incoming MIDI CC and parameter change automation at the same time, 30 /// there will be a conflict at playback: MIDI CC vs Automation. 31 /// The parameter automation will always target the same parameter because the param_id is stable. 32 /// The MIDI CC may have a different mapping in the future and may result in a different playback. 33 /// 34 /// When a MIDI CC changes a parameter's value, set the flag CLAP_EVENT_DONT_RECORD in 35 /// clap_event_param.header.flags. That way the host may record the MIDI CC automation, but not the 36 /// parameter change and there won't be conflict at playback. 37 /// 38 /// Scenarios: 39 /// 40 /// I. Loading a preset 41 /// - load the preset in a temporary state 42 /// - call @ref clap_host_params.rescan() if anything changed 43 /// - call @ref clap_host_latency.changed() if latency changed 44 /// - invalidate any other info that may be cached by the host 45 /// - if the plugin is activated and the preset will introduce breaking changes 46 /// (latency, audio ports, new parameters, ...) be sure to wait for the host 47 /// to deactivate the plugin to apply those changes. 48 /// If there are no breaking changes, the plugin can apply them them right away. 49 /// The plugin is resonsible for updating both its audio processor and its gui. 50 /// 51 /// II. Turning a knob on the DAW interface 52 /// - the host will send an automation event to the plugin via a process() or flush() 53 /// 54 /// III. Turning a knob on the Plugin interface 55 /// - the plugin is responsible for sending the parameter value to its audio processor 56 /// - call clap_host_params->request_flush() or clap_host->request_process(). 57 /// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(), 58 /// send an automation event and don't forget to set begin_adjust, 59 /// end_adjust and should_record flags 60 /// 61 /// IV. Turning a knob via automation 62 /// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush(). 63 /// - the plugin is responsible for updating its GUI 64 /// 65 /// V. Turning a knob via plugin's internal MIDI mapping 66 /// - the plugin sends a CLAP_EVENT_PARAM_SET output event, set should_record to false 67 /// - the plugin is responsible to update its GUI 68 /// 69 /// VI. Adding or removing parameters 70 /// - if the plugin is activated call clap_host->restart() 71 /// - once the plugin isn't active: 72 /// - apply the new state 73 /// - if a parameter is gone or is created with an id that may have been used before, 74 /// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL) 75 /// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) 76 77 static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params"; 78 79 #ifdef __cplusplus 80 extern "C" { 81 #endif 82 83 enum { 84 // Is this param stepped? (integer values only) 85 // if so the double value is converted to integer using a cast (equivalent to trunc). 86 CLAP_PARAM_IS_STEPPED = 1 << 0, 87 88 // Useful for for periodic parameters like a phase 89 CLAP_PARAM_IS_PERIODIC = 1 << 1, 90 91 // The parameter should not be shown to the user, because it is currently not used. 92 // It is not necessary to process automation for this parameter. 93 CLAP_PARAM_IS_HIDDEN = 1 << 2, 94 95 // The parameter can't be changed by the host. 96 CLAP_PARAM_IS_READONLY = 1 << 3, 97 98 // This parameter is used to merge the plugin and host bypass button. 99 // It implies that the parameter is stepped. 100 // min: 0 -> bypass off 101 // max: 1 -> bypass on 102 CLAP_PARAM_IS_BYPASS = 1 << 4, 103 104 // When set: 105 // - automation can be recorded 106 // - automation can be played back 107 // 108 // The host can send live user changes for this parameter regardless of this flag. 109 // 110 // If this parameters affect the internal processing structure of the plugin, ie: max delay, fft 111 // size, ... and the plugins needs to re-allocate its working buffers, then it should call 112 // host->request_restart(), and perform the change once the plugin is re-activated. 113 CLAP_PARAM_IS_AUTOMATABLE = 1 << 5, 114 115 // Does this parameter support per note automations? 116 CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6, 117 118 // Does this parameter support per key automations? 119 CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7, 120 121 // Does this parameter support per channel automations? 122 CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8, 123 124 // Does this parameter support per port automations? 125 CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9, 126 127 // Does this parameter support the modulation signal? 128 CLAP_PARAM_IS_MODULATABLE = 1 << 10, 129 130 // Does this parameter support per note modulations? 131 CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11, 132 133 // Does this parameter support per key modulations? 134 CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12, 135 136 // Does this parameter support per channel modulations? 137 CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13, 138 139 // Does this parameter support per port modulations? 140 CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14, 141 142 // Any change to this parameter will affect the plugin output and requires to be done via 143 // process() if the plugin is active. 144 // 145 // A simple example would be a DC Offset, changing it will change the output signal and must be 146 // processed. 147 CLAP_PARAM_REQUIRES_PROCESS = 1 << 15, 148 }; 149 typedef uint32_t clap_param_info_flags; 150 151 /* This describes a parameter */ 152 typedef struct clap_param_info { 153 // stable parameter identifier, it must never change. 154 clap_id id; 155 156 clap_param_info_flags flags; 157 158 // This value is optional and set by the plugin. The host will 159 // set it on all subsequent events regarding this param_id 160 // or set the cookie to nullptr if the host chooses to 161 // not implement cookies. 162 // 163 // The plugin must gracefully handle the case of a cookie 164 // which is nullptr, but can safely assume any cookie 165 // which is not nullptr is the value it issued. 166 // 167 // It is very strongly recommended that the host implement 168 // cookies. Some plugins may have noticably reduced 169 // performance when addressing params in hosts without cookies. 170 // 171 // The cookie's purpose is to provide a fast access to the 172 // plugin parameter objects. For instance: 173 // 174 // in clap_plugin_params.get_info 175 // Parameter *p = findParameter(param_id); 176 // param_info->cookie = p; 177 // 178 // later, in clap_plugin.process: 179 // 180 // Parameter *p{nullptr}; 181 // if (evt->cookie) [[likely]] 182 // p = (Parameter *)evt->cookie; 183 // else 184 // p = -- alternate mechanism -- 185 // 186 // where "alternate mechanism" is a mechanism the plugin implements 187 // to map parameter ids to internal objects. 188 // 189 // The host should make no assumption about the 190 // value of the cookie other than passing it back to the plugin or 191 // replacing it with nullptr. 192 // 193 // Once set, the cookie is valid until invalidated by a call to 194 // clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or when the plugin is 195 // destroyed. 196 void *cookie; 197 198 // the display name 199 char name[CLAP_NAME_SIZE]; 200 201 // the module path containing the param, eg:"oscillators/wt1" 202 // '/' will be used as a separator to show a tree like structure. 203 char module[CLAP_PATH_SIZE]; 204 205 double min_value; // minimum plain value 206 double max_value; // maximum plain value 207 double default_value; // default plain value 208 } clap_param_info_t; 209 210 typedef struct clap_plugin_params { 211 // Returns the number of parameters. 212 // [main-thread] 213 uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); 214 215 // Copies the parameter's info to param_info and returns true on success. 216 // [main-thread] 217 bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, 218 uint32_t param_index, 219 clap_param_info_t *param_info); 220 221 // Gets the parameter plain value. 222 // [main-thread] 223 bool(CLAP_ABI *get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value); 224 225 // Formats the display text for the given parameter value. 226 // The host should always format the parameter value to text using this function 227 // before displaying it to the user. 228 // [main-thread] 229 bool(CLAP_ABI *value_to_text)( 230 const clap_plugin_t *plugin, clap_id param_id, double value, char *display, uint32_t size); 231 232 // Converts the display text to a parameter value. 233 // [main-thread] 234 bool(CLAP_ABI *text_to_value)(const clap_plugin_t *plugin, 235 clap_id param_id, 236 const char *display, 237 double *value); 238 239 // Flushes a set of parameter changes. 240 // This method must not be called concurrently to clap_plugin->process(). 241 // 242 // Note: if the plugin is processing, then the process() call will already achieve the 243 // parameter update (bi-directionnal), so a call to flush isn't required, also be aware 244 // that the plugin may use the sample offset in process(), while this information would be 245 // lost within flush(). 246 // 247 // [active ? audio-thread : main-thread] 248 void(CLAP_ABI *flush)(const clap_plugin_t *plugin, 249 const clap_input_events_t *in, 250 const clap_output_events_t *out); 251 } clap_plugin_params_t; 252 253 enum { 254 // The parameter values did change, eg. after loading a preset. 255 // The host will scan all the parameters value. 256 // The host will not record those changes as automation points. 257 // New values takes effect immediately. 258 CLAP_PARAM_RESCAN_VALUES = 1 << 0, 259 260 // The value to text conversion changed, and the text needs to be rendered again. 261 CLAP_PARAM_RESCAN_TEXT = 1 << 1, 262 263 // The parameter info did change, use this flag for: 264 // - name change 265 // - module change 266 // - is_periodic (flag) 267 // - is_hidden (flag) 268 // New info takes effect immediately. 269 CLAP_PARAM_RESCAN_INFO = 1 << 2, 270 271 // Invalidates everything the host knows about parameters. 272 // It can only be used while the plugin is deactivated. 273 // If the plugin is activated use clap_host->restart() and delay any change until the host calls 274 // clap_plugin->deactivate(). 275 // 276 // You must use this flag if: 277 // - some parameters were added or removed. 278 // - some parameters had critical changes: 279 // - is_per_note (flag) 280 // - is_per_channel (flag) 281 // - is_readonly (flag) 282 // - is_bypass (flag) 283 // - is_stepped (flag) 284 // - is_modulatable (flag) 285 // - min_value 286 // - max_value 287 // - cookie 288 CLAP_PARAM_RESCAN_ALL = 1 << 3, 289 }; 290 typedef uint32_t clap_param_rescan_flags; 291 292 enum { 293 // Clears all possible references to a parameter 294 CLAP_PARAM_CLEAR_ALL = 1 << 0, 295 296 // Clears all automations to a parameter 297 CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1, 298 299 // Clears all modulations to a parameter 300 CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2, 301 }; 302 typedef uint32_t clap_param_clear_flags; 303 304 typedef struct clap_host_params { 305 // Rescan the full list of parameters according to the flags. 306 // [main-thread] 307 void(CLAP_ABI *rescan)(const clap_host_t *host, clap_param_rescan_flags flags); 308 309 // Clears references to a parameter. 310 // [main-thread] 311 void(CLAP_ABI *clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags); 312 313 // Request a parameter flush. 314 // 315 // The host will then schedule a call to either: 316 // - clap_plugin.process() 317 // - clap_plugin_params.flush() 318 // 319 // This function is always safe to use and should not be called from an [audio-thread] as the 320 // plugin would already be within process() or flush(). 321 // 322 // [thread-safe,!audio-thread] 323 void(CLAP_ABI *request_flush)(const clap_host_t *host); 324 } clap_host_params_t; 325 326 #ifdef __cplusplus 327 } 328 #endif