Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
11KB

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