diff --git a/notes b/notes index fc3cf00..a9b6511 100644 --- a/notes +++ b/notes @@ -4,22 +4,22 @@ company { LV2: manifest.ttl doap:maintainer foaf:name web: not used cmd: not used - android: 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 - android: 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 - android: not used ios: not used + android: not used } product { @@ -28,29 +28,29 @@ product { LV2: manifest.ttl plugin doap:name web: web-demo and <h1> cmd: not used - android: index.html <title>, AndroidManifest.xml <application> <activity> android:label 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 - android: 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 - android: 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 - ios: xcodegen name and target name, xcodeproj filename buses: [ { name: @@ -59,24 +59,24 @@ product { LV2: manifest.ttl lv2:port lv2:name web: not used cmd: not used - android: not used ios: not used + android: not used shortName: bus short name string, required VST3: not used LV2: manifest.ttl lv2:port lv2:shortName web: not used cmd: not used - android: not used ios: not used + android: not used id: bus unique id string, required VST3; not used LV2: manifest.ttl lv2:port lv2:symbol (resulting ports can have _l or _r appended) web: not used cmd: not used - android: not used ios: not used + android: not used direction: "input" or "output", required VST3: BusInfo flags - lots of implications @@ -115,24 +115,24 @@ 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 - android: 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 VST3: not used LV2: manifest.ttl lv2:port lv2:designation lv2:control web: not used cmd: not used - android: not used ios: not used + android: not used optional: bus is optionally connected? boolean, default false VST3: BusInfo flags, plugin initialize, activate bus, set active LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional web: not used cmd: whether to pass NULLs if not chosen audio I/O buses - android: 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 } ] parameters: [ @@ -143,24 +143,24 @@ product { LV2: manifest.ttl lv2:port lv2:name web: AudioWorkletProcessor.parameterDescriptors, web-demo <label> cmd: not used + ios: index.html android: index.html <label> - ios: index.html <label> shortName: parameter short name string, required VST3: ParameterInfo shortTitle LV2: manifest.ttl lv2:port lv2:shortName web: not used cmd: not used - android: not used ios: not used + android: not used id: parameter unique id string, required VST3; not used LV2: manifest.ttl lv2:port lv2:symbol (bypass ports used "enabled") web: not used cmd: command line parameter name etc. - android: not used ios: not used + android: not used direction: "input" or "output", required VST3: ParameterInfo flags - lots of implications @@ -175,16 +175,24 @@ product { LV2: manifest.ttl lv2:port, run() (set parameter) web: AudoWorkletProcessor.process(), web-demo <range> min/max/step cmd: set parameter - android: JNI set parameter, index.html <range> min/max/step 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 VST3: TBD LV2: manifest.ttl lv2:port, TBD round output value web: not (yet) used cmd: not (yet) used + ios: not used android: not (yet) used - ios: not (yet) used + isCpumeter: + 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: processor.js + cmd: 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 @@ -193,47 +201,46 @@ product { 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 - ios: native set parameter initial value, index.html initial <range> value minimum: minimum value, number, mapped, required for non-bypass VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped) 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 - ios: native set parameter (value clamped), index.html <range> mapping maximum: maximum value, number, mapped, required for non-bypass VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped) 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 - ios: native set parameter (value clamped), index.html <range> mapping toggled: parameter is on/off? boolean, default false VST3: ParameterInfo stepCount, controller set parameter/state 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 - ios: native set parameter, index.html <range> min/max/step optional: parameter is optionally connected? boolean, default false VST3: not used LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional web: not used cmd: not used - android: not used ios: not used + android: not used integer: parameter values are integers? boolean, default false VST3: ParameterInfo stepCount, controller set parameter/state 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 - ios: native set parameter, index.html <range> step scalePoints: { "label1": value1, "label2", value2, ... } labeled values, default none @@ -241,32 +248,32 @@ product { LV2: manifest.ttl lv2:port lv2:scalePoint web: not (yet) used cmd: not (yet) used - android: not (yet) used ios: not (yet) used + android: not (yet) used list: parameter is a list (using scalePoints values)? default false VST3: TBD (+approx to closest?) LV2: manifest.ttl lv2:port lv2:enumeration - run() (set parameter) TBD? web: TBD (approx to closest? dropdown? both?) cmd: not (yet) used - android: not (yet) used ios: not (yet) used + android: not (yet) used unit: unit of measure (from predefined list, see tibia-index.js), default "" VST3: ParameterInfo units LV2: manifest.ttl lv2:port units:unit web: web-demo value <span> innerText cmd: not (yet) used - android: not (yet) used ios: not (yet) used + android: not (yet) used map: "linear" vs "logarithmic" VST3: many places (requires libm) LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic web: web-demo <range> values cmd: not used - android: index.html <range> values ios: index.html <range> values + android: index.html <range> values } ] } diff --git a/templates/android/src/jni.cpp b/templates/android/src/jni.cpp index a65dfa5..96a3725 100644 --- a/templates/android/src/jni.cpp +++ b/templates/android/src/jni.cpp @@ -21,8 +21,9 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #include "plugin.h" #include <string.h> @@ -46,60 +47,71 @@ #if NUM_MIDI_INPUTS > 0 # include <vector> - # include <amidi/AMidi.h> #endif +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif + #if defined(__i386__) || defined(__x86_64__) #include <xmmintrin.h> #include <pmmintrin.h> #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<PortData> 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)); @@ -116,8 +128,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]; @@ -182,6 +201,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" @@ -202,35 +228,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); @@ -243,6 +269,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/templates/cmd/src/main.c b/templates/cmd/src/main.c index 6f598f2..747c220 100644 --- a/templates/cmd/src/main.c +++ b/templates/cmd/src/main.c @@ -21,8 +21,9 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #include "plugin.h" #include <stdio.h> diff --git a/templates/common/src/plugin_api.h b/templates/common/src/plugin_api.h deleted file mode 100644 index dcd696b..0000000 --- a/templates/common/src/plugin_api.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Tibia - * - * Copyright (C) 2024 Orastron Srl unipersonale - * - * Tibia is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Tibia is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tibia. If not, see <http://www.gnu.org/licenses/>. - * - * File author: Stefano D'Angelo - */ - -#ifndef PLUGIN_API_H -#define PLUGIN_API_H - -typedef struct { - 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_begin)(void *handle, size_t index); - void (*set_parameter)(void *handle, size_t index, float value); - void (*set_parameter_end)(void *handle, size_t index); -} plugin_ui_callbacks; - -{{?it.product.parameters.length > 0}} -enum { - {{~it.product.parameters :p}} - plugin_parameter_{{=p.id}}, - {{~}} -}; -{{?}} - -#endif diff --git a/templates/common/tibia-index.js b/templates/common/tibia-index.js deleted file mode 100644 index 1dfd137..0000000 --- a/templates/common/tibia-index.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Tibia - * - * Copyright (C) 2024 Orastron Srl unipersonale - * - * Tibia is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Tibia is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tibia. If not, see <http://www.gnu.org/licenses/>. - * - * File author: Stefano D'Angelo - */ - -var path = require("path"); -var sep = path.sep; - -module.exports = function (data, api) { - api.generateFileFromTemplateFile(`src${sep}plugin_api.h`, `src${sep}plugin_api.h`, data); -}; diff --git a/templates/daisy-seed/src/main.cpp b/templates/daisy-seed/src/main.cpp index 43253b3..7403e0b 100644 --- a/templates/daisy-seed/src/main.cpp +++ b/templates/daisy-seed/src/main.cpp @@ -21,8 +21,9 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #include "plugin.h" #include <string.h> diff --git a/templates/ios/src/native.mm b/templates/ios/src/native.mm index b7c1ebe..e48446e 100644 --- a/templates/ios/src/native.mm +++ b/templates/ios/src/native.mm @@ -21,67 +21,79 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #include "plugin.h" #if PARAMETERS_N > 0 -#include <algorithm> +# include <algorithm> #endif #if PARAMETERS_N + NUM_MIDI_INPUTS > 0 -#include <mutex> +# include <mutex> #endif #include <vector> #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; -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 +#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)); @@ -92,8 +104,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]; @@ -152,6 +171,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) @@ -176,7 +202,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; @@ -202,26 +228,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; @@ -254,10 +280,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); @@ -270,6 +296,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) { diff --git a/templates/lv2/src/lv2.c b/templates/lv2/src/lv2.c index 787c25b..7d38975 100644 --- a/templates/lv2/src/lv2.c +++ b/templates/lv2/src/lv2.c @@ -21,8 +21,9 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #include "plugin.h" @@ -52,6 +53,10 @@ # include <pmmintrin.h> #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); } @@ -67,31 +72,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; @@ -114,8 +123,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); @@ -129,10 +138,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); @@ -168,6 +177,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; @@ -230,6 +243,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)); @@ -284,8 +301,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; @@ -297,6 +321,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) { @@ -309,14 +341,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) { @@ -325,13 +357,13 @@ 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; - char has_touch; - LV2UI_Touch touch; + LV2UI_Write_Function write; + LV2UI_Controller controller; + char has_touch; + LV2UI_Touch touch; # endif } ui_instance; @@ -399,17 +431,17 @@ 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, - /* .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_begin = */ ui_set_parameter_begin_cb, - /* .set_parameter = */ ui_set_parameter_cb, + /* .set_parameter = */ ui_set_parameter_cb, /* .set_parameter_end = */ ui_set_parameter_end_cb # else /* .set_parameter_begin = */ NULL, - /* .set_parameter = */ NULL, + /* .set_parameter = */ NULL, /* .set_parameter_end = */ NULL # endif }; @@ -471,15 +503,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/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index f695277..d48cbe3 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -21,13 +21,14 @@ #include <stdlib.h> #include <stdint.h> +#include "callbacks.h" + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #include "vst3_c_api.h" #pragma GCC diagnostic pop #include "data.h" -#include "plugin_api.h" #include "plugin.h" #ifdef DATA_UI # include "plugin_ui.h" @@ -53,6 +54,10 @@ #include <pmmintrin.h> #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 @@ -72,8 +77,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); @@ -90,8 +95,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); @@ -109,8 +114,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); @@ -182,39 +187,42 @@ 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 + DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 // see https://github.com/steinbergmedia/vst3sdk/issues/128 char neededBusesActive; #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; +#ifdef PARAM_OUT_CPU_INDEX + float cpu_meter; #endif - void * mem; } pluginInstance; static Steinberg_Vst_IComponentVtbl pluginVtblIComponent; @@ -283,10 +291,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 @@ -316,6 +324,9 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_ # endif #endif p->mem = NULL; +#ifdef PARAM_OUT_CPU_INDEX + p->cpu_meter = 0.f; +#endif return Steinberg_kResultOk; } @@ -554,24 +565,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) { @@ -737,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)); @@ -824,7 +839,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; @@ -848,6 +869,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; } @@ -861,19 +889,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) { @@ -900,31 +928,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; @@ -937,10 +965,10 @@ static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController; # include <X11/Xlib.h> 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) { @@ -991,12 +1019,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__) @@ -1008,19 +1036,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; @@ -1170,17 +1198,17 @@ 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_begin = */ plugViewSetParameterBeginCb, - /* .set_parameter = */ plugViewSetParameterCb, + /* .set_parameter = */ plugViewSetParameterCb, /* .set_parameter_end = */ plugViewSetParameterEndCb # else /* .set_parameter_begin = */ NULL, - /* .set_parameter = */ NULL, + /* .set_parameter = */ NULL, /* .set_parameter_end = */ NULL # endif }; @@ -1203,11 +1231,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); @@ -1396,23 +1424,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 @@ -1497,7 +1525,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; } @@ -1781,28 +1809,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) { @@ -1848,12 +1876,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 @@ -1895,14 +1923,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 @@ -2127,22 +2155,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 }; diff --git a/templates/web/src/processor.c b/templates/web/src/processor.c index a559be3..72619c4 100644 --- a/templates/web/src/processor.c +++ b/templates/web/src/processor.c @@ -21,27 +21,28 @@ #include <stddef.h> #include <stdint.h> +#include "callbacks.h" + #include "data.h" -#include "plugin_api.h" #include "plugin.h" #include "string.h" #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; @@ -51,10 +52,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/test/plugin.h b/test/plugin.h index 1910a51..4bbf97e 100644 --- a/test/plugin.h +++ b/test/plugin.h @@ -68,17 +68,17 @@ static void plugin_reset(plugin *instance) { static void plugin_set_parameter(plugin *instance, size_t index, float value) { switch (index) { - case plugin_parameter_gain: + case 0: //approx instance->gain = powf(10.f, 0.05f * value); instance->gain = ((2.6039890429412597e-4f * value + 0.032131027163547855f) * value + 1.f) / ((0.0012705124328080768f * value - 0.0666763481312185f) * value + 1.f); break; - case plugin_parameter_delay: + case 1: instance->delay = 0.001f * value; break; - case plugin_parameter_cutoff: + case 2: instance->cutoff = value; break; - case plugin_parameter_bypass: + case 3: instance->bypass = value >= 0.5f; break; } diff --git a/test/run.sh b/test/run.sh index 4b3eeb8..50f3173 100755 --- a/test/run.sh +++ b/test/run.sh @@ -1,39 +1,32 @@ #!/bin/sh dir=`dirname $0` -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/vst3 $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/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/lv2 $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/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/web $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-make $dir/../out/web $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $dir/../out/web cp $dir/plugin.h $dir/../out/web/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/android $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/keystore.jks $dir/../out/android cp $dir/plugin.h $dir/../out/android/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/ios $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/plugin.h $dir/../out/ios/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/cmd $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd $dir/../out/cmd $dir/../tibia $dir/product.json,$dir/company.json,$dir/cmd-make.json $dir/../templates/cmd-make $dir/../out/cmd cp $dir/plugin.h $dir/../out/cmd/src -$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/daisy-seed $dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json $dir/../templates/daisy-seed $dir/../out/daisy-seed $dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json,$dir/daisy-seed-make.json $dir/../templates/daisy-seed-make $dir/../out/daisy-seed cp $dir/plugin.h $dir/../out/daisy-seed/src