clap

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

commit dc5d6e4c83db8081210e22bf074524a3935f8386
parent fa1af14290d7e00955b9c4bb5ea1c796fde81281
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date:   Wed, 28 Apr 2021 10:37:16 +0200

Better transport, faster plugin metadata scanning

Diffstat:
M.clang-format | 2+-
Minclude/clap/clap.h | 236+++++++++++--------------------------------------------------------------------
Ainclude/clap/events.h | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/clap/ext/audio-ports.h | 26++++++++++----------------
4 files changed, 200 insertions(+), 221 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -50,7 +50,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 +ColumnLimit: 100 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: true ConstructorInitializerAllOnOneLineOrOnePerLine: false diff --git a/include/clap/clap.h b/include/clap/clap.h @@ -29,13 +29,15 @@ #include <stddef.h> #include <stdint.h> +#include "events.h" + #ifdef __cplusplus extern "C" { #endif -#define CLAP_VERSION_MAKE(Major, Minor, Revision) \ +#define CLAP_VERSION_MAKE(Major, Minor, Revision) \ ((((Major)&0xff) << 16) | (((Minor)&0xff) << 8) | ((Revision)&0xff)) -#define CLAP_VERSION CLAP_VERSION_MAKE(0, 3, 0) +#define CLAP_VERSION CLAP_VERSION_MAKE(0, 4, 0) #define CLAP_VERSION_MAJ(Version) (((Version) >> 16) & 0xff) #define CLAP_VERSION_MIN(Version) (((Version) >> 8) & 0xff) #define CLAP_VERSION_REV(Version) ((Version)&0xff) @@ -59,180 +61,6 @@ typedef enum clap_string_size { CLAP_NAME_SIZE = 64, } clap_string_size; -// Description of the plugin -#define CLAP_ATTR_DESCRIPTION "clap/description" -// Manufacturer name -#define CLAP_ATTR_MANUFACTURER "clap/manufacturer" -// Url to product -#define CLAP_ATTR_URL "clap/url" -// Url to support page, or mail to support -#define CLAP_ATTR_SUPPORT "clap/support" - -//////////////// -// PARAMETERS // -//////////////// - -typedef union clap_param_value { - bool b; - double d; - int64_t i; -} clap_param_value; - -/////////////// -// TRANSPORT // -/////////////// - -typedef struct clap_loop_info { - bool is_loop_active; - double loop_start; - double loop_end; -} clap_loop_info; - -//////////// -// EVENTS // -//////////// - -typedef enum clap_event_type { - CLAP_EVENT_NOTE_ON, // note attribute - CLAP_EVENT_NOTE_OFF, // note attribute - CLAP_EVENT_NOTE_EXPRESSION, // note_expression attribute - CLAP_EVENT_CHOKE, // no attribute - CLAP_EVENT_PARAM_SET, // param attribute - CLAP_EVENT_JUMP, // jump attribute - CLAP_EVENT_TEMPO, // tempo attribute - CLAP_EVENT_PLAY, // is_playing attribute - CLAP_EVENT_RECORD, // is_recording attribute - CLAP_EVENT_TSIG, // tsig attribute - CLAP_EVENT_CHORD, // chord attribute - - /* MIDI Style */ - CLAP_EVENT_PROGRAM, // program attribute - CLAP_EVENT_MIDI, // midi attribute - CLAP_EVENT_MIDI_SYSEX, // midi attribute -} clap_event_type; - -/** Note On/Off event. */ -typedef struct clap_event_note { - int32_t key; // 0..127 - int32_t channel; // 0..15 - double velocity; // 0..1 -} clap_event_note; - -typedef enum clap_note_expression { - // TODO range, 20 * log(K * x)? - CLAP_NOTE_EXPRESSION_VOLUME, - - // pan, -1 left, 1 right - CLAP_NOTE_EXPRESSION_PAN, - - // relative tunind in semitone - CLAP_NOTE_EXPRESSION_TUNING, - CLAP_NOTE_EXPRESSION_VIBRATO, - CLAP_NOTE_EXPRESSION_BRIGHTNESS, - CLAP_NOTE_EXPRESSION_BREATH, - CLAP_NOTE_EXPRESSION_PRUSSURE, - CLAP_NOTE_EXPRESSION_TIMBRE, - - // TODO... -} clap_note_expression; - -typedef struct clap_event_note_expression { - clap_note_expression expression_id; - int32_t key; // 0..127, or -1 to match all keys - int32_t channel; // 0..15, or -1 to match all channels - int32_t control; // 0..127 - double normalized_value; // see expression for the range - double normalized_ramp; -} clap_event_note_expression; - -typedef struct clap_event_param { - int32_t key; - int32_t channel; - uint32_t index; // parameter index - clap_param_value normalized_value; - double normalized_ramp; // valid until the end of the block or the next event -} clap_event_param; - -typedef struct clap_event_jump { - double song_pos_beats; // position in beats - double song_pos_seconds; // position in seconds - - double bar_start; // start pos of the current bar - int32_t bar_number; // bar at song pos 0 has the number 0 -} clap_event_jump; - -typedef struct clap_event_tsig { - int16_t num; // time signature numerator - int16_t denom; // time signature denominator -} clap_event_tsig; - -typedef struct clap_event_chord { - // bitset of active keys: - // - 11 bits - // - root note is not part of the bitset - // - bit N is: root note + N + 1 - // 0000 0000 0100 0100 -> minor chord - // 0000 0000 0100 1000 -> major chord - uint16_t note_mask; - uint8_t root_note; // 0..11, 0 for C -} clap_event_chord; - -typedef struct clap_event_midi { - uint8_t data[4]; -} clap_event_midi; - -typedef struct clap_event_midi_sysex { - const uint8_t *buffer; // midi buffer - uint32_t size; -} clap_event_midi_sysex; - -/** - * Asks the plugin to load a program. - * This is analogue to the midi program change. - * - * The main advantage of setting a program instead of loading - * a preset, is that the program should already be in the plugin's - * memory, and can be set instantly (no loading time). - */ -typedef struct clap_event_program { - int32_t channel; // 0..15, -1 unspecified - int32_t bank_msb; // 0..0x7FFFFFFF, -1 unspecified - int32_t bank_lsb; // 0..0x7FFFFFFF, -1 unspecified - int32_t program; // 0..0x7FFFFFFF -} clap_event_program; - -typedef struct clap_event { - clap_event_type type; - uint32_t time; // offset from the first sample in the process block - - union { - clap_event_note note; - clap_event_note_expression note_expression; - clap_event_param param; - clap_event_jump jump; - clap_event_chord chord; - double tempo; - clap_event_tsig tsig; - bool is_playing; - bool is_recording; - clap_event_program program; - clap_event_midi midi; - clap_event_midi_sysex midi_sysex; - }; -} clap_event; - -typedef struct clap_event_list { - void *ctx; - - uint32_t (*size)(const clap_event_list *list); - - // Don't free the return event, it belongs to the list - const clap_event *(*get)(const clap_event_list *list, uint32_t index); - - // Makes a copy of the event - void (*push_back)(const clap_event_list *list, const clap_event *event); -} clap_event_list; - ///////////// // PROCESS // ///////////// @@ -258,7 +86,7 @@ typedef struct clap_audio_buffer { uint32_t latency; // latency from/to the audio interface uint64_t constant_mask; // bitmask for each channel, 1 if the value is // constant for the whole buffer - const char *plugin_port_id; // optional, used for validation + uint32_t port_id; } clap_audio_buffer; typedef struct clap_process { @@ -267,8 +95,6 @@ typedef struct clap_process { bool has_transport; // if false then this is a free running host, no // transport events will be provided - clap_loop_info loop_info; // only valid if has_transport is true - // Audio buffers, they must have the same count as specified // by clap_plugin_audio_ports->get_count(). // The index maps to clap_plugin_audio_ports->get_info(). @@ -301,10 +127,7 @@ typedef struct clap_host { /* Returns the size of the original string. If this is larger than size, then * the function did not have enough space to copy all the data. * [thread-safe] */ - int32_t (*get_attribute)(clap_host * host, - const char *attr, - char * buffer, - int32_t size); + int32_t (*get_attribute)(clap_host *host, const char *attr, char *buffer, int32_t size); /* Query an extension. * [thread-safe] */ @@ -334,22 +157,25 @@ typedef enum clap_plugin_type { CLAP_PLUGIN_ANALYZER = (1 << 3), } clap_plugin_type; -typedef struct clap_plugin { +typedef struct clap_plugin_descriptor { int32_t clap_version; // initialized to CLAP_VERSION - void *plugin_data; // reserved pointer for the plugin - - /* The 3 following strings are here because: - * - they are mandatory - * - it is convenient when you debug, to be able to see - * the plugin name, id and version by displaying - * the structure. - */ - char name[CLAP_NAME_SIZE]; // plugin name, eg: "Diva" - char id[CLAP_ID_SIZE]; // plugin id, eg: "com.u-he.diva" - char version[CLAP_NAME_SIZE]; // the plugin version, eg: "1.3.2" + const char *id; // eg: "com.u-he.diva" + const char *name; // eg: "Diva" + const char *vendor; // eg: "u-he" + const char *url; // eg: "https://u-he.com/products/diva/" + const char *manual_url; // eg: "https://dl.u-he.com/manuals/plugins/diva/Diva-user-guide.pdf" + const char *support_url; // eg: "https://u-he.com/support/" + const char *version; // eg: "1.4.4" + const char *description; // eg: "The spirit of analogue" uint64_t plugin_type; // bitfield of clap_plugin_type +} clap_plugin_descriptor; + +typedef struct clap_plugin { + const clap_plugin_descriptor *desc; + + void *plugin_data; // reserved pointer for the plugin /* Free the plugin and its resources. * It is not required to deactivate the plugin prior to this call. */ @@ -360,10 +186,7 @@ typedef struct clap_plugin { * Returns the size of the original string or 0 if there is no * value for this attributes. * [thread-safe] */ - int32_t (*get_attribute)(clap_plugin *plugin, - const char * attr, - char * buffer, - int32_t size); + int32_t (*get_attribute)(clap_plugin *plugin, const char *attr, char *buffer, int32_t size); /* activation/deactivation * [main-thread] */ @@ -372,14 +195,17 @@ typedef struct clap_plugin { /* process audio, events, ... * [audio-thread] */ - clap_process_status (*process)(clap_plugin * plugin, - const clap_process *process); + clap_process_status (*process)(clap_plugin *plugin, const clap_process *process); /* query an extension * [thread-safe] */ const void *(*extension)(clap_plugin *plugin, const char *id); } clap_plugin; +///////////////// +// ENTRY POINT // +///////////////// + /* This interface is the entry point of the dynamic library. * * Every methods must be thread-safe. */ @@ -391,15 +217,17 @@ struct clap_plugin_entry { * [thread-safe] */ int32_t (*get_plugin_count)(void); - /* Create a clap_plugin by its index. + /* Retrieves a plugin descriptor by its index. * Returns null in case of error. + * The descriptor does not need to be freed. * [thread-safe] */ - clap_plugin *(*create_plugin_by_index)(clap_host *host, int32_t index); + const clap_plugin_descriptor *(*get_plugin_descriptor)(clap_host *host, int32_t index); /* Create a clap_plugin by its plugin_id. + * The returned pointer must be freed by calling plugin->destroy(plugin); * Returns null in case of error. * [thread-safe] */ - clap_plugin *(*create_plugin_by_id)(clap_host *host, const char *plugin_id); + clap_plugin *(*create_plugin)(clap_host *host, const char *plugin_id); }; /* Entry point */ diff --git a/include/clap/events.h b/include/clap/events.h @@ -0,0 +1,156 @@ +#pragma once + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum clap_event_type { + CLAP_EVENT_NOTE_ON, // note attribute + CLAP_EVENT_NOTE_OFF, // note attribute + CLAP_EVENT_NOTE_EXPRESSION, // note_expression attribute + CLAP_EVENT_CHOKE, // no attribute + CLAP_EVENT_PARAM_SET, // param attribute + CLAP_EVENT_TIME_INFO, // time_info attribute + CLAP_EVENT_CHORD, // chord attribute + + /* MIDI Style */ + CLAP_EVENT_PROGRAM, // program attribute + CLAP_EVENT_MIDI, // midi attribute + CLAP_EVENT_MIDI_SYSEX, // midi attribute +} clap_event_type; + +/** Note On/Off event. */ +typedef struct clap_event_note { + int32_t key; // 0..127 + int32_t channel; // 0..15 + double velocity; // 0..1 +} clap_event_note; + +typedef enum clap_note_expression { + // TODO range, 20 * log(K * x)? + CLAP_NOTE_EXPRESSION_VOLUME, + + // pan, -1 left, 1 right + CLAP_NOTE_EXPRESSION_PAN, + + // relative tunind in semitone + CLAP_NOTE_EXPRESSION_TUNING, + CLAP_NOTE_EXPRESSION_VIBRATO, + CLAP_NOTE_EXPRESSION_BRIGHTNESS, + CLAP_NOTE_EXPRESSION_BREATH, + CLAP_NOTE_EXPRESSION_PRUSSURE, + CLAP_NOTE_EXPRESSION_TIMBRE, + + // TODO... +} clap_note_expression; + +typedef struct clap_event_note_expression { + clap_note_expression expression_id; + int32_t key; // 0..127, or -1 to match all keys + int32_t channel; // 0..15, or -1 to match all channels + int32_t control; // 0..127 + double normalized_value; // see expression for the range + double normalized_ramp; +} clap_event_note_expression; + +typedef union clap_param_value { + bool b; + double d; + int64_t i; +} clap_param_value; + +typedef struct clap_event_param { + int32_t key; + int32_t channel; + uint32_t index; // parameter index + clap_param_value normalized_value; + double normalized_ramp; // valid until the end of the block or the next event +} clap_event_param; + +typedef struct clap_event_time_info { + double song_pos_beats; // position in beats + double song_pos_seconds; // position in seconds + + double tempo; // in bpm + double tempo_ramp; // tempo increment for each samples and until the next + // time info event + + double bar_start; // start pos of the current bar + int32_t bar_number; // bar at song pos 0 has the number 0 + + bool is_loop_active; + double loop_start; // in beats + double loop_end; // in beats + + int16_t num; // time signature numerator + int16_t denom; // time signature denominator +} clap_event_time_info; + +typedef struct clap_event_chord { + // bitset of active keys: + // - 11 bits + // - root note is not part of the bitset + // - bit N is: root note + N + 1 + // 0000 0000 0100 0100 -> minor chord + // 0000 0000 0100 1000 -> major chord + uint16_t note_mask; + uint8_t root_note; // 0..11, 0 for C +} clap_event_chord; + +typedef struct clap_event_midi { + uint8_t data[4]; +} clap_event_midi; + +typedef struct clap_event_midi_sysex { + const uint8_t *buffer; // midi buffer + uint32_t size; +} clap_event_midi_sysex; + +/** + * Asks the plugin to load a program. + * This is analogue to the midi program change. + * + * The main advantage of setting a program instead of loading + * a preset, is that the program should already be in the plugin's + * memory, and can be set instantly (no loading time). + */ +typedef struct clap_event_program { + int32_t channel; // 0..15, -1 unspecified + int32_t bank_msb; // 0..0x7FFFFFFF, -1 unspecified + int32_t bank_lsb; // 0..0x7FFFFFFF, -1 unspecified + int32_t program; // 0..0x7FFFFFFF +} clap_event_program; + +typedef struct clap_event { + clap_event_type type; + uint32_t time; // offset from the first sample in the process block + + union { + clap_event_note note; + clap_event_note_expression note_expression; + clap_event_param param; + clap_event_time_info time_info; + clap_event_chord chord; + clap_event_program program; + clap_event_midi midi; + clap_event_midi_sysex midi_sysex; + }; +} clap_event; + +typedef struct clap_event_list { + void *ctx; + + uint32_t (*size)(const clap_event_list *list); + + // Don't free the return event, it belongs to the list + const clap_event *(*get)(const clap_event_list *list, uint32_t index); + + // Makes a copy of the event + void (*push_back)(const clap_event_list *list, const clap_event *event); +} clap_event_list; + +#ifdef __cplusplus +} +#endif +\ No newline at end of file diff --git a/include/clap/ext/audio-ports.h b/include/clap/ext/audio-ports.h @@ -21,14 +21,14 @@ typedef enum clap_audio_port_channel_mapping { } clap_audio_port_channel_mapping; typedef struct clap_audio_port_info { - char id[CLAP_ID_SIZE]; // stable identifier - char name[CLAP_NAME_SIZE]; // displayable name - bool is_main; // there can only be 1 main input and output - bool is_cv; // control voltage - bool supports_64_bits; // 32 bit support is mandatory, the host chooses - // between 32 and 64. - bool supports_in_place; // if true the daw can use the same buffer for input - // and output, only for main input to main output + uint32_t id; // stable identifier + char name[CLAP_NAME_SIZE]; // displayable name + bool is_main; // there can only be 1 main input and output + bool is_cv; // control voltage + bool supports_64_bits; // 32 bit support is mandatory, the host chooses + // between 32 and 64. + bool supports_in_place; // if true the daw can use the same buffer for input + // and output, only for main input to main output int32_t channel_count; clap_audio_port_channel_mapping channel_mapping; } clap_audio_port_info; @@ -41,15 +41,9 @@ typedef struct clap_plugin_audio_ports { // get info about about an audio port. // [main-thread] - void (*get_info)(clap_plugin * plugin, - int32_t index, - bool is_input, - clap_audio_port_info *info); + void (*get_info)(clap_plugin *plugin, int32_t index, bool is_input, clap_audio_port_info *info); - void (*activate_port)(clap_plugin *plugin, - int32_t index, - bool is_input, - bool use_64); + void (*activate_port)(clap_plugin *plugin, int32_t index, bool is_input, bool use_64); void (*deactivate_port)(clap_plugin *plugin, int32_t index, bool is_input); // Returns the port latency.