From 5b5f0618d1608edebfec7fe0979106e10c5e7cdd Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Wed, 3 Jul 2024 17:06:50 +0200 Subject: [PATCH 01/18] cpu meter support for lv2 --- notes | 8 +++ templates/common/fatica.h | 63 ++++++++++++++++++ templates/lv2/src/data.h | 3 + templates/lv2/src/lv2.c | 133 +++++++++++++++++++++++--------------- test/product.json | 18 ++++++ test/run.sh | 1 + 6 files changed, 175 insertions(+), 51 deletions(-) create mode 100644 templates/common/fatica.h diff --git a/notes b/notes index fb857f6..2a19817 100644 --- a/notes +++ b/notes @@ -162,6 +162,14 @@ product { web: not (yet) used cmd: not (yet) used android: not (yet) used + isCpumeter: + parameter is output cpu meter? boolean + VST3: TODO + LV2: data.h, lv2.c + web: TODO + cmd: TODO + android: TODO + ios: TODO defaultValue: default value, number, mapped, required for non-bypass VST3: ParameterInfo defaultNormalizedValue, controller initialize diff --git a/templates/common/fatica.h b/templates/common/fatica.h new file mode 100644 index 0000000..e0914e5 --- /dev/null +++ b/templates/common/fatica.h @@ -0,0 +1,63 @@ +#ifndef FATICA_H +#define FATICA_H + +// API + +// unit = 100-nanosecond starting from somewhen +unsigned long long fatica_time_process(void); + +// Implementation + +#if defined(_WIN32) || defined(__CYGWIN__) + +#include + +static ULONGLONG filetime_to_ull(const FILETIME* ft) { + return (((ULONGLONG)ft->dwHighDateTime) << 32) + ft->dwLowDateTime; +} + +unsigned long long fatica_time_process(void) { + FILETIME creationTime, exitTime, kernelTime, userTime; + const DWORD threadId = GetCurrentThreadId(); + const HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId); + if (!GetThreadTimes(hThread, &creationTime, &exitTime, &kernelTime, &userTime)) + return 0ull; + CloseHandle(hThread); + return (unsigned long long) (filetime_to_ull(&kernelTime) + filetime_to_ull(&userTime)); +} + +#elif defined(__linux__) + +#if __STDC_VERSION__ >= 199901L +# define _XOPEN_SOURCE 600 +#else +# define _XOPEN_SOURCE 500 +#endif +#include +#include + +unsigned long long fatica_time_process(void) { + struct timespec ts; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) + return 0ull; + return (unsigned long long) (ts.tv_sec * 1e7 + ts.tv_nsec / 1e2); +} + +#elif defined(__APPLE__) + +#include +#include +#include + +unsigned long long fatica_time_process(void) { + thread_t thread = mach_thread_self(); + thread_basic_info_data_t info; + mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; + if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count) != KERN_SUCCESS) + return 0ull; + return (info.user_time.seconds + info.system_time.seconds) * 1000 + + (info.user_time.microseconds + info.system_time.microseconds) / 1000; +} + +#endif +#endif // FATICA_H diff --git a/templates/lv2/src/data.h b/templates/lv2/src/data.h index cf5e8b5..3a6d806 100644 --- a/templates/lv2/src/data.h +++ b/templates/lv2/src/data.h @@ -63,6 +63,9 @@ static struct { static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = { {{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}} }; +{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}} +# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}} +{{?}} #endif {{?it.lv2.ui}} diff --git a/templates/lv2/src/lv2.c b/templates/lv2/src/lv2.c index 843bb69..c23933e 100644 --- a/templates/lv2/src/lv2.c +++ b/templates/lv2/src/lv2.c @@ -22,17 +22,17 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); void (*set_parameter)(void *handle, size_t index, float value); } plugin_ui_callbacks; @@ -66,6 +66,10 @@ typedef struct { # include #endif +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif + static inline float clampf(float x, float m, float M) { return x < m ? m : (x > M ? M : x); } @@ -81,31 +85,35 @@ static float adjust_param(size_t index, float value) { } typedef struct { - plugin p; + plugin p; #if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0 - const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N]; + const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N]; #endif #if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0 - float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N]; + float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N]; #endif #if DATA_PRODUCT_MIDI_INPUTS_N > 0 - const LV2_Atom_Sequence * x_midi[DATA_PRODUCT_MIDI_INPUTS_N]; + const LV2_Atom_Sequence *x_midi[DATA_PRODUCT_MIDI_INPUTS_N]; #endif #if DATA_PRODUCT_MIDI_OUTPUTS_N > 0 - LV2_Atom_Sequence * y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N]; + LV2_Atom_Sequence *y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N]; #endif #if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0 - float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N]; + float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N]; #endif #if DATA_PRODUCT_CONTROL_INPUTS_N > 0 - float params[DATA_PRODUCT_CONTROL_INPUTS_N]; + float params[DATA_PRODUCT_CONTROL_INPUTS_N]; #endif - void * mem; - char * bundle_path; - LV2_Log_Logger logger; - LV2_URID_Map * map; + void *mem; + char *bundle_path; + LV2_Log_Logger logger; + LV2_URID_Map *map; #if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0 - LV2_URID uri_midi_MidiEvent; + LV2_URID uri_midi_MidiEvent; +#endif +#ifdef PARAM_OUT_CPU_INDEX + float cpu_meter; + float sample_rate; #endif } plugin_instance; @@ -128,8 +136,8 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s // from https://lv2plug.in/book const char* missing = lv2_features_query(features, - LV2_LOG__log, &instance->logger.log, false, - LV2_URID__map, &instance->map, true, + LV2_LOG__log, &instance->logger.log, false, + LV2_URID__map, &instance->map, true, NULL); lv2_log_logger_set_map(&instance->logger, instance->map); @@ -143,10 +151,10 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s #endif plugin_callbacks cbs = { - /* .handle = */ (void *)instance, - /* .format = */ "lv2", - /* .get_bindir = */ get_bundle_path_cb, - /* .get_datadir = */ get_bundle_path_cb + /* .handle = */ (void *)instance, + /* .format = */ "lv2", + /* .get_bindir = */ get_bundle_path_cb, + /* .get_datadir = */ get_bundle_path_cb }; plugin_init(&instance->p, &cbs); @@ -182,6 +190,10 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++) instance->c[i] = NULL; #endif +#ifdef PARAM_OUT_CPU_INDEX + instance->cpu_meter = 0.f; + instance->sample_rate = sample_rate; +#endif return instance; @@ -244,6 +256,10 @@ static void activate(LV2_Handle instance) { static void run(LV2_Handle instance, uint32_t sample_count) { plugin_instance * i = (plugin_instance *)instance; +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeStart = fatica_time_process(); +#endif + #if defined(__aarch64__) uint64_t fpcr; __asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr)); @@ -298,8 +314,15 @@ static void run(LV2_Handle instance, uint32_t sample_count) { #if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0 for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) { uint32_t k = param_out_index[j]; - if (i->c[k] != NULL) + if (i->c[k] != NULL) { +# ifdef PARAM_OUT_CPU_INDEX + if (k == PARAM_OUT_CPU_INDEX) { + *i->c[k] = i->cpu_meter; + continue; + } +# endif *i->c[k] = plugin_get_parameter(&i->p, k); + } } #else (void)plugin_get_parameter; @@ -311,6 +334,14 @@ static void run(LV2_Handle instance, uint32_t sample_count) { _MM_SET_FLUSH_ZERO_MODE(flush_zero_mode); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); #endif + +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + i->cpu_meter = i->cpu_meter * 0.9f + ((float) (processTimeS * i->sample_rate)) * 0.1f; +#endif + } static void cleanup(LV2_Handle instance) { @@ -323,14 +354,14 @@ static void cleanup(LV2_Handle instance) { } static const LV2_Descriptor descriptor = { - /* .URI = */ DATA_LV2_URI, - /* .instantiate = */ instantiate, - /* .connect_port = */ connect_port, - /* .activate = */ activate, - /* .run = */ run, - /* .deactivate = */ NULL, - /* .cleanup = */ cleanup, - /* .extension_data = */ NULL + /* .URI = */ DATA_LV2_URI, + /* .instantiate = */ instantiate, + /* .connect_port = */ connect_port, + /* .activate = */ activate, + /* .run = */ run, + /* .deactivate = */ NULL, + /* .cleanup = */ cleanup, + /* .extension_data = */ NULL }; LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) { @@ -339,11 +370,11 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) { #ifdef DATA_UI typedef struct { - plugin_ui * ui; - char * bundle_path; + plugin_ui *ui; + char *bundle_path; # if DATA_PRODUCT_CONTROL_INPUTS_N > 0 - LV2UI_Write_Function write; - LV2UI_Controller controller; + LV2UI_Write_Function write; + LV2UI_Controller controller; # endif } ui_instance; @@ -390,14 +421,14 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch goto err_bundle_path; plugin_ui_callbacks cbs = { - /* .handle = */ (void *)instance, - /* .format = */ "lv2", - /* .get_bindir = */ ui_get_bundle_path_cb, - /* .get_datadir = */ ui_get_bundle_path_cb, + /* .handle = */ (void *)instance, + /* .format. = */ "lv2", + /* .get_bindir. = */ ui_get_bundle_path_cb, + /* .get_datadir = */ ui_get_bundle_path_cb, # if DATA_PRODUCT_CONTROL_INPUTS_N > 0 - /* .set_parameter = */ ui_set_parameter_cb + /* .set_parameter = */ ui_set_parameter_cb # else - /* .set_parameter = */ NULL + /* .set_parameter = */ NULL # endif }; # if DATA_PRODUCT_CONTROL_INPUTS_N > 0 @@ -458,15 +489,15 @@ static const void * ui_extension_data(const char * uri) { } static const LV2UI_Descriptor ui_descriptor = { - /* .URI = */ DATA_LV2_UI_URI, - /* .instantiate = */ ui_instantiate, - /* .cleanup = */ ui_cleanup, + /* .URI = */ DATA_LV2_UI_URI, + /* .instantiate = */ ui_instantiate, + /* .cleanup = */ ui_cleanup, # if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0 - /* .port_event = */ ui_port_event, + /* .port_event = */ ui_port_event, # else - /* .port_event = */ NULL, + /* .port_event = */ NULL, # endif - /* .extension_data = */ ui_extension_data + /* .extension_data = */ ui_extension_data }; LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) { diff --git a/test/product.json b/test/product.json index 0e1f1c7..167c89b 100644 --- a/test/product.json +++ b/test/product.json @@ -132,6 +132,24 @@ "list": false, "unit": "", "map": "linear" + }, + { + "name": "cpu", + "shortName": "cpu", + "id": "cpu", + "direction": "output", + "isBypass": false, + "isLatency": false, + "isCpumeter": true, + "defaultValue": 0.0, + "minimum": 0.0, + "maximum": 1.0, + "toggled": false, + "optional": false, + "integer": false, + "list": false, + "unit": "%", + "map": "linear" } ], "ui": { diff --git a/test/run.sh b/test/run.sh index 50f3173..3b86b9f 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,6 +7,7 @@ cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src $dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2 $dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json,$dir/lv2-make.json $dir/../templates/lv2-make $dir/../out/lv2 +cp $dir/../templates/common/* $dir/../out/lv2/src/ cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web From 0fa25e8dc7a7e720f845181508d4c3073a150ec0 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Wed, 3 Jul 2024 17:13:04 +0200 Subject: [PATCH 02/18] fix typo --- templates/lv2/src/lv2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/lv2/src/lv2.c b/templates/lv2/src/lv2.c index c23933e..bde12e6 100644 --- a/templates/lv2/src/lv2.c +++ b/templates/lv2/src/lv2.c @@ -422,8 +422,8 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch plugin_ui_callbacks cbs = { /* .handle = */ (void *)instance, - /* .format. = */ "lv2", - /* .get_bindir. = */ ui_get_bundle_path_cb, + /* .format = */ "lv2", + /* .get_bindir = */ ui_get_bundle_path_cb, /* .get_datadir = */ ui_get_bundle_path_cb, # if DATA_PRODUCT_CONTROL_INPUTS_N > 0 /* .set_parameter = */ ui_set_parameter_cb From 8ffbd207fe2f0ee26c27863ae60df36acc6971f1 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Wed, 3 Jul 2024 17:32:34 +0200 Subject: [PATCH 03/18] better indentation --- templates/ios/src/data.h | 72 ++++++++++++++------------- templates/ios/src/native.mm | 98 ++++++++++++++++++------------------- test/plugin.h | 22 ++++----- 3 files changed, 98 insertions(+), 94 deletions(-) diff --git a/templates/ios/src/data.h b/templates/ios/src/data.h index 8b3d2a1..c600b3b 100644 --- a/templates/ios/src/data.h +++ b/templates/ios/src/data.h @@ -18,66 +18,70 @@ * File author: Stefano D'Angelo */ -#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} -#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} +#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} +#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} -#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} -#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} -#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} +#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} -#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} +#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} #if NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT > 0 static struct { - size_t index; - char out; - char optional; - char channels; + size_t index; + char out; + char optional; + char channels; } audio_bus_data[NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT] = { {{~it.product.buses :b:i}} {{?b.type == "audio"}} { - /* .index = */ {{=i}}, - /* .out = */ {{=b.direction == "output" ? 1 : 0}}, - /* .optional = */ {{=b.optional ? 1 : 0}}, - /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} + /* .index = */ {{=i}}, + /* .out = */ {{=b.direction == "output" ? 1 : 0}}, + /* .optional = */ {{=b.optional ? 1 : 0}}, + /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} }, {{?}} {{~}} }; #endif -#define PARAMETERS_N {{=it.product.parameters.length}} +#define PARAMETERS_N {{=it.product.parameters.length}} #if PARAMETERS_N > 0 -# define PARAM_BYPASS 1 -# define PARAM_TOGGLED (1<<1) -# define PARAM_INTEGER (1<<2) +# define PARAM_BYPASS 1 +# define PARAM_TOGGLED (1<<1) +# define PARAM_INTEGER (1<<2) static struct { - char out; - float def; - float min; - float max; - uint32_t flags; + char out; + float def; + float min; + float max; + uint32_t flags; } param_data[PARAMETERS_N] = { {{~it.product.parameters :p}} { - /* .out = */ {{=p.direction == "output" ? 1 : 0}}, - /* .def = */ {{=p.defaultValue.toExponential()}}, - /* .min = */ {{=p.minimum.toExponential()}}f, - /* .max = */ {{=p.maximum.toExponential()}}f, - /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??p.isLatency}}PARAM_INTEGER{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} + /* .out = */ {{=p.direction == "output" ? 1 : 0}}, + /* .def = */ {{=p.defaultValue.toExponential()}}, + /* .min = */ {{=p.minimum.toExponential()}}f, + /* .max = */ {{=p.maximum.toExponential()}}f, + /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??p.isLatency}}PARAM_INTEGER{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} }, {{~}} }; + +{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}} +# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}} +{{?}} #endif diff --git a/templates/ios/src/native.mm b/templates/ios/src/native.mm index 509328f..83d691d 100644 --- a/templates/ios/src/native.mm +++ b/templates/ios/src/native.mm @@ -22,10 +22,10 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; #include "data.h" @@ -42,47 +42,47 @@ typedef struct { #include "miniaudio.h" #define BLOCK_SIZE 32 -static ma_device device; -static ma_device_config deviceConfig; -char device_inited = 0; -static plugin instance; -static void * mem; +static ma_device device; +static ma_device_config deviceConfig; +char device_inited = 0; +static plugin instance; +static void *mem; #if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN -float zero[BLOCK_SIZE]; +float zero[BLOCK_SIZE]; #endif #if NUM_CHANNELS_IN > 0 -float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; -float * x_in[NUM_CHANNELS_IN]; +float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; +float *x_in[NUM_CHANNELS_IN]; #endif #if NUM_ALL_CHANNELS_IN > 0 -const float * x[NUM_ALL_CHANNELS_IN]; +const float *x[NUM_ALL_CHANNELS_IN]; #else -const float ** x; +const float **x; #endif #if NUM_NON_OPT_CHANNELS_OUT > 0 -float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; +float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; #endif #if NUM_CHANNELS_OUT > 0 -float * y_out[NUM_CHANNELS_OUT]; +float *y_out[NUM_CHANNELS_OUT]; #endif #if NUM_ALL_CHANNELS_OUT > 0 -float * y[NUM_ALL_CHANNELS_OUT]; +float *y[NUM_ALL_CHANNELS_OUT]; #else -float ** y; +float **y; #endif #if PARAMETERS_N > 0 -std::mutex mutex; -float param_values[PARAMETERS_N]; -float param_values_prev[PARAMETERS_N]; +std::mutex mutex; +float param_values[PARAMETERS_N]; +float param_values_prev[PARAMETERS_N]; #endif #if NUM_MIDI_INPUTS > 0 -CFStringRef midiClientName = NULL; -MIDIClientRef midiClient = NULL; -CFStringRef midiInputName = NULL; -MIDIPortRef midiPort = NULL; +CFStringRef midiClientName = NULL; +MIDIClientRef midiClient = NULL; +CFStringRef midiInputName = NULL; +MIDIPortRef midiPort = NULL; #define MIDIBUFFERLEN 1023 -uint8_t midiBuffer[MIDIBUFFERLEN]; -int midiBuffer_i = 0; +uint8_t midiBuffer[MIDIBUFFERLEN]; +int midiBuffer_i = 0; #endif static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { @@ -182,7 +182,7 @@ void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^( continue; mutex.lock(); if (midiBuffer_i < MIDIBUFFERLEN - 3) { - midiBuffer[midiBuffer_i ] = t[2]; + midiBuffer[midiBuffer_i ] = t[2]; midiBuffer[midiBuffer_i + 1] = t[1]; midiBuffer[midiBuffer_i + 2] = t[0]; midiBuffer_i += 3; @@ -208,26 +208,26 @@ char audioStart() { deviceConfig = ma_device_config_init(ma_device_type_playback); #endif - deviceConfig.periodSizeInFrames = BLOCK_SIZE; - deviceConfig.periods = 1; - deviceConfig.performanceProfile = ma_performance_profile_low_latency; - deviceConfig.noPreSilencedOutputBuffer = 1; - deviceConfig.noClip = 0; - deviceConfig.noDisableDenormals = 0; - deviceConfig.noFixedSizedCallback = 1; - deviceConfig.dataCallback = data_callback; - deviceConfig.capture.pDeviceID = NULL; - deviceConfig.capture.format = ma_format_f32; - deviceConfig.capture.channels = NUM_CHANNELS_IN; - deviceConfig.capture.shareMode = ma_share_mode_shared; - deviceConfig.playback.pDeviceID = NULL; - deviceConfig.playback.format = ma_format_f32; + deviceConfig.periodSizeInFrames = BLOCK_SIZE; + deviceConfig.periods = 1; + deviceConfig.performanceProfile = ma_performance_profile_low_latency; + deviceConfig.noPreSilencedOutputBuffer = 1; + deviceConfig.noClip = 0; + deviceConfig.noDisableDenormals = 0; + deviceConfig.noFixedSizedCallback = 1; + deviceConfig.dataCallback = data_callback; + deviceConfig.capture.pDeviceID = NULL; + deviceConfig.capture.format = ma_format_f32; + deviceConfig.capture.channels = NUM_CHANNELS_IN; + deviceConfig.capture.shareMode = ma_share_mode_shared; + deviceConfig.playback.pDeviceID = NULL; + deviceConfig.playback.format = ma_format_f32; #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 - deviceConfig.playback.channels = NUM_CHANNELS_OUT; + deviceConfig.playback.channels = NUM_CHANNELS_OUT; #else - deviceConfig.playback.channels = 1; // Fake & muted + deviceConfig.playback.channels = 1; // Fake & muted #endif - deviceConfig.playback.shareMode = ma_share_mode_shared; + deviceConfig.playback.shareMode = ma_share_mode_shared; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) return false; @@ -260,10 +260,10 @@ char audioStart() { #endif plugin_callbacks cbs = { - /* .handle = */ NULL, - /* .format = */ "ios", - /* .get_bindir = */ NULL, - /* .get_datadir = */ NULL + /* .handle = */ NULL, + /* .format = */ "ios", + /* .get_bindir = */ NULL, + /* .get_datadir = */ NULL }; plugin_init(&instance, &cbs); diff --git a/test/plugin.h b/test/plugin.h index ffbbb13..4bbf97e 100644 --- a/test/plugin.h +++ b/test/plugin.h @@ -19,19 +19,19 @@ */ typedef struct plugin { - float sample_rate; - size_t delay_line_length; + float sample_rate; + size_t delay_line_length; - float gain; - float delay; - float cutoff; - char bypass; + float gain; + float delay; + float cutoff; + char bypass; - float * delay_line; - size_t delay_line_cur; - float z1; - float cutoff_k; - float yz1; + float *delay_line; + size_t delay_line_cur; + float z1; + float cutoff_k; + float yz1; } plugin; static void plugin_init(plugin *instance, plugin_callbacks *cbs) { From 67cddf552be91d74fdd50ad27648976383b9f773 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Wed, 3 Jul 2024 18:00:09 +0200 Subject: [PATCH 04/18] cpu meter ios --- templates/ios-make/Makefile | 1 + templates/ios/src/native.mm | 40 ++++++++++++++++++++++++++++++------- test/run.sh | 1 + 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/templates/ios-make/Makefile b/templates/ios-make/Makefile index 4d84418..855f8c2 100644 --- a/templates/ios-make/Makefile +++ b/templates/ios-make/Makefile @@ -31,6 +31,7 @@ SOURCES := \ $(COMMON_DIR)/src/native.mm \ $(COMMON_DIR)/src/app-Bridging-Header.h \ $(PLUGIN_DIR)/plugin.h \ + $(PLUGIN_DIR)/fatica.h \ $(C_SRCS_EXTRA) \ $(CXX_SRCS_EXTRA) \ $(SRCS_EXTRA) diff --git a/templates/ios/src/native.mm b/templates/ios/src/native.mm index 83d691d..00ed24d 100644 --- a/templates/ios/src/native.mm +++ b/templates/ios/src/native.mm @@ -31,16 +31,19 @@ typedef struct { #include "data.h" #include "plugin.h" #if PARAMETERS_N > 0 -#include +# include #endif #if PARAMETERS_N + NUM_MIDI_INPUTS > 0 -#include +# include #endif #include #define MINIAUDIO_IMPLEMENTATION #define MA_NO_RUNTIME_LINKING #include "miniaudio.h" #define BLOCK_SIZE 32 +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif static ma_device device; static ma_device_config deviceConfig; @@ -84,10 +87,18 @@ MIDIPortRef midiPort = NULL; uint8_t midiBuffer[MIDIBUFFERLEN]; int midiBuffer_i = 0; #endif +#ifdef PARAM_OUT_CPU_INDEX +float cpu_meter = 0.f; +float sample_rate = 1.f; +#endif static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { (void)pDevice; - + +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeStart = fatica_time_process(); +#endif + #if defined(__aarch64__) uint64_t fpcr; __asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr)); @@ -98,9 +109,16 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, if (mutex.try_lock()) { # if PARAMETERS_N > 0 for (size_t i = 0; i < PARAMETERS_N; i++) { - if (param_data[i].out) - param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); - else if (param_values_prev[i] != param_values[i]) { + if (param_data[i].out) { +# ifdef PARAM_OUT_CPU_INDEX + if (i == PARAM_OUT_CPU_INDEX) { + param_values_prev[i] = param_values[i] = cpu_meter; + continue; + } +# endif + param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); + } + else if (param_values_prev[i] != param_values[i]) { plugin_set_parameter(&instance, i, param_values[i]); param_values_prev[i] = param_values[i]; } @@ -158,6 +176,13 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, #if defined(__aarch64__) __asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr)); #endif + +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + cpu_meter = cpu_meter * 0.9f + ((float) (processTimeS * sample_rate)) * 0.1f; +#endif } #if (NUM_MIDI_INPUTS > 0) @@ -276,7 +301,8 @@ char audioStart() { #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); - + sample_rate = (float)device.sampleRate; + size_t req = plugin_mem_req(&instance); if (req != 0) { mem = malloc(req); diff --git a/test/run.sh b/test/run.sh index 3b86b9f..dda595b 100755 --- a/test/run.sh +++ b/test/run.sh @@ -22,6 +22,7 @@ cp $dir/plugin.h $dir/../out/android/src $dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json $dir/../templates/ios $dir/../out/ios $dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json,$dir/ios-make.json $dir/../templates/ios-make $dir/../out/ios +cp $dir/../templates/common/* $dir/../out/ios/src/ cp $dir/plugin.h $dir/../out/ios/src $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd $dir/../out/cmd From ebf2a2052c496c988a162bdefca4e66caccbdc73 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Thu, 4 Jul 2024 09:48:34 +0200 Subject: [PATCH 05/18] vst3 indentation/alignment --- templates/vst3/src/data.h | 216 +++++++++++++------------- templates/vst3/src/vst3.c | 308 +++++++++++++++++++------------------- 2 files changed, 262 insertions(+), 262 deletions(-) diff --git a/templates/vst3/src/data.h b/templates/vst3/src/data.h index a8e5f4b..4841551 100644 --- a/templates/vst3/src/data.h +++ b/templates/vst3/src/data.h @@ -18,54 +18,54 @@ * File author: Stefano D'Angelo */ -#define DATA_COMPANY_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.company.name, 63)}}" -#define DATA_COMPANY_URL "{{=it.tibia.CGetUTF8StringLiteral(it.company.url, 255)}}" -#define DATA_COMPANY_EMAIL "{{=it.tibia.CGetUTF8StringLiteral(it.company.email, 127)}}" +#define DATA_COMPANY_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.company.name, 63)}}" +#define DATA_COMPANY_URL "{{=it.tibia.CGetUTF8StringLiteral(it.company.url, 255)}}" +#define DATA_COMPANY_EMAIL "{{=it.tibia.CGetUTF8StringLiteral(it.company.email, 127)}}" -#define DATA_PRODUCT_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.product.name, 63)}}" -#define DATA_PRODUCT_VERSION "{{=(it.product.version + '.' + it.product.buildVersion).substring(0, 63)}}" +#define DATA_PRODUCT_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.product.name, 63)}}" +#define DATA_PRODUCT_VERSION "{{=(it.product.version + '.' + it.product.buildVersion).substring(0, 63)}}" -static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; -static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; +static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; +static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; -#define DATA_VST3_SDK_VERSION "VST 3.7.9" -static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; +#define DATA_VST3_SDK_VERSION "VST 3.7.9" +static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; static Steinberg_char16 dataVST3ControllerNameW[64] = { {{~Array.from(it.product.name + " Controller").slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }; -#define DATA_VST3_PLUGIN_CID_1 0x{{=it.vst3.plugin.cid.substring(0, 8)}} -#define DATA_VST3_PLUGIN_CID_2 0x{{=it.vst3.plugin.cid.substring(8, 16)}} -#define DATA_VST3_PLUGIN_CID_3 0x{{=it.vst3.plugin.cid.substring(16, 24)}} -#define DATA_VST3_PLUGIN_CID_4 0x{{=it.vst3.plugin.cid.substring(24, 32)}} +#define DATA_VST3_PLUGIN_CID_1 0x{{=it.vst3.plugin.cid.substring(0, 8)}} +#define DATA_VST3_PLUGIN_CID_2 0x{{=it.vst3.plugin.cid.substring(8, 16)}} +#define DATA_VST3_PLUGIN_CID_3 0x{{=it.vst3.plugin.cid.substring(16, 24)}} +#define DATA_VST3_PLUGIN_CID_4 0x{{=it.vst3.plugin.cid.substring(24, 32)}} -#define DATA_VST3_CONTROLLER_CID_1 0x{{=it.vst3.controller.cid.substring(0, 8)}} -#define DATA_VST3_CONTROLLER_CID_2 0x{{=it.vst3.controller.cid.substring(8, 16)}} -#define DATA_VST3_CONTROLLER_CID_3 0x{{=it.vst3.controller.cid.substring(16, 24)}} -#define DATA_VST3_CONTROLLER_CID_4 0x{{=it.vst3.controller.cid.substring(24, 32)}} +#define DATA_VST3_CONTROLLER_CID_1 0x{{=it.vst3.controller.cid.substring(0, 8)}} +#define DATA_VST3_CONTROLLER_CID_2 0x{{=it.vst3.controller.cid.substring(8, 16)}} +#define DATA_VST3_CONTROLLER_CID_3 0x{{=it.vst3.controller.cid.substring(16, 24)}} +#define DATA_VST3_CONTROLLER_CID_4 0x{{=it.vst3.controller.cid.substring(24, 32)}} -static const Steinberg_TUID dataPluginCID = SMTG_INLINE_UID(DATA_VST3_PLUGIN_CID_1, DATA_VST3_PLUGIN_CID_2, DATA_VST3_PLUGIN_CID_3, DATA_VST3_PLUGIN_CID_4); +static const Steinberg_TUID dataPluginCID = SMTG_INLINE_UID(DATA_VST3_PLUGIN_CID_1, DATA_VST3_PLUGIN_CID_2, DATA_VST3_PLUGIN_CID_3, DATA_VST3_PLUGIN_CID_4); static const Steinberg_TUID dataControllerCID = SMTG_INLINE_UID(DATA_VST3_CONTROLLER_CID_1, DATA_VST3_CONTROLLER_CID_2, DATA_VST3_CONTROLLER_CID_3, DATA_VST3_CONTROLLER_CID_4); -#define DATA_VST3_SUBCATEGORY "{{=it.vst3.subCategory}}" +#define DATA_VST3_SUBCATEGORY "{{=it.vst3.subCategory}}" -#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} -#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} -#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} -#define DATA_PRODUCT_BUSES_MIDI_OUTPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}} +#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} +#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} +#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} +#define DATA_PRODUCT_BUSES_MIDI_OUTPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}} -#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} #if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_AUDIO_INPUT_N] = { {{~it.product.buses.filter(x => x.type == "audio" && x.direction == "input") :b}} { - /* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio, - /* .direction = */ Steinberg_Vst_BusDirections_kInput, - /* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}}, - /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, - /* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} + /* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio, + /* .direction = */ Steinberg_Vst_BusDirections_kInput, + /* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}}, + /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, + /* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} }, {{~}} }; @@ -75,12 +75,12 @@ static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_AUDIO_I static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N] = { {{~it.product.buses.filter(x => x.type == "audio" && x.direction == "output") :b}} { - /* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio, - /* .direction = */ Steinberg_Vst_BusDirections_kOutput, - /* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}}, - /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, - /* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} + /* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio, + /* .direction = */ Steinberg_Vst_BusDirections_kOutput, + /* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}}, + /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, + /* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} }, {{~}} }; @@ -90,12 +90,12 @@ static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PRODUCT_BUSES_AUDIO_ static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = { {{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b}} { - /* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent, - /* .direction = */ Steinberg_Vst_BusDirections_kInput, - /* .channelCount = */ 16, - /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, - /* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} + /* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent, + /* .direction = */ Steinberg_Vst_BusDirections_kInput, + /* .channelCount = */ 16, + /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, + /* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} }, {{~}} }; @@ -105,12 +105,12 @@ static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INP static struct Steinberg_Vst_BusInfo busInfoMidiOutput[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N] = { {{~it.product.buses.filter(x => x.type == "midi" && x.direction == "output") :b}} { - /* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent, - /* .direction = */ Steinberg_Vst_BusDirections_kOutput, - /* .channelCount = */ 16, - /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, - /* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} + /* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent, + /* .direction = */ Steinberg_Vst_BusDirections_kOutput, + /* .channelCount = */ 16, + /* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}}, + /* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}} }, {{~}} }; @@ -122,91 +122,91 @@ static uint32_t midiInIndex[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = { }; #endif -#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}} +#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}} #if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = { {{~it.product.parameters.filter(x => !x.isLatency) :p:i}} { {{?p.isBypass}} - /* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}}, - /* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .units = */ { 0 }, - /* .stepCount = */ 1, - /* .defaultNormalizedValue = */ 0.0, - /* .unitId = */ 0, - /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate + /* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}}, + /* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .units = */ { 0 }, + /* .stepCount = */ 1, + /* .defaultNormalizedValue = */ 0.0, + /* .unitId = */ 0, + /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate {{??}} - /* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 0}}, - /* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .stepCount = */ {{=p.toggled ? 1 : (p.list && p.scalePoints.length > 1 ? p.scalePoints.length - 1 : (p.integer ? p.maximum - p.minimum : 0))}}, - /* .defaultNormalizedValue = */ {{?p.map == "logarithmic"}}{{=Number(Math.log(p.defaultValue / p.minimum) / (2 * Math.log(Math.sqrt(p.minimum * p.maximum) / Math.abs(p.minimum)))).toExponential()}}{{??}}{{=Number((p.defaultValue - p.minimum) / (p.maximum - p.minimum)).toExponential()}}{{?}}, - /* .unitId = */ 0, - /* .flags = */ {{?p.direction == "input"}}Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate{{??}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly{{?}} + /* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 0}}, + /* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .stepCount = */ {{=p.toggled ? 1 : (p.list && p.scalePoints.length > 1 ? p.scalePoints.length - 1 : (p.integer ? p.maximum - p.minimum : 0))}}, + /* .defaultNormalizedValue = */ {{?p.map == "logarithmic"}}{{=Number(Math.log(p.defaultValue / p.minimum) / (2 * Math.log(Math.sqrt(p.minimum * p.maximum) / Math.abs(p.minimum)))).toExponential()}}{{??}}{{=Number((p.defaultValue - p.minimum) / (p.maximum - p.minimum)).toExponential()}}{{?}}, + /* .unitId = */ 0, + /* .flags = */ {{?p.direction == "input"}}Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate{{??}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly{{?}} {{?}} }, {{~}} {{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}} { - /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}}, - /* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .units = */ { 0 }, - /* .stepCount = */ 0, - /* .defaultNormalizedValue = */ 0.0, - /* .unitId = */ 0, - /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate + /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}}, + /* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .units = */ { 0 }, + /* .stepCount = */ 0, + /* .defaultNormalizedValue = */ 0.0, + /* .unitId = */ 0, + /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate }, { - /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}}, - /* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .units = */ { 0 }, - /* .stepCount = */ 0, - /* .defaultNormalizedValue = */ 0.5, - /* .unitId = */ 0, - /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate + /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}}, + /* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .units = */ { 0 }, + /* .stepCount = */ 0, + /* .defaultNormalizedValue = */ 0.5, + /* .unitId = */ 0, + /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate }, { - /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}}, - /* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, - /* .units = */ { 0 }, - /* .stepCount = */ 0, - /* .defaultNormalizedValue = */ 0.0, - /* .unitId = */ 0, - /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate + /* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}}, + /* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 }, + /* .units = */ { 0 }, + /* .stepCount = */ 0, + /* .defaultNormalizedValue = */ 0.0, + /* .unitId = */ 0, + /* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate }, {{~}} }; # if DATA_PRODUCT_PARAMETERS_N > 0 -# define DATA_PARAM_BYPASS 1 -# define DATA_PARAM_TOGGLED (1<<1) -# define DATA_PARAM_INTEGER (1<<2) -# define DATA_PARAM_MAP_LOG (1<<3) +# define DATA_PARAM_BYPASS 1 +# define DATA_PARAM_TOGGLED (1<<1) +# define DATA_PARAM_INTEGER (1<<2) +# define DATA_PARAM_MAP_LOG (1<<3) static struct { - size_t index; - double min; - double max; - double def; - uint32_t flags; - double mapK; + size_t index; + double min; + double max; + double def; + uint32_t flags; + double mapK; // scalePoints? } parameterData[DATA_PRODUCT_PARAMETERS_N] = { {{~it.product.parameters.filter(x => !x.isLatency) :p:i}} { - /* .index = */ {{=p.paramIndex}}, - /* .min = */ {{=p.minimum.toExponential()}}, - /* .max = */ {{=p.maximum.toExponential()}}, - /* .def = */ {{=p.defaultValue.toExponential()}}, - /* .flags = */ {{?p.isBypass}}DATA_PARAM_BYPASS{{??}}0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?p.map == "logarithmic"}} | DATA_PARAM_MAP_LOG{{?}}{{?}}, - /* .mapK = */ {{?p.map == "logarithmic"}}{{=Number(2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))).toExponential()}}{{??}}0.0{{?}} + /* .index = */ {{=p.paramIndex}}, + /* .min = */ {{=p.minimum.toExponential()}}, + /* .max = */ {{=p.maximum.toExponential()}}, + /* .def = */ {{=p.defaultValue.toExponential()}}, + /* .flags = */ {{?p.isBypass}}DATA_PARAM_BYPASS{{??}}0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?p.map == "logarithmic"}} | DATA_PARAM_MAP_LOG{{?}}{{?}}, + /* .mapK = */ {{?p.map == "logarithmic"}}{{=Number(2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))).toExponential()}}{{??}}0.0{{?}} }, {{~}} }; @@ -216,10 +216,10 @@ static struct { #endif {{?it.product.parameters.find(x => x.isLatency)}} -#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}} +#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}} {{?}} {{?it.product.ui}} #define DATA_UI -#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}} +#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}} {{?}} diff --git a/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index 12483ad..3bda8da 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -22,18 +22,18 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); - void (*set_parameter)(void *handle, size_t index, float value); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); + void (*set_parameter)(void *handle, size_t index, float value); } plugin_ui_callbacks; #pragma GCC diagnostic push @@ -83,8 +83,8 @@ typedef struct Steinberg_ITimerHandlerVtbl { /* methods derived from "Steinberg_FUnknown": */ Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); /* methods derived from "Steinberg_ITimerHandler": */ void (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface); @@ -101,8 +101,8 @@ typedef struct Steinberg_IEventHandlerVtbl { /* methods derived from "Steinberg_FUnknown": */ Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); /* methods derived from "Steinberg_IEventHandler": */ void (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, int fd); @@ -120,8 +120,8 @@ typedef struct Steinberg_IRunLoopVtbl { /* methods derived from "Steinberg_FUnknown": */ Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); - Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); /* methods derived from "Steinberg_IRunLoop": */ Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler, int fd); @@ -193,35 +193,35 @@ static double parameterAdjust(int i, double v) { } typedef struct pluginInstance { - Steinberg_Vst_IComponentVtbl * vtblIComponent; - Steinberg_Vst_IAudioProcessorVtbl * vtblIAudioProcessor; - Steinberg_Vst_IProcessContextRequirementsVtbl * vtblIProcessContextRequirements; - Steinberg_uint32 refs; - Steinberg_FUnknown * context; - plugin p; - float sampleRate; + Steinberg_Vst_IComponentVtbl *vtblIComponent; + Steinberg_Vst_IAudioProcessorVtbl *vtblIAudioProcessor; + Steinberg_Vst_IProcessContextRequirementsVtbl *vtblIProcessContextRequirements; + Steinberg_uint32 refs; + Steinberg_FUnknown *context; + plugin p; + float sampleRate; #if DATA_PRODUCT_PARAMETERS_N > 0 - float parameters[DATA_PRODUCT_PARAMETERS_N]; + float parameters[DATA_PRODUCT_PARAMETERS_N]; #endif #if DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N > 0 - const float * inputs[DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N]; + const float *inputs[DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N]; #endif #if DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N > 0 - float * outputs[DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N]; + float *outputs[DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N]; #endif #if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 - char inputsActive[DATA_PRODUCT_BUSES_AUDIO_INPUT_N]; + char inputsActive[DATA_PRODUCT_BUSES_AUDIO_INPUT_N]; #endif #if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 - char outputsActive[DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N]; + char outputsActive[DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N]; #endif #if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 - char midiInputsActive[DATA_PRODUCT_BUSES_MIDI_INPUT_N]; + char midiInputsActive[DATA_PRODUCT_BUSES_MIDI_INPUT_N]; #endif #if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 - char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N]; + char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N]; #endif - void * mem; + void *mem; } pluginInstance; static Steinberg_Vst_IComponentVtbl pluginVtblIComponent; @@ -290,10 +290,10 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_ p->context = context; plugin_callbacks cbs = { - /* .handle = */ (void *)p, - /* .format = */ "vst3", - /* .get_bindir = */ get_bindir_cb, - /* .get_datadir = */ get_datadir_cb + /* .handle = */ (void *)p, + /* .format = */ "vst3", + /* .get_bindir = */ get_bindir_cb, + /* .get_datadir = */ get_datadir_cb }; plugin_init(&p->p, &cbs); #if DATA_PRODUCT_PARAMETERS_N > 0 @@ -555,24 +555,24 @@ static Steinberg_tresult pluginGetState(void* thisInterface, struct Steinberg_IB static Steinberg_Vst_IComponentVtbl pluginVtblIComponent = { /* FUnknown */ - /* .queryInterface = */ pluginIComponentQueryInterface, - /* .addRef = */ pluginIComponentAddRef, - /* .release = */ pluginIComponentRelease, + /* .queryInterface = */ pluginIComponentQueryInterface, + /* .addRef = */ pluginIComponentAddRef, + /* .release = */ pluginIComponentRelease, /* IPluginBase */ - /* .initialize = */ pluginInitialize, - /* .terminate = */ pluginTerminate, + /* .initialize = */ pluginInitialize, + /* .terminate = */ pluginTerminate, /* IComponent */ - /* .getControllerClassId = */ pluginGetControllerClassId, - /* .setIoMode = */ pluginSetIoMode, - /* .getBusCount = */ pluginGetBusCount, - /* .getBusInfo = */ pluginGetBusInfo, - /* .getRoutingInfo = */ pluginGetRoutingInfo, - /* .activateBus = */ pluginActivateBus, - /* .setActive = */ pluginSetActive, - /* .setState = */ pluginSetState, - /* .getState = */ pluginGetState + /* .getControllerClassId = */ pluginGetControllerClassId, + /* .setIoMode = */ pluginSetIoMode, + /* .getBusCount = */ pluginGetBusCount, + /* .getBusInfo = */ pluginGetBusInfo, + /* .getRoutingInfo = */ pluginGetRoutingInfo, + /* .activateBus = */ pluginActivateBus, + /* .setActive = */ pluginSetActive, + /* .setState = */ pluginSetState, + /* .getState = */ pluginGetState }; static Steinberg_tresult pluginIAudioProcessorQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { @@ -850,19 +850,19 @@ static Steinberg_uint32 pluginGetTailSamples(void* thisInterface) { static Steinberg_Vst_IAudioProcessorVtbl pluginVtblIAudioProcessor = { /* FUnknown */ - /* .queryInterface = */ pluginIAudioProcessorQueryInterface, - /* .addRef = */ pluginIAudioProcessorAddRef, - /* .release = */ pluginIAudioProcessorRelease, + /* .queryInterface = */ pluginIAudioProcessorQueryInterface, + /* .addRef = */ pluginIAudioProcessorAddRef, + /* .release = */ pluginIAudioProcessorRelease, /* IAudioProcessor */ - /* .setBusArrangements = */ pluginSetBusArrangements, - /*. getBusArrangement = */ pluginGetBusArrangement, - /* .canProcessSampleSize = */ pluginCanProcessSampleSize, - /* .getLatencySamples = */ pluginGetLatencySamples, - /* .setupProcessing = */ pluginSetupProcessing, - /* .setProcessing = */ pluginSetProcessing, - /* .process = */ pluginProcess, - /* .getTailSamples = */ pluginGetTailSamples + /* .setBusArrangements = */ pluginSetBusArrangements, + /*. getBusArrangement = */ pluginGetBusArrangement, + /* .canProcessSampleSize = */ pluginCanProcessSampleSize, + /* .getLatencySamples = */ pluginGetLatencySamples, + /* .setupProcessing = */ pluginSetupProcessing, + /* .setProcessing = */ pluginSetProcessing, + /* .process = */ pluginProcess, + /* .getTailSamples = */ pluginGetTailSamples }; static Steinberg_tresult pluginIProcessContextRequirementsQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { @@ -889,31 +889,31 @@ static Steinberg_uint32 pluginGetProcessContextRequirements(void* thisInterface) static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRequirements = { /* FUnknown */ - /* .queryInterface = */ pluginIProcessContextRequirementsQueryInterface, - /* .addRef = */ pluginIProcessContextRequirementsAddRef, - /* .release = */ pluginIProcessContextRequirementsRelease, + /* .queryInterface = */ pluginIProcessContextRequirementsQueryInterface, + /* .addRef = */ pluginIProcessContextRequirementsAddRef, + /* .release = */ pluginIProcessContextRequirementsRelease, /* IProcessContextRequirements */ - /* .getProcessContextRequirements = */ pluginGetProcessContextRequirements + /* .getProcessContextRequirements = */ pluginGetProcessContextRequirements }; typedef struct plugView plugView; typedef struct controller { - Steinberg_Vst_IEditControllerVtbl * vtblIEditController; - Steinberg_Vst_IMidiMappingVtbl * vtblIMidiMapping; + Steinberg_Vst_IEditControllerVtbl *vtblIEditController; + Steinberg_Vst_IMidiMappingVtbl *vtblIMidiMapping; #ifdef DATA_UI //Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint; #endif - Steinberg_uint32 refs; - Steinberg_FUnknown * context; + Steinberg_uint32 refs; + Steinberg_FUnknown *context; #if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 - double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N]; + double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N]; #endif - struct Steinberg_Vst_IComponentHandler * componentHandler; + struct Steinberg_Vst_IComponentHandler *componentHandler; #ifdef DATA_UI - plugView ** views; - size_t viewsCount; + plugView **views; + size_t viewsCount; #endif } controller; @@ -926,10 +926,10 @@ static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController; # include typedef struct { - Steinberg_ITimerHandlerVtbl * vtblITimerHandler; - Steinberg_uint32 refs; - void * data; - void (*cb)(void *data); + Steinberg_ITimerHandlerVtbl *vtblITimerHandler; + Steinberg_uint32 refs; + void *data; + void (*cb)(void *data); } timerHandler; static Steinberg_tresult timerHandlerQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { @@ -980,12 +980,12 @@ static void timerHandlerOnTimer(void* thisInterface) { static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = { /* FUnknown */ - /* .queryInterface = */ timerHandlerQueryInterface, - /* .addRef = */ timerHandlerAddRef, - /* .release = */ timerHandlerRelease, + /* .queryInterface = */ timerHandlerQueryInterface, + /* .addRef = */ timerHandlerAddRef, + /* .release = */ timerHandlerRelease, /* ITimerHandler */ - /* .onTimer = */ timerHandlerOnTimer + /* .onTimer = */ timerHandlerOnTimer }; # elif defined(__APPLE__) @@ -998,19 +998,19 @@ static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = { # endif typedef struct plugView { - Steinberg_IPlugViewVtbl * vtblIPlugView; - Steinberg_uint32 refs; - Steinberg_IPlugFrame * frame; - plugin_ui * ui; - controller * ctrl; + Steinberg_IPlugViewVtbl *vtblIPlugView; + Steinberg_uint32 refs; + Steinberg_IPlugFrame *frame; + plugin_ui *ui; + controller *ctrl; # ifdef __linux__ - Steinberg_IRunLoop * runLoop; - timerHandler timer; - Display * display; + Steinberg_IRunLoop *runLoop; + timerHandler timer; + Display *display; # elif defined(__APPLE__) - CFRunLoopTimerRef timer; + CFRunLoopTimerRef timer; # elif defined(_WIN32) || defined(__CYGWIN__) - UINT_PTR timer; + UINT_PTR timer; # endif } plugView; @@ -1132,14 +1132,14 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste return Steinberg_kInvalidArgument; plugin_ui_callbacks cbs = { - /* .handle = */ (void *)v, - /* .format = */ "vst3", - /* .get_bindir = */ get_bindir_cb, - /* .get_datadir = */ get_datadir_cb, + /* .handle = */ (void *)v, + /* .format = */ "vst3", + /* .get_bindir = */ get_bindir_cb, + /* .get_datadir = */ get_datadir_cb, # if DATA_PRODUCT_PARAMETERS_N > 0 - /* .set_parameter = */ plugViewSetParameterCb + /* .set_parameter = */ plugViewSetParameterCb # else - /* .set_parameter = */ NULL + /* .set_parameter = */ NULL # endif }; v->ui = plugin_ui_create(1, parent, &cbs); @@ -1161,11 +1161,11 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste } # elif defined(__APPLE__) CFRunLoopTimerContext ctx = { - /* .version = */ 0, - /* .info = */ v, - /* .retain = */ NULL, - /* .release = */ NULL, - /* .copyDescription = */ NULL + /* .version = */ 0, + /* .info = */ v, + /* .retain = */ NULL, + /* .release = */ NULL, + /* .copyDescription = */ NULL }; v->timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 20.0 / 1000.0, 0, 0, plugViewTimerCb, &ctx); CFRunLoopAddTimer(CFRunLoopGetCurrent(), v->timer, kCFRunLoopCommonModes); @@ -1354,23 +1354,23 @@ static void plugViewOnTimer(void *thisInterface) { static Steinberg_IPlugViewVtbl plugViewVtblIPlugView = { /* FUnknown */ - /* .queryInterface = */ plugViewQueryInterface, - /* .addRef = */ plugViewAddRef, - /* .release = */ plugViewRelease, + /* .queryInterface = */ plugViewQueryInterface, + /* .addRef = */ plugViewAddRef, + /* .release = */ plugViewRelease, /* IPlugView */ - /* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported, - /* .attached = */ plugViewAttached, - /* .removed = */ plugViewRemoved, - /* .onWheel = */ plugViewOnWheel, - /* .onKeyDown = */ plugViewOnKeyDown, - /* .onKeyUp = */ plugViewOnKeyUp, - /* .getSize = */ plugViewGetSize, - /* .onSize = */ plugViewOnSize, - /* .onFocus = */ plugViewOnFocus, - /* .setFrame = */ plugViewSetFrame, - /* .canResize = */ plugViewCanResize, - /* .checkSizeConstraint = */ plugViewCheckSizeConstraint + /* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported, + /* .attached = */ plugViewAttached, + /* .removed = */ plugViewRemoved, + /* .onWheel = */ plugViewOnWheel, + /* .onKeyDown = */ plugViewOnKeyDown, + /* .onKeyUp = */ plugViewOnKeyUp, + /* .getSize = */ plugViewGetSize, + /* .onSize = */ plugViewOnSize, + /* .onFocus = */ plugViewOnFocus, + /* .setFrame = */ plugViewSetFrame, + /* .canResize = */ plugViewCanResize, + /* .checkSizeConstraint = */ plugViewCheckSizeConstraint }; #endif @@ -1455,7 +1455,7 @@ static Steinberg_tresult controllerInitialize(void* thisInterface, struct Steinb #endif #if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 for (int i = DATA_PRODUCT_PARAMETERS_N; i < DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N; i += 3) { - c->parameters[i] = 0.0; + c->parameters[i ] = 0.0; c->parameters[i + 1] = 0.5; c->parameters[i + 2] = 0.0; } @@ -1739,28 +1739,28 @@ static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Ste static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController = { /* FUnknown */ - /* .queryInterface = */ controllerIEditControllerQueryInterface, - /* .addRef = */ controllerIEditControllerAddRef, - /* .release = */ controllerIEditControllerRelease, + /* .queryInterface = */ controllerIEditControllerQueryInterface, + /* .addRef = */ controllerIEditControllerAddRef, + /* .release = */ controllerIEditControllerRelease, /* IPluginBase */ - /* .initialize = */ controllerInitialize, - /* .terminate = */ controllerTerminate, + /* .initialize = */ controllerInitialize, + /* .terminate = */ controllerTerminate, /* IEditController */ - /* .setComponentState = */ controllerSetComponentState, - /* .setState = */ controllerSetState, - /* .getState = */ controllerGetState, - /* .getParameterCount = */ controllerGetParameterCount, - /* .getParameterInfo = */ controllerGetParameterInfo, - /* .getParamStringByValue = */ controllerGetParamStringByValue, - /* .getParamValueByString = */ controllerGetParamValueByString, - /* .normalizedParamToPlain = */ controllerNormalizedParamToPlain, - /* .plainParamToNormalized = */ controllerPlainParamToNormalized, - /* .getParamNormalized = */ controllerGetParamNormalized, - /* .setParamNormalized = */ controllerSetParamNormalized, - /* .setComponentHandler = */ controllerSetComponentHandler, - /* .createView = */ controllerCreateView + /* .setComponentState = */ controllerSetComponentState, + /* .setState = */ controllerSetState, + /* .getState = */ controllerGetState, + /* .getParameterCount = */ controllerGetParameterCount, + /* .getParameterInfo = */ controllerGetParameterInfo, + /* .getParamStringByValue = */ controllerGetParamStringByValue, + /* .getParamValueByString = */ controllerGetParamValueByString, + /* .normalizedParamToPlain = */ controllerNormalizedParamToPlain, + /* .plainParamToNormalized = */ controllerPlainParamToNormalized, + /* .getParamNormalized = */ controllerGetParamNormalized, + /* .setParamNormalized = */ controllerSetParamNormalized, + /* .setComponentHandler = */ controllerSetComponentHandler, + /* .createView = */ controllerCreateView }; static Steinberg_tresult controllerIMidiMappingQueryInterface(void* thisInterface, const Steinberg_TUID iid, void** obj) { @@ -1806,12 +1806,12 @@ static Steinberg_tresult controllerGetMidiControllerAssignment(void* thisInterfa static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping = { /* FUnknown */ - /* .queryInterface = */ controllerIMidiMappingQueryInterface, - /* .addRef = */ controllerIMidiMappingAddRef, - /* .release = */ controllerIMidiMappingRelease, + /* .queryInterface = */ controllerIMidiMappingQueryInterface, + /* .addRef = */ controllerIMidiMappingAddRef, + /* .release = */ controllerIMidiMappingRelease, /* IMidiMapping */ - /* .getMidiControllerAssignment = */ controllerGetMidiControllerAssignment + /* .getMidiControllerAssignment = */ controllerGetMidiControllerAssignment }; #ifdef DATA_UI @@ -1853,14 +1853,14 @@ static Steinberg_tresult controllerIConnectionPointNotify(void* thisInterface, s static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint = { /* FUnknown */ - /* .queryInterface = */ controllerIConnectionPointQueryInterface, - /* .addRef = */ controllerIConnectionPointAddRef, - /* .release = */ controllerIConnectionPointRelease, + /* .queryInterface = */ controllerIConnectionPointQueryInterface, + /* .addRef = */ controllerIConnectionPointAddRef, + /* .release = */ controllerIConnectionPointRelease, /* IConnectionPoint */ - /* .connect = */ controllerIConnectionPointConnect, - /* .disconnect = */ controllerIConnectionPointDisconnect, - /* .notify = */ controllerIConnectionPointNotify + /* .connect = */ controllerIConnectionPointConnect, + /* .disconnect = */ controllerIConnectionPointDisconnect, + /* .notify = */ controllerIConnectionPointNotify }; # endif #endif @@ -2085,22 +2085,22 @@ static Steinberg_tresult factorySetHostContext(void* thisInterface, struct Stein static Steinberg_IPluginFactory3Vtbl factoryVtbl = { /* FUnknown */ - /* .queryInterface = */ factoryQueryInterface, - /* .addRef = */ factoryAddRef, - /* .release = */ factoryRelease, + /* .queryInterface = */ factoryQueryInterface, + /* .addRef = */ factoryAddRef, + /* .release = */ factoryRelease, /* IPluginFactory */ - /* .getFactoryInfo = */ factoryGetFactoryInfo, - /* .countClasses = */ factoryCountClasses, - /* .getClassInfo = */ factoryGetClassInfo, - /* .createInstance = */ factoryCreateInstance, + /* .getFactoryInfo = */ factoryGetFactoryInfo, + /* .countClasses = */ factoryCountClasses, + /* .getClassInfo = */ factoryGetClassInfo, + /* .createInstance = */ factoryCreateInstance, /* IPluginFactory2 */ - /* .getClassInfo2 = */ factoryGetClassInfo2, + /* .getClassInfo2 = */ factoryGetClassInfo2, /* IPluginFactory3 */ - /* .getClassInfoUnicode = */ factoryGetClassInfoUnicode, - /* .setHostContext = */ factorySetHostContext + /* .getClassInfoUnicode = */ factoryGetClassInfoUnicode, + /* .setHostContext = */ factorySetHostContext }; static Steinberg_IPluginFactory3 factory = { &factoryVtbl }; From 5d07c39170b89ab3d9cdb867bc532c83f2e8453f Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Thu, 4 Jul 2024 10:02:20 +0200 Subject: [PATCH 06/18] vst3 cpu meter --- templates/vst3/src/data.h | 4 ++++ templates/vst3/src/vst3.c | 29 ++++++++++++++++++++++++++++- test/run.sh | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/templates/vst3/src/data.h b/templates/vst3/src/data.h index 4841551..14ef826 100644 --- a/templates/vst3/src/data.h +++ b/templates/vst3/src/data.h @@ -211,6 +211,10 @@ static struct { {{~}} }; +{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}} +# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}} +{{?}} + # endif #endif diff --git a/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index 3bda8da..54473b1 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -64,6 +64,10 @@ typedef struct { #include #endif +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif + // COM in C doc: // https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C // https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733 @@ -222,6 +226,9 @@ typedef struct pluginInstance { char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N]; #endif void *mem; +#ifdef PARAM_OUT_CPU_INDEX + float cpu_meter; +#endif } pluginInstance; static Steinberg_Vst_IComponentVtbl pluginVtblIComponent; @@ -320,6 +327,9 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_ p->midiOutputsActive[i] = 0; #endif p->mem = NULL; +#ifdef PARAM_OUT_CPU_INDEX + p->cpu_meter = 0.f; +#endif return Steinberg_kResultOk; } @@ -738,6 +748,10 @@ static void processParams(pluginInstance *p, struct Steinberg_Vst_ProcessData *d static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst_ProcessData* data) { TRACE("plugin IAudioProcessor process\n"); +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeStart = fatica_time_process(); +#endif + #if defined(__aarch64__) uint64_t fpcr; __asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr)); @@ -813,7 +827,13 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst for (Steinberg_int32 i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) { if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly)) continue; - float v = plugin_get_parameter(&p->p, parameterData[i].index); + float v; +# ifdef PARAM_OUT_CPU_INDEX + if (i == PARAM_OUT_CPU_INDEX) + v = p->cpu_meter; + else +# endif + v = plugin_get_parameter(&p->p, parameterData[i].index); if (v == p->parameters[i]) continue; p->parameters[i] = v; @@ -837,6 +857,13 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); #endif +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + p->cpu_meter = p->cpu_meter * 0.9f + ((float) (processTimeS * p->sampleRate)) * 0.1f; +#endif + return Steinberg_kResultOk; } diff --git a/test/run.sh b/test/run.sh index dda595b..f949268 100755 --- a/test/run.sh +++ b/test/run.sh @@ -3,6 +3,7 @@ dir=`dirname $0` $dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3 $dir/../out/vst3 $dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json,$dir/vst3-make.json $dir/../templates/vst3-make $dir/../out/vst3 +cp $dir/../templates/common/* $dir/../out/vst3/src/ cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src $dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2 From 0babfc9b5df984936012117c581f6c188f921a73 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Thu, 4 Jul 2024 10:09:38 +0200 Subject: [PATCH 07/18] indentation/alignment --- templates/web/src/data.h | 16 ++++++++-------- templates/web/src/processor.c | 32 ++++++++++++++++---------------- templates/web/src/processor.js | 10 +++++----- templates/web/src/walloc.c | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/templates/web/src/data.h b/templates/web/src/data.h index d97fd2d..04abc02 100644 --- a/templates/web/src/data.h +++ b/templates/web/src/data.h @@ -18,17 +18,17 @@ * File author: Stefano D'Angelo */ -#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}} -#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}} -#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} -#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}} -#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.length}} -#define DATA_PRODUCT_PARAMETERS_OUTPUT_N {{=it.product.parameters.filter(x => x.direction == "output").length}} +#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}} +#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}} +#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} +#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}} +#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.length}} +#define DATA_PRODUCT_PARAMETERS_OUTPUT_N {{=it.product.parameters.filter(x => x.direction == "output").length}} #if DATA_PRODUCT_PARAMETERS_N > 0 static struct { - char out; - float def; + char out; + float def; } param_data[DATA_PRODUCT_PARAMETERS_N] = { {{~it.product.parameters :p}} { diff --git a/templates/web/src/processor.c b/templates/web/src/processor.c index e658695..645177e 100644 --- a/templates/web/src/processor.c +++ b/templates/web/src/processor.c @@ -22,10 +22,10 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; #include "data.h" @@ -35,19 +35,19 @@ typedef struct { #include "walloc.h" typedef struct { - plugin p; - void * mem; + plugin p; + void *mem; #if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0 - float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128]; - const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N]; - float zero_buf[128]; + float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128]; + const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N]; + float zero_buf[128]; #endif #if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0 - float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128]; - float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N]; + float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128]; + float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N]; #endif #if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0 - float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N]; + float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N]; #endif } instance; @@ -57,10 +57,10 @@ instance * processor_new(float sample_rate) { return NULL; plugin_callbacks cbs = { - /* .handle = */ NULL, - /* .format = */ "web", - /* .get_bindir = */ NULL, - /* .get_datadir = */ NULL + /* .handle = */ NULL, + /* .format = */ "web", + /* .get_bindir = */ NULL, + /* .get_datadir = */ NULL }; plugin_init(&i->p, &cbs); diff --git a/templates/web/src/processor.js b/templates/web/src/processor.js index efd1eae..ad198d8 100644 --- a/templates/web/src/processor.js +++ b/templates/web/src/processor.js @@ -18,14 +18,14 @@ * File author: Stefano D'Angelo */ -var buses = {{=JSON.stringify(it.product.buses, null, 2)}}; +var buses = {{=JSON.stringify(it.product.buses, null, 2)}}; var parameters = {{=JSON.stringify(it.product.parameters, null, 2)}}; -var busesIn = buses.filter(x => x.type == "audio" && x.direction == "input"); -var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output"); +var busesIn = buses.filter(x => x.type == "audio" && x.direction == "input"); +var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output"); -var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); -var nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); +var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); +var nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); class Processor extends AudioWorkletProcessor { constructor(options) { diff --git a/templates/web/src/walloc.c b/templates/web/src/walloc.c index da5731f..9b0fe3b 100644 --- a/templates/web/src/walloc.c +++ b/templates/web/src/walloc.c @@ -28,7 +28,7 @@ extern unsigned char __heap_base; typedef struct _header { struct _header *next; struct _header *prev; - char free; + char free; } header; static char inited = 0; From 992eebc8a28aafa7ed79a8d17580e35a8ea8e440 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Thu, 4 Jul 2024 10:58:35 +0200 Subject: [PATCH 08/18] web cpumeter. Not tested --- templates/web/src/processor.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/templates/web/src/processor.js b/templates/web/src/processor.js index ad198d8..d9b2778 100644 --- a/templates/web/src/processor.js +++ b/templates/web/src/processor.js @@ -27,6 +27,9 @@ var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output") var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); var nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0); +var cpu_meter = 0.0; +var sampleRate = 1.0; + class Processor extends AudioWorkletProcessor { constructor(options) { super(); @@ -71,6 +74,8 @@ class Processor extends AudioWorkletProcessor { } process(inputs, outputs, params) { + const processTimeStart = performance.now(); + for (var i = 0; i < this.parametersIn.length; i++) { var index = this.parametersIn[i].index; var parameter = parameters[index]; @@ -141,7 +146,11 @@ class Processor extends AudioWorkletProcessor { for (var i = 0; i < this.parametersOut.length; i++) { var index = this.parametersOut[i].index; - var value = this.parametersOutValues[i]; + var value; + if (parameters[index].isCpumeter) + value = cpu_meter; + else + value = this.parametersOutValues[i]; if (value != this.parametersOut[i].value) { this.paramOutChangeMsg.index = index; this.paramOutChangeMsg.value = value; @@ -149,6 +158,10 @@ class Processor extends AudioWorkletProcessor { this.parametersOut[i].value = value; } } + const processTimeEnd = performance.now(); + const processTimeMs = processTimeEnd - processTimeStart; + const processTimeS = processTimeMs * 0.001; + cpu_meter = cpu_meter * 0.9 + (processTimeS * sampleRate) * 0.1; return true; // because Chrome sucks: https://bugs.chromium.org/p/chromium/issues/detail?id=921354 } From 4d0ab165b3d89a3e4496b86e7fd7853613a9dd68 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Thu, 4 Jul 2024 11:21:41 +0200 Subject: [PATCH 09/18] proper spacing alignment --- templates/android-make/vars.mk | 54 +++++++++++++++---------------- templates/cmd-make/vars.mk | 22 ++++++------- templates/daisy-seed-make/vars.mk | 18 +++++------ templates/ios-make/vars.mk | 14 ++++---- templates/lv2-make/vars.mk | 16 ++++----- templates/vst3-make/vars.mk | 18 +++++------ templates/web-make/vars.mk | 18 +++++------ 7 files changed, 80 insertions(+), 80 deletions(-) diff --git a/templates/android-make/vars.mk b/templates/android-make/vars.mk index 7a4a7e6..0d9f33e 100644 --- a/templates/android-make/vars.mk +++ b/templates/android-make/vars.mk @@ -18,38 +18,38 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} -JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}} +BUNDLE_NAME := {{=it.product.bundleName}} +JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.android_make?.cflags ?? ""}} -CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.android_make?.cxxflags ?? ""}} -JFLAGS_EXTRA := {{=it.make?.jflags ?? ""}} {{=it.android_make?.jflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.android_make?.ldflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.android_make?.cflags ?? ""}} +CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.android_make?.cxxflags ?? ""}} +JFLAGS_EXTRA := {{=it.make?.jflags ?? ""}} {{=it.android_make?.jflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.android_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.android_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.android_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.android_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.android_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} -KEY_STORE := {{=it.android_make.keyStore}} -KEY_ALIAS := {{=it.android_make.keyAlias}} -STORE_PASS := {{=it.android_make.storePass}} -KEY_PASS := {{=it.android_make.keyPass}} +KEY_STORE := {{=it.android_make.keyStore}} +KEY_ALIAS := {{=it.android_make.keyAlias}} +STORE_PASS := {{=it.android_make.storePass}} +KEY_PASS := {{=it.android_make.keyPass}} -ANDROID_SDK_DIR := {{=it.android_make.sdkDir}} -ANDROID_NDK_DIR := ${ANDROID_SDK_DIR}/ndk/{{=it.android_make.ndkVersion}} -BUILD_TOOLS_DIR := ${ANDROID_SDK_DIR}/build-tools/{{=it.android_make.buildToolsVersion}} -ANDROIDX_DIR := {{=it.android_make.androidxDir}} -KOTLIN_DIR := {{=it.android_make.kotlinDir}} +ANDROID_SDK_DIR := {{=it.android_make.sdkDir}} +ANDROID_NDK_DIR := ${ANDROID_SDK_DIR}/ndk/{{=it.android_make.ndkVersion}} +BUILD_TOOLS_DIR := ${ANDROID_SDK_DIR}/build-tools/{{=it.android_make.buildToolsVersion}} +ANDROIDX_DIR := {{=it.android_make.androidxDir}} +KOTLIN_DIR := {{=it.android_make.kotlinDir}} -ANDROID_JAR_FILE := ${ANDROID_SDK_DIR}/platforms/android-{{=it.android_make.androidVersion}}/android.jar -ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-{{=it.android_make.androidxCoreVersion}}.jar -ANDROIDX_LIFECYCLE_COMMON_FILE := ${ANDROIDX_DIR}/lifecycle-common-{{=it.android_make.androidxLifecycleCommonVersion}}.jar +ANDROID_JAR_FILE := ${ANDROID_SDK_DIR}/platforms/android-{{=it.android_make.androidVersion}}/android.jar +ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-{{=it.android_make.androidxCoreVersion}}.jar +ANDROIDX_LIFECYCLE_COMMON_FILE := ${ANDROIDX_DIR}/lifecycle-common-{{=it.android_make.androidxLifecycleCommonVersion}}.jar ANDROIDX_VERSIONEDPARCELABLE_FILE := ${ANDROIDX_DIR}/versionedparcelable-{{=it.android_make.androidxVersionedparcelableVersion}}.jar -KOTLIN_STDLIB_FILE := ${KOTLIN_DIR}/kotlin-stdlib-{{=it.android_make.kotlinStdlibVersion}}.jar -KOTLINX_COROUTINES_CORE_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-{{=it.android_make.kotlinxCoroutinesCoreVersion}}.jar -KOTLINX_COROUTINES_CORE_JVM_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-jvm-{{=it.android_make.kotlinxCoroutinesCoreJVMVersion}}.jar +KOTLIN_STDLIB_FILE := ${KOTLIN_DIR}/kotlin-stdlib-{{=it.android_make.kotlinStdlibVersion}}.jar +KOTLINX_COROUTINES_CORE_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-{{=it.android_make.kotlinxCoroutinesCoreVersion}}.jar +KOTLINX_COROUTINES_CORE_JVM_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-jvm-{{=it.android_make.kotlinxCoroutinesCoreJVMVersion}}.jar -HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} +HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} diff --git a/templates/cmd-make/vars.mk b/templates/cmd-make/vars.mk index 03dd33d..4596e22 100644 --- a/templates/cmd-make/vars.mk +++ b/templates/cmd-make/vars.mk @@ -18,20 +18,20 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.cmd_make?.cflags ?? ""}} -CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.cmd_make?.cxxflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.cmd_make?.ldflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.cmd_make?.cflags ?? ""}} +CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.cmd_make?.cxxflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.cmd_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} -TINYWAV_DIR := {{=it.cmd_make.tinywavDir}} +TINYWAV_DIR := {{=it.cmd_make.tinywavDir}} MIDI_PARSER_DIR := {{=it.cmd_make.midiParserDir}} -HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} +HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} diff --git a/templates/daisy-seed-make/vars.mk b/templates/daisy-seed-make/vars.mk index 337404e..0685473 100644 --- a/templates/daisy-seed-make/vars.mk +++ b/templates/daisy-seed-make/vars.mk @@ -18,17 +18,17 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.daisy_seed_make?.cflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.daisy_seed_make?.cflags ?? ""}} CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.daisy_seed_make?.cxxflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.daisy_seed_make?.ldflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.daisy_seed_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.daisy_seed_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.daisy_seed_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.daisy_seed_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.daisy_seed_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} -LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}} +LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}} diff --git a/templates/ios-make/vars.mk b/templates/ios-make/vars.mk index 78fd5d0..252d223 100644 --- a/templates/ios-make/vars.mk +++ b/templates/ios-make/vars.mk @@ -18,12 +18,12 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}} -SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}} +SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}} -COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} diff --git a/templates/lv2-make/vars.mk b/templates/lv2-make/vars.mk index ef0e151..330f797 100644 --- a/templates/lv2-make/vars.mk +++ b/templates/lv2-make/vars.mk @@ -18,15 +18,15 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.lv2_make?.cflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.lv2_make?.cflags ?? ""}} CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.lv2_make?.cxxflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.lv2_make?.ldflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.lv2_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.lv2_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.lv2_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.lv2_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.lv2_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} diff --git a/templates/vst3-make/vars.mk b/templates/vst3-make/vars.mk index ccd6526..4e49bba 100644 --- a/templates/vst3-make/vars.mk +++ b/templates/vst3-make/vars.mk @@ -18,17 +18,17 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.vst3_make?.cflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.vst3_make?.cflags ?? ""}} CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.vst3_make?.cxxflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.vst3_make?.ldflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.vst3_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.vst3_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.vst3_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.vst3_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.vst3_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} -HAS_UI := {{=it.product.ui ? "yes" : "no"}} +HAS_UI := {{=it.product.ui ? "yes" : "no"}} diff --git a/templates/web-make/vars.mk b/templates/web-make/vars.mk index a80d740..95d701d 100644 --- a/templates/web-make/vars.mk +++ b/templates/web-make/vars.mk @@ -18,17 +18,17 @@ # File author: Stefano D'Angelo # -BUNDLE_NAME := {{=it.product.bundleName}} +BUNDLE_NAME := {{=it.product.bundleName}} -CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.web_make?.cflags ?? ""}} +CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.web_make?.cflags ?? ""}} CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.web_make?.cxxflags ?? ""}} -LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.web_make?.ldflags ?? ""}} +LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.web_make?.ldflags ?? ""}} -C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.web_make?.cSrcs ?? ""}} -CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.web_make?.cxxSrcs ?? ""}} +C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.web_make?.cSrcs ?? ""}} +CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.web_make?.cxxSrcs ?? ""}} -COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}} -DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}} -PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} +COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}} +DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}} +PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}} -HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} +HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} From acf92dd51d3dba085afab83ad6981869d805555a Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Fri, 5 Jul 2024 16:08:07 +0200 Subject: [PATCH 10/18] unit fix --- test/product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/product.json b/test/product.json index 167c89b..4cd3e3b 100644 --- a/test/product.json +++ b/test/product.json @@ -148,7 +148,7 @@ "optional": false, "integer": false, "list": false, - "unit": "%", + "unit": "", "map": "linear" } ], From f366841c2c96a55fb3bc564df705fad0adfd6832 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Fri, 5 Jul 2024 16:18:17 +0200 Subject: [PATCH 11/18] minor fixing --- templates/ios/src/app.swift | 12 +- templates/ios/src/index.html | 226 ++++++++++++++++++----------------- templates/ios/src/native.mm | 28 ++--- 3 files changed, 134 insertions(+), 132 deletions(-) diff --git a/templates/ios/src/app.swift b/templates/ios/src/app.swift index d92db0c..706f8d5 100644 --- a/templates/ios/src/app.swift +++ b/templates/ios/src/app.swift @@ -97,12 +97,12 @@ struct templateApp: App { var body: some Scene { WindowGroup { ContentView() - .onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in - audioPause() - } - .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in - audioResume() - } + .onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in + audioPause() + } + .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in + audioResume() + } } } } diff --git a/templates/ios/src/index.html b/templates/ios/src/index.html index ce7e217..e7b0655 100644 --- a/templates/ios/src/index.html +++ b/templates/ios/src/index.html @@ -21,14 +21,15 @@ --> - - - {{=it.product.name}} - - - - - -
- + .range { + width: 90%; + } + + + + +
+ diff --git a/templates/ios/src/native.mm b/templates/ios/src/native.mm index 00ed24d..fe4bb1e 100644 --- a/templates/ios/src/native.mm +++ b/templates/ios/src/native.mm @@ -109,16 +109,16 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, if (mutex.try_lock()) { # if PARAMETERS_N > 0 for (size_t i = 0; i < PARAMETERS_N; i++) { - if (param_data[i].out) { + if (param_data[i].out) { # ifdef PARAM_OUT_CPU_INDEX - if (i == PARAM_OUT_CPU_INDEX) { - param_values_prev[i] = param_values[i] = cpu_meter; - continue; - } + if (i == PARAM_OUT_CPU_INDEX) { + param_values_prev[i] = param_values[i] = cpu_meter; + continue; + } # endif - param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); - } - else if (param_values_prev[i] != param_values[i]) { + param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); + } + else if (param_values_prev[i] != param_values[i]) { plugin_set_parameter(&instance, i, param_values[i]); param_values_prev[i] = param_values[i]; } @@ -178,10 +178,10 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, #endif #ifdef PARAM_OUT_CPU_INDEX - const unsigned long long processTimeEnd = fatica_time_process(); - const unsigned long long processTime100n = processTimeEnd - processTimeStart; - const double processTimeS = ((double) processTime100n) * 1.0e-7; - cpu_meter = cpu_meter * 0.9f + ((float) (processTimeS * sample_rate)) * 0.1f; + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + cpu_meter = cpu_meter * 0.9f + ((float) (processTimeS * sample_rate)) * 0.1f; #endif } @@ -301,8 +301,8 @@ char audioStart() { #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); - sample_rate = (float)device.sampleRate; - + sample_rate = (float)device.sampleRate; + size_t req = plugin_mem_req(&instance); if (req != 0) { mem = malloc(req); From 1565eaabf386fbbb0226d900bd89f9c99b7ae4fb Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Mon, 8 Jul 2024 15:22:14 +0200 Subject: [PATCH 12/18] fixes --- templates/ios-make/Makefile | 2 +- templates/ios-make/project.yml | 44 ++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/templates/ios-make/Makefile b/templates/ios-make/Makefile index 855f8c2..610d122 100644 --- a/templates/ios-make/Makefile +++ b/templates/ios-make/Makefile @@ -21,7 +21,7 @@ include vars.mk COMMON_DIR := $(or $(COMMON_DIR),.) -DATA_DIR := $(or $(DATA_DIR),.) +DATA_DIR := $(or $(DATA_DIR),.) PLUGIN_DIR := $(or $(PLUGIN_DIR),src) SOURCES := \ diff --git a/templates/ios-make/project.yml b/templates/ios-make/project.yml index 707bb85..d4639ac 100644 --- a/templates/ios-make/project.yml +++ b/templates/ios-make/project.yml @@ -20,39 +20,41 @@ name: {{=it.product.bundleName}} targets: - {{=it.product.bundleName}}: + {{=it.product.bundleName}}: {{?it.ios_make.supportedDestinations}} - supportedDestinations: {{=Array.isArray(it.ios_make.supportedDestinations) ? "[" + it.ios_make.supportedDestinations.toString() + "]" : it.ios_make.supportedDestinations}} + supportedDestinations: {{=Array.isArray(it.ios_make.supportedDestinations) ? "[" + it.ios_make.supportedDestinations.toString() + "]" : it.ios_make.supportedDestinations}} {{??}} - platform: [iOS] + platform: [iOS] {{?}} - deploymentTarget: "{{=it.ios_make.deploymentTarget}}" - type: application - sources: - - path: src - settings: - base: - PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}} - SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h + deploymentTarget: "{{=it.ios_make.deploymentTarget}}" + type: application + sources: + - path: src + dependencies: + + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}} + SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h {{?it.ios_make.headerSearchPaths}} - HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}} - - {{=p}}{{~}} + HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}} + - {{=p}}{{~}} {{?}} - info: - path: Info.plist + info: + path: Info.plist {{?(it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0) || it.ios_make.infoProperties || it.ios_make.uiLaunchScreen}} - properties: + properties: {{?it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0}} - NSMicrophoneUsageDescription: Need audio input for processing sound + NSMicrophoneUsageDescription: Need audio input for processing sound {{?}} {{?it.ios_make.infoProperties}} {{~it.ios_make.infoProperties :p}} - {{=p.key}}: {{=Array.isArray(p.value) ? "[" + p.value.toString() + "]" : p.value}} + {{=p.key}}: {{=Array.isArray(p.value) ? "[" + p.value.toString() + "]" : p.value}} {{~}} {{?}} {{?it.ios_make.launchScreen}} - UILaunchScreen: - UIColorName: {{=it.ios_make.launchScreen.colorName}} - UIImageName: {{=it.ios_make.launchScreen.imageName}} + UILaunchScreen: + UIColorName: {{=it.ios_make.launchScreen.colorName}} + UIImageName: {{=it.ios_make.launchScreen.imageName}} {{?}} {{?}} From 25f7d76d3fba0eab6285de841d0d4453a263c48a Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Mon, 8 Jul 2024 17:37:58 +0200 Subject: [PATCH 13/18] yaml proper indentation --- templates/ios-make/project.yml | 48 ++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/templates/ios-make/project.yml b/templates/ios-make/project.yml index d4639ac..fc7211a 100644 --- a/templates/ios-make/project.yml +++ b/templates/ios-make/project.yml @@ -20,41 +20,43 @@ name: {{=it.product.bundleName}} targets: - {{=it.product.bundleName}}: + {{=it.product.bundleName}}: {{?it.ios_make.supportedDestinations}} - supportedDestinations: {{=Array.isArray(it.ios_make.supportedDestinations) ? "[" + it.ios_make.supportedDestinations.toString() + "]" : it.ios_make.supportedDestinations}} + supportedDestinations: {{=Array.isArray(it.ios_make.supportedDestinations) ? "[" + it.ios_make.supportedDestinations.toString() + "]" : it.ios_make.supportedDestinations}} {{??}} - platform: [iOS] + platform: [iOS] {{?}} - deploymentTarget: "{{=it.ios_make.deploymentTarget}}" - type: application - sources: - - path: src - dependencies: - - settings: - base: - PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}} - SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h + deploymentTarget: "{{=it.ios_make.deploymentTarget}}" + type: application + sources: + - path: src +{{?it.ios_make.dependencies}} + dependencies: {{~it.ios_make.dependencies :d}} + - target: {{=d}}{{~}} +{{?}} + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}} + SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h {{?it.ios_make.headerSearchPaths}} - HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}} - - {{=p}}{{~}} + HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}} + - {{=p}}{{~}} {{?}} - info: - path: Info.plist + info: + path: Info.plist {{?(it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0) || it.ios_make.infoProperties || it.ios_make.uiLaunchScreen}} - properties: + properties: {{?it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0}} - NSMicrophoneUsageDescription: Need audio input for processing sound + NSMicrophoneUsageDescription: Need audio input for processing sound {{?}} {{?it.ios_make.infoProperties}} {{~it.ios_make.infoProperties :p}} - {{=p.key}}: {{=Array.isArray(p.value) ? "[" + p.value.toString() + "]" : p.value}} + {{=p.key}}: {{=Array.isArray(p.value) ? "[" + p.value.toString() + "]" : p.value}} {{~}} {{?}} {{?it.ios_make.launchScreen}} - UILaunchScreen: - UIColorName: {{=it.ios_make.launchScreen.colorName}} - UIImageName: {{=it.ios_make.launchScreen.imageName}} + UILaunchScreen: + UIColorName: {{=it.ios_make.launchScreen.colorName}} + UIImageName: {{=it.ios_make.launchScreen.imageName}} {{?}} {{?}} From 6fa2728e766df8741c26a7481e398b398054e7e0 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 11:44:56 +0200 Subject: [PATCH 14/18] tested with latest android framework --- test/android-make.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/android-make.json b/test/android-make.json index 49661ec..6c35e5c 100644 --- a/test/android-make.json +++ b/test/android-make.json @@ -6,16 +6,16 @@ "storePass": "android", "keyPass": "android", "sdkDir": "${HOME}/Android/Sdk", - "ndkVersion": "25.2.9519653", - "buildToolsVersion": "34.0.0", + "ndkVersion": "27.0.11902837", + "buildToolsVersion": "35.0.0", "androidxDir": "${HOME}/Android/androidx", "kotlinDir": "${HOME}/Android/kotlin", - "androidVersion": "34", - "androidxCoreVersion": "1.10.1", - "androidxLifecycleCommonVersion": "2.6.1", - "androidxVersionedparcelableVersion": "1.1.1", - "kotlinStdlibVersion": "1.9.0", - "kotlinxCoroutinesCoreVersion": "1.7.3", - "kotlinxCoroutinesCoreJVMVersion": "1.7.3" + "androidVersion": "35", + "androidxCoreVersion": "1.13.1", + "androidxLifecycleCommonVersion": "2.8.3", + "androidxVersionedparcelableVersion": "1.2.0", + "kotlinStdlibVersion": "2.0.0", + "kotlinxCoroutinesCoreVersion": "1.8.0", + "kotlinxCoroutinesCoreJVMVersion": "1.8.1" } } From 5ef05ef959be4d6c03a28339620fb8d431792e0d Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 12:20:18 +0200 Subject: [PATCH 15/18] ifdef fix --- templates/ios/src/native.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/ios/src/native.mm b/templates/ios/src/native.mm index fe4bb1e..086999c 100644 --- a/templates/ios/src/native.mm +++ b/templates/ios/src/native.mm @@ -96,7 +96,7 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, (void)pDevice; #ifdef PARAM_OUT_CPU_INDEX - const unsigned long long processTimeStart = fatica_time_process(); + const unsigned long long processTimeStart = fatica_time_process(); #endif #if defined(__aarch64__) @@ -301,7 +301,9 @@ char audioStart() { #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); +#ifdef PARAM_OUT_CPU_INDEX sample_rate = (float)device.sampleRate; +#endif size_t req = plugin_mem_req(&instance); if (req != 0) { From 619ff345a3fb795d8b867d2e3ba6c1cb494bcb5d Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 12:20:57 +0200 Subject: [PATCH 16/18] generate error when platform is not supported --- templates/common/fatica.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/templates/common/fatica.h b/templates/common/fatica.h index e0914e5..1e69165 100644 --- a/templates/common/fatica.h +++ b/templates/common/fatica.h @@ -10,7 +10,7 @@ unsigned long long fatica_time_process(void); #if defined(_WIN32) || defined(__CYGWIN__) -#include +# include static ULONGLONG filetime_to_ull(const FILETIME* ft) { return (((ULONGLONG)ft->dwHighDateTime) << 32) + ft->dwLowDateTime; @@ -28,13 +28,13 @@ unsigned long long fatica_time_process(void) { #elif defined(__linux__) -#if __STDC_VERSION__ >= 199901L -# define _XOPEN_SOURCE 600 -#else -# define _XOPEN_SOURCE 500 -#endif -#include -#include +# if __STDC_VERSION__ >= 199901L +# define _XOPEN_SOURCE 600 +# else +# define _XOPEN_SOURCE 500 +# endif +# include +# include unsigned long long fatica_time_process(void) { struct timespec ts; @@ -45,9 +45,9 @@ unsigned long long fatica_time_process(void) { #elif defined(__APPLE__) -#include -#include -#include +# include +# include +# include unsigned long long fatica_time_process(void) { thread_t thread = mach_thread_self(); @@ -59,5 +59,7 @@ unsigned long long fatica_time_process(void) { + (info.user_time.microseconds + info.system_time.microseconds) / 1000; } +#else +# error "System not supported" #endif #endif // FATICA_H From c39b5ed9930588a17dd4eb5eb3e2046c13aba083 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 12:21:11 +0200 Subject: [PATCH 17/18] cpumeter android --- templates/android/src/data.h | 55 +++++++++------- templates/android/src/jni.cpp | 121 +++++++++++++++++++++------------- test/run.sh | 1 + 3 files changed, 106 insertions(+), 71 deletions(-) diff --git a/templates/android/src/data.h b/templates/android/src/data.h index 4c99f3a..bc7ab8c 100644 --- a/templates/android/src/data.h +++ b/templates/android/src/data.h @@ -18,37 +18,37 @@ * File author: Stefano D'Angelo */ -#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} -#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} +#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} +#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} -#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} -#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} -#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input") .reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} +#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} -#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} +#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} #if NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT > 0 static struct { - size_t index; - char out; - char optional; - char channels; + size_t index; + char out; + char optional; + char channels; } audio_bus_data[NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT] = { {{~it.product.buses :b:i}} {{?b.type == "audio"}} { - /* .index = */ {{=i}}, - /* .out = */ {{=b.direction == "output" ? 1 : 0}}, - /* .optional = */ {{=b.optional ? 1 : 0}}, - /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} + /* .index = */ {{=i}}, + /* .out = */ {{=b.direction == "output" ? 1 : 0}}, + /* .optional = */ {{=b.optional ? 1 : 0}}, + /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} }, {{?}} {{~}} @@ -72,14 +72,19 @@ static struct { } param_data[PARAMETERS_N] = { {{~it.product.parameters :p}} { - /* .out = */ {{=p.direction == "output" ? 1 : 0}}, - /* .def = */ {{=p.defaultValue.toExponential()}}, - /* .min = */ {{=p.minimum.toExponential()}}f, - /* .max = */ {{=p.maximum.toExponential()}}f, - /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} + /* .out = */ {{=p.direction == "output" ? 1 : 0}}, + /* .def = */ {{=p.defaultValue.toExponential()}}, + /* .min = */ {{=p.minimum.toExponential()}}f, + /* .max = */ {{=p.maximum.toExponential()}}f, + /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} }, {{~}} }; + +{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}} +# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}} +{{?}} + #endif #define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x diff --git a/templates/android/src/jni.cpp b/templates/android/src/jni.cpp index f935597..b062f7d 100644 --- a/templates/android/src/jni.cpp +++ b/templates/android/src/jni.cpp @@ -22,10 +22,10 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; #include "data.h" @@ -52,60 +52,71 @@ typedef struct { #if NUM_MIDI_INPUTS > 0 # include - # include #endif +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif + #if defined(__i386__) || defined(__x86_64__) #include #include #endif -static ma_device device; -static plugin instance; -static void * mem; +static ma_device device; +static plugin instance; +static void *mem; #if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN -float zero[BLOCK_SIZE]; +float zero[BLOCK_SIZE]; #endif #if NUM_CHANNELS_IN > 0 -float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; -float * x_in[NUM_CHANNELS_IN]; +float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; +float *x_in[NUM_CHANNELS_IN]; #endif #if NUM_ALL_CHANNELS_IN > 0 -const float * x[NUM_ALL_CHANNELS_IN]; +const float *x[NUM_ALL_CHANNELS_IN]; #else -const float ** x; +const float **x; #endif #if NUM_NON_OPT_CHANNELS_OUT > 0 -float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; +float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; #endif #if NUM_CHANNELS_OUT > 0 -float * y_out[NUM_CHANNELS_OUT]; +float *y_out[NUM_CHANNELS_OUT]; #endif #if NUM_ALL_CHANNELS_OUT > 0 -float * y[NUM_ALL_CHANNELS_OUT]; +float *y[NUM_ALL_CHANNELS_OUT]; #else -float ** y; +float **y; #endif #if PARAMETERS_N > 0 -std::mutex mutex; -float param_values[PARAMETERS_N]; -float param_values_prev[PARAMETERS_N]; +std::mutex mutex; +float param_values[PARAMETERS_N]; +float param_values_prev[PARAMETERS_N]; #endif #if NUM_MIDI_INPUTS > 0 struct PortData { - AMidiDevice *device; - int portNumber; - AMidiOutputPort *port; + AMidiDevice *device; + int portNumber; + AMidiOutputPort *port; }; std::vector midiPorts; # define MIDI_BUFFER_SIZE 1024 -uint8_t midiBuffer[MIDI_BUFFER_SIZE]; +uint8_t midiBuffer[MIDI_BUFFER_SIZE]; +#endif +#ifdef PARAM_OUT_CPU_INDEX +float cpu_meter = 0.f; +float sample_rate = 1.f; #endif static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { (void)pDevice; +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeStart = fatica_time_process(); +#endif + #if defined(__aarch64__) uint64_t fpcr; __asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr)); @@ -122,8 +133,15 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, if (mutex.try_lock()) { # if PARAMETERS_N > 0 for (size_t i = 0; i < PARAMETERS_N; i++) { - if (param_data[i].out) + if (param_data[i].out) { +# ifdef PARAM_OUT_CPU_INDEX + if (i == PARAM_OUT_CPU_INDEX) { + param_values_prev[i] = param_values[i] = cpu_meter; + continue; + } +# endif param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); + } else if (param_values_prev[i] != param_values[i]) { plugin_set_parameter(&instance, i, param_values[i]); param_values_prev[i] = param_values[i]; @@ -188,6 +206,13 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, _MM_SET_FLUSH_ZERO_MODE(flush_zero_mode); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); #endif + +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + cpu_meter = cpu_meter * 0.9f + ((float) (processTimeS * sample_rate)) * 0.1f; +#endif } extern "C" @@ -208,35 +233,35 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback); #endif - deviceConfig.periodSizeInFrames = BLOCK_SIZE; - deviceConfig.periods = 1; - deviceConfig.performanceProfile = ma_performance_profile_low_latency; - deviceConfig.noPreSilencedOutputBuffer = 1; - deviceConfig.noClip = 0; - deviceConfig.noDisableDenormals = 0; - deviceConfig.noFixedSizedCallback = 1; - deviceConfig.dataCallback = data_callback; - deviceConfig.capture.pDeviceID = NULL; - deviceConfig.capture.format = ma_format_f32; - deviceConfig.capture.channels = NUM_CHANNELS_IN; - deviceConfig.capture.shareMode = ma_share_mode_shared; - deviceConfig.playback.pDeviceID = NULL; - deviceConfig.playback.format = ma_format_f32; + deviceConfig.periodSizeInFrames = BLOCK_SIZE; + deviceConfig.periods = 1; + deviceConfig.performanceProfile = ma_performance_profile_low_latency; + deviceConfig.noPreSilencedOutputBuffer = 1; + deviceConfig.noClip = 0; + deviceConfig.noDisableDenormals = 0; + deviceConfig.noFixedSizedCallback = 1; + deviceConfig.dataCallback = data_callback; + deviceConfig.capture.pDeviceID = NULL; + deviceConfig.capture.format = ma_format_f32; + deviceConfig.capture.channels = NUM_CHANNELS_IN; + deviceConfig.capture.shareMode = ma_share_mode_shared; + deviceConfig.playback.pDeviceID = NULL; + deviceConfig.playback.format = ma_format_f32; #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 - deviceConfig.playback.channels = NUM_CHANNELS_OUT; + deviceConfig.playback.channels = NUM_CHANNELS_OUT; #else - deviceConfig.playback.channels = 1; // Fake & muted + deviceConfig.playback.channels = 1; // Fake & muted #endif - deviceConfig.playback.shareMode = ma_share_mode_shared; + deviceConfig.playback.shareMode = ma_share_mode_shared; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) return false; plugin_callbacks cbs = { - /* .handle = */ NULL, - /* .format = */ "android", - /* .get_bindir = */ NULL, - /* .get_datadir = */ NULL + /* .handle = */ NULL, + /* .format = */ "android", + /* .get_bindir = */ NULL, + /* .get_datadir = */ NULL }; plugin_init(&instance, &cbs); @@ -249,6 +274,10 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); +#ifdef PARAM_OUT_CPU_INDEX + sample_rate = (float)device.sampleRate; +#endif + size_t req = plugin_mem_req(&instance); if (req != 0) { mem = malloc(req); diff --git a/test/run.sh b/test/run.sh index f949268..94bda7e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -18,6 +18,7 @@ cp $dir/plugin.h $dir/../out/web/src $dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android $dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json,$dir/android-make.json $dir/../templates/android-make $dir/../out/android +cp $dir/../templates/common/* $dir/../out/android/src/ cp $dir/keystore.jks $dir/../out/android cp $dir/plugin.h $dir/../out/android/src From e092600b4db471dfeee99cfed910d6cce0d51dca Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 12:43:06 +0200 Subject: [PATCH 18/18] added missing ios notes --- notes | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/notes b/notes index 2a19817..a9b6511 100644 --- a/notes +++ b/notes @@ -4,18 +4,21 @@ company { LV2: manifest.ttl doap:maintainer foaf:name web: not used cmd: not used + ios: not used android: not used url: VST3: PFactoryInfo.url LV2: manifest.ttl doap:maintainer rdfs:seeAlso web: not used cmd: not used + ios: not used android: not used email: VST3: PFactoryInfo.email LV2: manifest.ttl doap:maintainer foaf:mbox web: not used cmd: not used + ios: not used android: not used } @@ -25,24 +28,28 @@ product { LV2: manifest.ttl plugin doap:name web: web-demo and <h1> cmd: not used + ios: index.html <title> android: index.html <title>, AndroidManifest.xml <application> <activity> android:label version: VST3: PClassInfo{2,W}.version (first 3 numbers) LV2: not used web: not used cmd: not used + ios: not used android: not used buildVersion: VST3: PClassInfo{2,W}.version (last number) LV2: not used web: not used cmd: not used + ios: not used android: not used bundleName: VST3: plugin folder name, plugin .dll name, Info.plist LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary web: registerProcessor(), output file names cmd: executable file name + ios: project.yml name/target, vars.mk BUNDLE_NAME android: .so/.apk filenames buses: [ { @@ -52,6 +59,7 @@ product { LV2: manifest.ttl lv2:port lv2:name web: not used cmd: not used + ios: not used android: not used shortName: bus short name string, required @@ -59,6 +67,7 @@ product { LV2: manifest.ttl lv2:port lv2:shortName web: not used cmd: not used + ios: not used android: not used id: bus unique id string, required @@ -66,6 +75,7 @@ product { LV2: manifest.ttl lv2:port lv2:symbol (resulting ports can have _l or _r appended) web: not used cmd: not used + ios: not used android: not used direction: "input" or "output", required @@ -73,6 +83,7 @@ product { LV2: manifest.ttl lv2:port a - lots of implications web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications cmd: lots of places + ios: data.h, index.html android: lots of places type: "audio" or "midi", required @@ -80,6 +91,7 @@ product { LV2: lots of implications everywhere web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications cmd: lots of places + ios: data.h, index.html android: lots of places channels: "mono" or "stereo", audio type only, required @@ -87,6 +99,7 @@ product { LV2: manifest.ttl lv2:port - lots of implications web: AudioWorkletNode.outputChannelCount - lots of implications cmd: lots of places + ios: data.h android: lots of places sidechain: bus is not part of main audio path (sidechain)? boolean, default false @@ -94,6 +107,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty lv2:isSideChain web: web-demo choice of audio I/O buses cmd: choice of audio I/O buses + ios: choice of audio I/O buses android: choice of audio I/O buses cv: bus is control voltage audio-rate? boolean, audio type only, default false @@ -101,6 +115,7 @@ product { LV2: manifest.ttl lv2:port a lv2:CVPort web: web-demo choice of audio I/O buses cmd: choice of audio I/O buses + ios: choice of audio I/O buses android: choice of audio I/O buses control: bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false @@ -108,6 +123,7 @@ product { LV2: manifest.ttl lv2:port lv2:designation lv2:control web: not used cmd: not used + ios: not used android: not used optional: bus is optionally connected? boolean, default false @@ -115,6 +131,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional web: not used cmd: whether to pass NULLs if not chosen audio I/O buses + ios: whether to pass NULLs if not chosen audio I/O buses android: whether to pass NULLs if not chosen audio I/O buses } ] @@ -126,6 +143,7 @@ product { LV2: manifest.ttl lv2:port lv2:name web: AudioWorkletProcessor.parameterDescriptors, web-demo <label> cmd: not used + ios: index.html android: index.html <label> shortName: parameter short name string, required @@ -133,6 +151,7 @@ product { LV2: manifest.ttl lv2:port lv2:shortName web: not used cmd: not used + ios: not used android: not used id: parameter unique id string, required @@ -140,6 +159,7 @@ product { LV2: manifest.ttl lv2:port lv2:symbol (bypass ports used "enabled") web: not used cmd: command line parameter name etc. + ios: not used android: not used direction: "input" or "output", required @@ -147,6 +167,7 @@ product { LV2: manifest.ttl lv2:port a - lots of implications web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications cmd: lots of places + ios: data.h, index.html android: lots of places isBypass: parameter is bypass/enabled? boolean - lots of implications, default false @@ -154,6 +175,7 @@ product { LV2: manifest.ttl lv2:port, run() (set parameter) web: AudoWorkletProcessor.process(), web-demo <range> min/max/step cmd: set parameter + ios: native.mm set parameter, index.html <range> min/max/step android: JNI set parameter, index.html <range> min/max/step isLatency: parameter is latency output? boolean - lots of implications, default false @@ -161,21 +183,23 @@ product { LV2: manifest.ttl lv2:port, TBD round output value web: not (yet) used cmd: not (yet) used + ios: not used android: not (yet) used isCpumeter: - parameter is output cpu meter? boolean - VST3: TODO + parameter is output cpu meter? boolean. It must be an output parameter. It is handled within the wrappers, and not by the plugin user code + VST3: data.h, vst3.c LV2: data.h, lv2.c - web: TODO + web: processor.js cmd: TODO - android: TODO - ios: TODO + ios: data.h native.mm + android: data.h jni.cpp defaultValue: default value, number, mapped, required for non-bypass VST3: ParameterInfo defaultNormalizedValue, controller initialize LV2: manifest.ttl lv2:port lv2:default, activate() (set initial parameter) web: AudioWorkletProcessor.parameterDescriptors, processor_new(), web-demo initial <range> value and value <span> innerText cmd: default parameter value + ios: native.mm set parameter initial value, index.html initial <range> value android: JNI set parameter initial value, index.html initial <range> value minimum: minimum value, number, mapped, required for non-bypass @@ -183,6 +207,7 @@ product { LV2: manifest.ttl lv2:port lv2:minimum, run() (set parameter, value clamped) web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping cmd: set parameter (value clamped) + ios: native.mm set parameter (value clamped), index.html <range> mapping android: JNI set parameter (value clamped), index.html <range> mapping maximum: maximum value, number, mapped, required for non-bypass @@ -190,6 +215,7 @@ product { LV2: manifest.ttl lv2:port lv2:maximum, run() (set parameter, value clamped) web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping cmd: set parameter (value clamped) + ios: native.mm set parameter (value clamped), index.html <range> mapping android: JNI set parameter (value clamped), index.html <range> mapping toggled: parameter is on/off? boolean, default false @@ -197,6 +223,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty lv2:toggled, run() (set parameter) web: AudoWorkletProcessor.process(), web-demo <range> min/max/step cmd: set parameter + ios: native.mm set parameter, index.html <range> min/max/step android: JNI set parameter, index.html <range> min/max/step optional: parameter is optionally connected? boolean, default false @@ -204,6 +231,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional web: not used cmd: not used + ios: not used android: not used integer: parameter values are integers? boolean, default false @@ -211,6 +239,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty lv2:integer, run() (set parameter) web: AudoWorkletProcessor.process(), web-demo <range> step cmd: set parameter + ios: native.mm set parameter, index.html <range> step android: JNI set parameter, index.html <range> step scalePoints: { "label1": value1, "label2", value2, ... } @@ -219,6 +248,7 @@ product { LV2: manifest.ttl lv2:port lv2:scalePoint web: not (yet) used cmd: not (yet) used + ios: not (yet) used android: not (yet) used list: parameter is a list (using scalePoints values)? default false @@ -226,6 +256,7 @@ product { LV2: manifest.ttl lv2:port lv2:enumeration - run() (set parameter) TBD? web: TBD (approx to closest? dropdown? both?) cmd: not (yet) used + ios: not (yet) used android: not (yet) used unit: unit of measure (from predefined list, see tibia-index.js), default "" @@ -233,6 +264,7 @@ product { LV2: manifest.ttl lv2:port units:unit web: web-demo value <span> innerText cmd: not (yet) used + ios: not (yet) used android: not (yet) used map: "linear" vs "logarithmic" @@ -240,6 +272,7 @@ product { LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic web: web-demo <range> values cmd: not used + ios: index.html <range> values android: index.html <range> values } ]