Revert "Merge remote-tracking branch 'origin/main' into cpumeter"

This reverts commit c0106cccd8, reversing
changes made to e6bfa583a6.
This commit is contained in:
Paolo Marrone 2024-08-29 16:10:41 +02:00
parent c0106cccd8
commit a57cc0f7e7
12 changed files with 462 additions and 415 deletions

63
notes
View File

@ -4,22 +4,22 @@ company {
LV2: manifest.ttl doap:maintainer foaf:name LV2: manifest.ttl doap:maintainer foaf:name
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
url: url:
VST3: PFactoryInfo.url VST3: PFactoryInfo.url
LV2: manifest.ttl doap:maintainer rdfs:seeAlso LV2: manifest.ttl doap:maintainer rdfs:seeAlso
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
email: email:
VST3: PFactoryInfo.email VST3: PFactoryInfo.email
LV2: manifest.ttl doap:maintainer foaf:mbox LV2: manifest.ttl doap:maintainer foaf:mbox
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
} }
product { product {
@ -28,29 +28,29 @@ product {
LV2: manifest.ttl plugin doap:name LV2: manifest.ttl plugin doap:name
web: web-demo <title> and <h1> web: web-demo <title> and <h1>
cmd: not used cmd: not used
android: index.html <title>, AndroidManifest.xml <application> <activity> android:label
ios: index.html <title> ios: index.html <title>
android: index.html <title>, AndroidManifest.xml <application> <activity> android:label
version: version:
VST3: PClassInfo{2,W}.version (first 3 numbers) VST3: PClassInfo{2,W}.version (first 3 numbers)
LV2: not used LV2: not used
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
buildVersion: buildVersion:
VST3: PClassInfo{2,W}.version (last number) VST3: PClassInfo{2,W}.version (last number)
LV2: not used LV2: not used
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
bundleName: bundleName:
VST3: plugin folder name, plugin .dll name, Info.plist VST3: plugin folder name, plugin .dll name, Info.plist
LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary
web: registerProcessor(), output file names web: registerProcessor(), output file names
cmd: executable file name cmd: executable file name
ios: project.yml name/target, vars.mk BUNDLE_NAME
android: .so/.apk filenames android: .so/.apk filenames
ios: xcodegen name and target name, xcodeproj filename
buses: [ buses: [
{ {
name: name:
@ -59,24 +59,24 @@ product {
LV2: manifest.ttl lv2:port lv2:name LV2: manifest.ttl lv2:port lv2:name
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
shortName: shortName:
bus short name string, required bus short name string, required
VST3: not used VST3: not used
LV2: manifest.ttl lv2:port lv2:shortName LV2: manifest.ttl lv2:port lv2:shortName
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
id: id:
bus unique id string, required bus unique id string, required
VST3; not used VST3; not used
LV2: manifest.ttl lv2:port lv2:symbol (resulting ports can have _l or _r appended) LV2: manifest.ttl lv2:port lv2:symbol (resulting ports can have _l or _r appended)
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
direction: direction:
"input" or "output", required "input" or "output", required
VST3: BusInfo flags - lots of implications VST3: BusInfo flags - lots of implications
@ -115,24 +115,24 @@ product {
LV2: manifest.ttl lv2:port a lv2:CVPort LV2: manifest.ttl lv2:port a lv2:CVPort
web: web-demo choice of audio I/O buses web: web-demo choice of audio I/O buses
cmd: 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 ios: choice of audio I/O buses
android: choice of audio I/O buses
control: control:
bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false
VST3: not used VST3: not used
LV2: manifest.ttl lv2:port lv2:designation lv2:control LV2: manifest.ttl lv2:port lv2:designation lv2:control
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
optional: optional:
bus is optionally connected? boolean, default false bus is optionally connected? boolean, default false
VST3: BusInfo flags, plugin initialize, activate bus, set active VST3: BusInfo flags, plugin initialize, activate bus, set active
LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional
web: not used web: not used
cmd: whether to pass NULLs if not chosen audio I/O buses 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 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: [ parameters: [
@ -143,24 +143,24 @@ product {
LV2: manifest.ttl lv2:port lv2:name LV2: manifest.ttl lv2:port lv2:name
web: AudioWorkletProcessor.parameterDescriptors, web-demo <label> web: AudioWorkletProcessor.parameterDescriptors, web-demo <label>
cmd: not used cmd: not used
ios: index.html
android: index.html <label> android: index.html <label>
ios: index.html <label>
shortName: shortName:
parameter short name string, required parameter short name string, required
VST3: ParameterInfo shortTitle VST3: ParameterInfo shortTitle
LV2: manifest.ttl lv2:port lv2:shortName LV2: manifest.ttl lv2:port lv2:shortName
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
id: id:
parameter unique id string, required parameter unique id string, required
VST3; not used VST3; not used
LV2: manifest.ttl lv2:port lv2:symbol (bypass ports used "enabled") LV2: manifest.ttl lv2:port lv2:symbol (bypass ports used "enabled")
web: not used web: not used
cmd: command line parameter name etc. cmd: command line parameter name etc.
android: not used
ios: not used ios: not used
android: not used
direction: direction:
"input" or "output", required "input" or "output", required
VST3: ParameterInfo flags - lots of implications VST3: ParameterInfo flags - lots of implications
@ -175,16 +175,24 @@ product {
LV2: manifest.ttl lv2:port, run() (set parameter) LV2: manifest.ttl lv2:port, run() (set parameter)
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
cmd: set parameter cmd: set parameter
android: JNI set parameter, index.html <range> min/max/step
ios: native.mm 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: isLatency:
parameter is latency output? boolean - lots of implications, default false parameter is latency output? boolean - lots of implications, default false
VST3: TBD VST3: TBD
LV2: manifest.ttl lv2:port, TBD round output value LV2: manifest.ttl lv2:port, TBD round output value
web: not (yet) used web: not (yet) used
cmd: not (yet) used cmd: not (yet) used
ios: not used
android: not (yet) 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: defaultValue:
default value, number, mapped, required for non-bypass default value, number, mapped, required for non-bypass
VST3: ParameterInfo defaultNormalizedValue, controller initialize VST3: ParameterInfo defaultNormalizedValue, controller initialize
@ -193,47 +201,46 @@ product {
cmd: default parameter value cmd: default parameter value
ios: native.mm set parameter initial value, index.html initial <range> value ios: native.mm set parameter initial value, index.html initial <range> value
android: JNI 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:
minimum value, number, mapped, required for non-bypass minimum value, number, mapped, required for non-bypass
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped) VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
LV2: manifest.ttl lv2:port lv2:minimum, run() (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 web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
cmd: set parameter (value clamped) 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 android: JNI set parameter (value clamped), index.html <range> mapping
ios: native set parameter (value clamped), index.html <range> mapping
maximum: maximum:
maximum value, number, mapped, required for non-bypass maximum value, number, mapped, required for non-bypass
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped) VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
LV2: manifest.ttl lv2:port lv2:maximum, run() (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 web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
cmd: set parameter (value clamped) 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 android: JNI set parameter (value clamped), index.html <range> mapping
ios: native set parameter (value clamped), index.html <range> mapping
toggled: toggled:
parameter is on/off? boolean, default false parameter is on/off? boolean, default false
VST3: ParameterInfo stepCount, controller set parameter/state VST3: ParameterInfo stepCount, controller set parameter/state
LV2: manifest.ttl lv2:port lv2:portProperty lv2:toggled, run() (set parameter) LV2: manifest.ttl lv2:port lv2:portProperty lv2:toggled, run() (set parameter)
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
cmd: set parameter cmd: set parameter
ios: native.mm set parameter, index.html <range> min/max/step
android: JNI 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: optional:
parameter is optionally connected? boolean, default false parameter is optionally connected? boolean, default false
VST3: not used VST3: not used
LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional
web: not used web: not used
cmd: not used cmd: not used
android: not used
ios: not used ios: not used
android: not used
integer: integer:
parameter values are integers? boolean, default false parameter values are integers? boolean, default false
VST3: ParameterInfo stepCount, controller set parameter/state VST3: ParameterInfo stepCount, controller set parameter/state
LV2: manifest.ttl lv2:port lv2:portProperty lv2:integer, run() (set parameter) LV2: manifest.ttl lv2:port lv2:portProperty lv2:integer, run() (set parameter)
web: AudoWorkletProcessor.process(), web-demo <range> step web: AudoWorkletProcessor.process(), web-demo <range> step
cmd: set parameter cmd: set parameter
ios: native.mm set parameter, index.html <range> step
android: JNI set parameter, index.html <range> step android: JNI set parameter, index.html <range> step
ios: native set parameter, index.html <range> step
scalePoints: scalePoints:
{ "label1": value1, "label2", value2, ... } { "label1": value1, "label2", value2, ... }
labeled values, default none labeled values, default none
@ -241,32 +248,32 @@ product {
LV2: manifest.ttl lv2:port lv2:scalePoint LV2: manifest.ttl lv2:port lv2:scalePoint
web: not (yet) used web: not (yet) used
cmd: not (yet) used cmd: not (yet) used
android: not (yet) used
ios: not (yet) used ios: not (yet) used
android: not (yet) used
list: list:
parameter is a list (using scalePoints values)? default false parameter is a list (using scalePoints values)? default false
VST3: TBD (+approx to closest?) VST3: TBD (+approx to closest?)
LV2: manifest.ttl lv2:port lv2:enumeration - run() (set parameter) TBD? LV2: manifest.ttl lv2:port lv2:enumeration - run() (set parameter) TBD?
web: TBD (approx to closest? dropdown? both?) web: TBD (approx to closest? dropdown? both?)
cmd: not (yet) used cmd: not (yet) used
android: not (yet) used
ios: not (yet) used ios: not (yet) used
android: not (yet) used
unit: unit:
unit of measure (from predefined list, see tibia-index.js), default "" unit of measure (from predefined list, see tibia-index.js), default ""
VST3: ParameterInfo units VST3: ParameterInfo units
LV2: manifest.ttl lv2:port units:unit LV2: manifest.ttl lv2:port units:unit
web: web-demo value <span> innerText web: web-demo value <span> innerText
cmd: not (yet) used cmd: not (yet) used
android: not (yet) used
ios: not (yet) used ios: not (yet) used
android: not (yet) used
map: map:
"linear" vs "logarithmic" "linear" vs "logarithmic"
VST3: many places (requires libm) VST3: many places (requires libm)
LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic
web: web-demo <range> values web: web-demo <range> values
cmd: not used cmd: not used
android: index.html <range> values
ios: index.html <range> values ios: index.html <range> values
android: index.html <range> values
} }
] ]
} }

View File

@ -21,8 +21,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#include <string.h> #include <string.h>
@ -46,60 +47,71 @@
#if NUM_MIDI_INPUTS > 0 #if NUM_MIDI_INPUTS > 0
# include <vector> # include <vector>
# include <amidi/AMidi.h> # include <amidi/AMidi.h>
#endif #endif
#ifdef PARAM_OUT_CPU_INDEX
# include "fatica.h"
#endif
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h> #include <xmmintrin.h>
#include <pmmintrin.h> #include <pmmintrin.h>
#endif #endif
static ma_device device; static ma_device device;
static plugin instance; static plugin instance;
static void * mem; static void *mem;
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN #if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
float zero[BLOCK_SIZE]; float zero[BLOCK_SIZE];
#endif #endif
#if NUM_CHANNELS_IN > 0 #if NUM_CHANNELS_IN > 0
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
float * x_in[NUM_CHANNELS_IN]; float *x_in[NUM_CHANNELS_IN];
#endif #endif
#if NUM_ALL_CHANNELS_IN > 0 #if NUM_ALL_CHANNELS_IN > 0
const float * x[NUM_ALL_CHANNELS_IN]; const float *x[NUM_ALL_CHANNELS_IN];
#else #else
const float ** x; const float **x;
#endif #endif
#if NUM_NON_OPT_CHANNELS_OUT > 0 #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 #endif
#if NUM_CHANNELS_OUT > 0 #if NUM_CHANNELS_OUT > 0
float * y_out[NUM_CHANNELS_OUT]; float *y_out[NUM_CHANNELS_OUT];
#endif #endif
#if NUM_ALL_CHANNELS_OUT > 0 #if NUM_ALL_CHANNELS_OUT > 0
float * y[NUM_ALL_CHANNELS_OUT]; float *y[NUM_ALL_CHANNELS_OUT];
#else #else
float ** y; float **y;
#endif #endif
#if PARAMETERS_N > 0 #if PARAMETERS_N > 0
std::mutex mutex; std::mutex mutex;
float param_values[PARAMETERS_N]; float param_values[PARAMETERS_N];
float param_values_prev[PARAMETERS_N]; float param_values_prev[PARAMETERS_N];
#endif #endif
#if NUM_MIDI_INPUTS > 0 #if NUM_MIDI_INPUTS > 0
struct PortData { struct PortData {
AMidiDevice *device; AMidiDevice *device;
int portNumber; int portNumber;
AMidiOutputPort *port; AMidiOutputPort *port;
}; };
std::vector<PortData> midiPorts; std::vector<PortData> midiPorts;
# define MIDI_BUFFER_SIZE 1024 # 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 #endif
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
(void)pDevice; (void)pDevice;
#ifdef PARAM_OUT_CPU_INDEX
const unsigned long long processTimeStart = fatica_time_process();
#endif
#if defined(__aarch64__) #if defined(__aarch64__)
uint64_t fpcr; uint64_t fpcr;
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(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 (mutex.try_lock()) {
# if PARAMETERS_N > 0 # if PARAMETERS_N > 0
for (size_t i = 0; i < PARAMETERS_N; i++) { 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); param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
}
else if (param_values_prev[i] != param_values[i]) { else if (param_values_prev[i] != param_values[i]) {
plugin_set_parameter(&instance, i, param_values[i]); plugin_set_parameter(&instance, i, param_values[i]);
param_values_prev[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_FLUSH_ZERO_MODE(flush_zero_mode);
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
#endif #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" 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); ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
#endif #endif
deviceConfig.periodSizeInFrames = BLOCK_SIZE; deviceConfig.periodSizeInFrames = BLOCK_SIZE;
deviceConfig.periods = 1; deviceConfig.periods = 1;
deviceConfig.performanceProfile = ma_performance_profile_low_latency; deviceConfig.performanceProfile = ma_performance_profile_low_latency;
deviceConfig.noPreSilencedOutputBuffer = 1; deviceConfig.noPreSilencedOutputBuffer = 1;
deviceConfig.noClip = 0; deviceConfig.noClip = 0;
deviceConfig.noDisableDenormals = 0; deviceConfig.noDisableDenormals = 0;
deviceConfig.noFixedSizedCallback = 1; deviceConfig.noFixedSizedCallback = 1;
deviceConfig.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
deviceConfig.capture.pDeviceID = NULL; deviceConfig.capture.pDeviceID = NULL;
deviceConfig.capture.format = ma_format_f32; deviceConfig.capture.format = ma_format_f32;
deviceConfig.capture.channels = NUM_CHANNELS_IN; deviceConfig.capture.channels = NUM_CHANNELS_IN;
deviceConfig.capture.shareMode = ma_share_mode_shared; deviceConfig.capture.shareMode = ma_share_mode_shared;
deviceConfig.playback.pDeviceID = NULL; deviceConfig.playback.pDeviceID = NULL;
deviceConfig.playback.format = ma_format_f32; deviceConfig.playback.format = ma_format_f32;
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
deviceConfig.playback.channels = NUM_CHANNELS_OUT; deviceConfig.playback.channels = NUM_CHANNELS_OUT;
#else #else
deviceConfig.playback.channels = 1; // Fake & muted deviceConfig.playback.channels = 1; // Fake & muted
#endif #endif
deviceConfig.playback.shareMode = ma_share_mode_shared; deviceConfig.playback.shareMode = ma_share_mode_shared;
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
return false; return false;
plugin_callbacks cbs = { plugin_callbacks cbs = {
/* .handle = */ NULL, /* .handle = */ NULL,
/* .format = */ "android", /* .format = */ "android",
/* .get_bindir = */ NULL, /* .get_bindir = */ NULL,
/* .get_datadir = */ NULL /* .get_datadir = */ NULL
}; };
plugin_init(&instance, &cbs); plugin_init(&instance, &cbs);
@ -243,6 +269,10 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
#endif #endif
plugin_set_sample_rate(&instance, (float)device.sampleRate); 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); size_t req = plugin_mem_req(&instance);
if (req != 0) { if (req != 0) {
mem = malloc(req); mem = malloc(req);

View File

@ -21,8 +21,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#include <stdio.h> #include <stdio.h>

View File

@ -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

View File

@ -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);
};

View File

@ -21,8 +21,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#include <string.h> #include <string.h>

View File

@ -21,67 +21,79 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#if PARAMETERS_N > 0 #if PARAMETERS_N > 0
#include <algorithm> # include <algorithm>
#endif #endif
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0 #if PARAMETERS_N + NUM_MIDI_INPUTS > 0
#include <mutex> # include <mutex>
#endif #endif
#include <vector> #include <vector>
#define MINIAUDIO_IMPLEMENTATION #define MINIAUDIO_IMPLEMENTATION
#define MA_NO_RUNTIME_LINKING #define MA_NO_RUNTIME_LINKING
#include "miniaudio.h" #include "miniaudio.h"
#define BLOCK_SIZE 32 #define BLOCK_SIZE 32
#ifdef PARAM_OUT_CPU_INDEX
# include "fatica.h"
#endif
static ma_device device; static ma_device device;
static ma_device_config deviceConfig; static ma_device_config deviceConfig;
char device_inited = 0; char device_inited = 0;
static plugin instance; static plugin instance;
static void * mem; static void *mem;
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN #if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
float zero[BLOCK_SIZE]; float zero[BLOCK_SIZE];
#endif #endif
#if NUM_CHANNELS_IN > 0 #if NUM_CHANNELS_IN > 0
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
float * x_in[NUM_CHANNELS_IN]; float *x_in[NUM_CHANNELS_IN];
#endif #endif
#if NUM_ALL_CHANNELS_IN > 0 #if NUM_ALL_CHANNELS_IN > 0
const float * x[NUM_ALL_CHANNELS_IN]; const float *x[NUM_ALL_CHANNELS_IN];
#else #else
const float ** x; const float **x;
#endif #endif
#if NUM_NON_OPT_CHANNELS_OUT > 0 #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 #endif
#if NUM_CHANNELS_OUT > 0 #if NUM_CHANNELS_OUT > 0
float * y_out[NUM_CHANNELS_OUT]; float *y_out[NUM_CHANNELS_OUT];
#endif #endif
#if NUM_ALL_CHANNELS_OUT > 0 #if NUM_ALL_CHANNELS_OUT > 0
float * y[NUM_ALL_CHANNELS_OUT]; float *y[NUM_ALL_CHANNELS_OUT];
#else #else
float ** y; float **y;
#endif #endif
#if PARAMETERS_N > 0 #if PARAMETERS_N > 0
std::mutex mutex; std::mutex mutex;
float param_values[PARAMETERS_N]; float param_values[PARAMETERS_N];
float param_values_prev[PARAMETERS_N]; float param_values_prev[PARAMETERS_N];
#endif #endif
#if NUM_MIDI_INPUTS > 0 #if NUM_MIDI_INPUTS > 0
CFStringRef midiClientName = NULL; CFStringRef midiClientName = NULL;
MIDIClientRef midiClient = NULL; MIDIClientRef midiClient = NULL;
CFStringRef midiInputName = NULL; CFStringRef midiInputName = NULL;
MIDIPortRef midiPort = NULL; MIDIPortRef midiPort = NULL;
#define MIDIBUFFERLEN 1023 #define MIDIBUFFERLEN 1023
uint8_t midiBuffer[MIDIBUFFERLEN]; uint8_t midiBuffer[MIDIBUFFERLEN];
int midiBuffer_i = 0; int midiBuffer_i = 0;
#endif
#ifdef PARAM_OUT_CPU_INDEX
float cpu_meter = 0.f;
float sample_rate = 1.f;
#endif #endif
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
(void)pDevice; (void)pDevice;
#ifdef PARAM_OUT_CPU_INDEX
const unsigned long long processTimeStart = fatica_time_process();
#endif
#if defined(__aarch64__) #if defined(__aarch64__)
uint64_t fpcr; uint64_t fpcr;
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(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 (mutex.try_lock()) {
# if PARAMETERS_N > 0 # if PARAMETERS_N > 0
for (size_t i = 0; i < PARAMETERS_N; i++) { 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); param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
}
else if (param_values_prev[i] != param_values[i]) { else if (param_values_prev[i] != param_values[i]) {
plugin_set_parameter(&instance, i, param_values[i]); plugin_set_parameter(&instance, i, param_values[i]);
param_values_prev[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__) #if defined(__aarch64__)
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr)); __asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
#endif #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) #if (NUM_MIDI_INPUTS > 0)
@ -176,7 +202,7 @@ void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(
continue; continue;
mutex.lock(); mutex.lock();
if (midiBuffer_i < MIDIBUFFERLEN - 3) { if (midiBuffer_i < MIDIBUFFERLEN - 3) {
midiBuffer[midiBuffer_i ] = t[2]; midiBuffer[midiBuffer_i ] = t[2];
midiBuffer[midiBuffer_i + 1] = t[1]; midiBuffer[midiBuffer_i + 1] = t[1];
midiBuffer[midiBuffer_i + 2] = t[0]; midiBuffer[midiBuffer_i + 2] = t[0];
midiBuffer_i += 3; midiBuffer_i += 3;
@ -202,26 +228,26 @@ char audioStart() {
deviceConfig = ma_device_config_init(ma_device_type_playback); deviceConfig = ma_device_config_init(ma_device_type_playback);
#endif #endif
deviceConfig.periodSizeInFrames = BLOCK_SIZE; deviceConfig.periodSizeInFrames = BLOCK_SIZE;
deviceConfig.periods = 1; deviceConfig.periods = 1;
deviceConfig.performanceProfile = ma_performance_profile_low_latency; deviceConfig.performanceProfile = ma_performance_profile_low_latency;
deviceConfig.noPreSilencedOutputBuffer = 1; deviceConfig.noPreSilencedOutputBuffer = 1;
deviceConfig.noClip = 0; deviceConfig.noClip = 0;
deviceConfig.noDisableDenormals = 0; deviceConfig.noDisableDenormals = 0;
deviceConfig.noFixedSizedCallback = 1; deviceConfig.noFixedSizedCallback = 1;
deviceConfig.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
deviceConfig.capture.pDeviceID = NULL; deviceConfig.capture.pDeviceID = NULL;
deviceConfig.capture.format = ma_format_f32; deviceConfig.capture.format = ma_format_f32;
deviceConfig.capture.channels = NUM_CHANNELS_IN; deviceConfig.capture.channels = NUM_CHANNELS_IN;
deviceConfig.capture.shareMode = ma_share_mode_shared; deviceConfig.capture.shareMode = ma_share_mode_shared;
deviceConfig.playback.pDeviceID = NULL; deviceConfig.playback.pDeviceID = NULL;
deviceConfig.playback.format = ma_format_f32; deviceConfig.playback.format = ma_format_f32;
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
deviceConfig.playback.channels = NUM_CHANNELS_OUT; deviceConfig.playback.channels = NUM_CHANNELS_OUT;
#else #else
deviceConfig.playback.channels = 1; // Fake & muted deviceConfig.playback.channels = 1; // Fake & muted
#endif #endif
deviceConfig.playback.shareMode = ma_share_mode_shared; deviceConfig.playback.shareMode = ma_share_mode_shared;
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
return false; return false;
@ -254,10 +280,10 @@ char audioStart() {
#endif #endif
plugin_callbacks cbs = { plugin_callbacks cbs = {
/* .handle = */ NULL, /* .handle = */ NULL,
/* .format = */ "ios", /* .format = */ "ios",
/* .get_bindir = */ NULL, /* .get_bindir = */ NULL,
/* .get_datadir = */ NULL /* .get_datadir = */ NULL
}; };
plugin_init(&instance, &cbs); plugin_init(&instance, &cbs);
@ -270,6 +296,9 @@ char audioStart() {
#endif #endif
plugin_set_sample_rate(&instance, (float)device.sampleRate); 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); size_t req = plugin_mem_req(&instance);
if (req != 0) { if (req != 0) {

View File

@ -21,8 +21,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#include "plugin.h" #include "plugin.h"
@ -52,6 +53,10 @@
# include <pmmintrin.h> # include <pmmintrin.h>
#endif #endif
#ifdef PARAM_OUT_CPU_INDEX
# include "fatica.h"
#endif
static inline float clampf(float x, float m, float M) { static inline float clampf(float x, float m, float M) {
return x < m ? m : (x > M ? M : x); return x < m ? m : (x > M ? M : x);
} }
@ -67,31 +72,35 @@ static float adjust_param(size_t index, float value) {
} }
typedef struct { typedef struct {
plugin p; plugin p;
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0 #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 #endif
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0 #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 #endif
#if DATA_PRODUCT_MIDI_INPUTS_N > 0 #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 #endif
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0 #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 #endif
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0 #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 #endif
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0 #if DATA_PRODUCT_CONTROL_INPUTS_N > 0
float params[DATA_PRODUCT_CONTROL_INPUTS_N]; float params[DATA_PRODUCT_CONTROL_INPUTS_N];
#endif #endif
void * mem; void *mem;
char * bundle_path; char *bundle_path;
LV2_Log_Logger logger; LV2_Log_Logger logger;
LV2_URID_Map * map; LV2_URID_Map *map;
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0 #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 #endif
} plugin_instance; } plugin_instance;
@ -114,8 +123,8 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
// from https://lv2plug.in/book // from https://lv2plug.in/book
const char* missing = lv2_features_query(features, const char* missing = lv2_features_query(features,
LV2_LOG__log, &instance->logger.log, false, LV2_LOG__log, &instance->logger.log, false,
LV2_URID__map, &instance->map, true, LV2_URID__map, &instance->map, true,
NULL); NULL);
lv2_log_logger_set_map(&instance->logger, instance->map); 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 #endif
plugin_callbacks cbs = { plugin_callbacks cbs = {
/* .handle = */ (void *)instance, /* .handle = */ (void *)instance,
/* .format = */ "lv2", /* .format = */ "lv2",
/* .get_bindir = */ get_bundle_path_cb, /* .get_bindir = */ get_bundle_path_cb,
/* .get_datadir = */ get_bundle_path_cb /* .get_datadir = */ get_bundle_path_cb
}; };
plugin_init(&instance->p, &cbs); 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++) for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++)
instance->c[i] = NULL; instance->c[i] = NULL;
#endif #endif
#ifdef PARAM_OUT_CPU_INDEX
instance->cpu_meter = 0.f;
instance->sample_rate = sample_rate;
#endif
return instance; return instance;
@ -230,6 +243,10 @@ static void activate(LV2_Handle instance) {
static void run(LV2_Handle instance, uint32_t sample_count) { static void run(LV2_Handle instance, uint32_t sample_count) {
plugin_instance * i = (plugin_instance *)instance; plugin_instance * i = (plugin_instance *)instance;
#ifdef PARAM_OUT_CPU_INDEX
const unsigned long long processTimeStart = fatica_time_process();
#endif
#if defined(__aarch64__) #if defined(__aarch64__)
uint64_t fpcr; uint64_t fpcr;
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(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 #if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) { for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
uint32_t k = param_out_index[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); *i->c[k] = plugin_get_parameter(&i->p, k);
}
} }
#else #else
(void)plugin_get_parameter; (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_FLUSH_ZERO_MODE(flush_zero_mode);
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
#endif #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) { static void cleanup(LV2_Handle instance) {
@ -309,14 +341,14 @@ static void cleanup(LV2_Handle instance) {
} }
static const LV2_Descriptor descriptor = { static const LV2_Descriptor descriptor = {
/* .URI = */ DATA_LV2_URI, /* .URI = */ DATA_LV2_URI,
/* .instantiate = */ instantiate, /* .instantiate = */ instantiate,
/* .connect_port = */ connect_port, /* .connect_port = */ connect_port,
/* .activate = */ activate, /* .activate = */ activate,
/* .run = */ run, /* .run = */ run,
/* .deactivate = */ NULL, /* .deactivate = */ NULL,
/* .cleanup = */ cleanup, /* .cleanup = */ cleanup,
/* .extension_data = */ NULL /* .extension_data = */ NULL
}; };
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) { 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 #ifdef DATA_UI
typedef struct { typedef struct {
plugin_ui * ui; plugin_ui *ui;
char * bundle_path; char *bundle_path;
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
LV2UI_Write_Function write; LV2UI_Write_Function write;
LV2UI_Controller controller; LV2UI_Controller controller;
char has_touch; char has_touch;
LV2UI_Touch touch; LV2UI_Touch touch;
# endif # endif
} ui_instance; } ui_instance;
@ -399,17 +431,17 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
} }
plugin_ui_callbacks cbs = { plugin_ui_callbacks cbs = {
/* .handle = */ (void *)instance, /* .handle = */ (void *)instance,
/* .format = */ "lv2", /* .format = */ "lv2",
/* .get_bindir = */ ui_get_bundle_path_cb, /* .get_bindir = */ ui_get_bundle_path_cb,
/* .get_datadir = */ ui_get_bundle_path_cb, /* .get_datadir = */ ui_get_bundle_path_cb,
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
/* .set_parameter_begin = */ ui_set_parameter_begin_cb, /* .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 /* .set_parameter_end = */ ui_set_parameter_end_cb
# else # else
/* .set_parameter_begin = */ NULL, /* .set_parameter_begin = */ NULL,
/* .set_parameter = */ NULL, /* .set_parameter = */ NULL,
/* .set_parameter_end = */ NULL /* .set_parameter_end = */ NULL
# endif # endif
}; };
@ -471,15 +503,15 @@ static const void * ui_extension_data(const char * uri) {
} }
static const LV2UI_Descriptor ui_descriptor = { static const LV2UI_Descriptor ui_descriptor = {
/* .URI = */ DATA_LV2_UI_URI, /* .URI = */ DATA_LV2_UI_URI,
/* .instantiate = */ ui_instantiate, /* .instantiate = */ ui_instantiate,
/* .cleanup = */ ui_cleanup, /* .cleanup = */ ui_cleanup,
# if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
/* .port_event = */ ui_port_event, /* .port_event = */ ui_port_event,
# else # else
/* .port_event = */ NULL, /* .port_event = */ NULL,
# endif # endif
/* .extension_data = */ ui_extension_data /* .extension_data = */ ui_extension_data
}; };
LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) { LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) {

View File

@ -21,13 +21,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wpedantic"
#include "vst3_c_api.h" #include "vst3_c_api.h"
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#ifdef DATA_UI #ifdef DATA_UI
# include "plugin_ui.h" # include "plugin_ui.h"
@ -53,6 +54,10 @@
#include <pmmintrin.h> #include <pmmintrin.h>
#endif #endif
#ifdef PARAM_OUT_CPU_INDEX
# include "fatica.h"
#endif
// COM in C doc: // COM in C doc:
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C // https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733 // https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
@ -72,8 +77,8 @@ typedef struct Steinberg_ITimerHandlerVtbl
{ {
/* methods derived from "Steinberg_FUnknown": */ /* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_ITimerHandler": */ /* methods derived from "Steinberg_ITimerHandler": */
void (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface); void (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface);
@ -90,8 +95,8 @@ typedef struct Steinberg_IEventHandlerVtbl
{ {
/* methods derived from "Steinberg_FUnknown": */ /* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IEventHandler": */ /* methods derived from "Steinberg_IEventHandler": */
void (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, int fd); void (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, int fd);
@ -109,8 +114,8 @@ typedef struct Steinberg_IRunLoopVtbl
{ {
/* methods derived from "Steinberg_FUnknown": */ /* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IRunLoop": */ /* methods derived from "Steinberg_IRunLoop": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler, int fd); 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 { typedef struct pluginInstance {
Steinberg_Vst_IComponentVtbl * vtblIComponent; Steinberg_Vst_IComponentVtbl *vtblIComponent;
Steinberg_Vst_IAudioProcessorVtbl * vtblIAudioProcessor; Steinberg_Vst_IAudioProcessorVtbl *vtblIAudioProcessor;
Steinberg_Vst_IProcessContextRequirementsVtbl * vtblIProcessContextRequirements; Steinberg_Vst_IProcessContextRequirementsVtbl *vtblIProcessContextRequirements;
Steinberg_uint32 refs; Steinberg_uint32 refs;
Steinberg_FUnknown * context; Steinberg_FUnknown *context;
plugin p; plugin p;
float sampleRate; float sampleRate;
#if DATA_PRODUCT_PARAMETERS_N > 0 #if DATA_PRODUCT_PARAMETERS_N > 0
float parameters[DATA_PRODUCT_PARAMETERS_N]; float parameters[DATA_PRODUCT_PARAMETERS_N];
#endif #endif
#if DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N > 0 #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 #endif
#if DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N > 0 #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 #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 #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 // see https://github.com/steinbergmedia/vst3sdk/issues/128
char neededBusesActive; char neededBusesActive;
#endif #endif
#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 #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 #endif
#if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 #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 #endif
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 #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 #endif
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 #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 #endif
void * mem;
} pluginInstance; } pluginInstance;
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent; static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
@ -283,10 +291,10 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_
p->context = context; p->context = context;
plugin_callbacks cbs = { plugin_callbacks cbs = {
/* .handle = */ (void *)p, /* .handle = */ (void *)p,
/* .format = */ "vst3", /* .format = */ "vst3",
/* .get_bindir = */ get_bindir_cb, /* .get_bindir = */ get_bindir_cb,
/* .get_datadir = */ get_datadir_cb /* .get_datadir = */ get_datadir_cb
}; };
plugin_init(&p->p, &cbs); plugin_init(&p->p, &cbs);
#if DATA_PRODUCT_PARAMETERS_N > 0 #if DATA_PRODUCT_PARAMETERS_N > 0
@ -316,6 +324,9 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_
# endif # endif
#endif #endif
p->mem = NULL; p->mem = NULL;
#ifdef PARAM_OUT_CPU_INDEX
p->cpu_meter = 0.f;
#endif
return Steinberg_kResultOk; return Steinberg_kResultOk;
} }
@ -554,24 +565,24 @@ static Steinberg_tresult pluginGetState(void* thisInterface, struct Steinberg_IB
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent = { static Steinberg_Vst_IComponentVtbl pluginVtblIComponent = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ pluginIComponentQueryInterface, /* .queryInterface = */ pluginIComponentQueryInterface,
/* .addRef = */ pluginIComponentAddRef, /* .addRef = */ pluginIComponentAddRef,
/* .release = */ pluginIComponentRelease, /* .release = */ pluginIComponentRelease,
/* IPluginBase */ /* IPluginBase */
/* .initialize = */ pluginInitialize, /* .initialize = */ pluginInitialize,
/* .terminate = */ pluginTerminate, /* .terminate = */ pluginTerminate,
/* IComponent */ /* IComponent */
/* .getControllerClassId = */ pluginGetControllerClassId, /* .getControllerClassId = */ pluginGetControllerClassId,
/* .setIoMode = */ pluginSetIoMode, /* .setIoMode = */ pluginSetIoMode,
/* .getBusCount = */ pluginGetBusCount, /* .getBusCount = */ pluginGetBusCount,
/* .getBusInfo = */ pluginGetBusInfo, /* .getBusInfo = */ pluginGetBusInfo,
/* .getRoutingInfo = */ pluginGetRoutingInfo, /* .getRoutingInfo = */ pluginGetRoutingInfo,
/* .activateBus = */ pluginActivateBus, /* .activateBus = */ pluginActivateBus,
/* .setActive = */ pluginSetActive, /* .setActive = */ pluginSetActive,
/* .setState = */ pluginSetState, /* .setState = */ pluginSetState,
/* .getState = */ pluginGetState /* .getState = */ pluginGetState
}; };
static Steinberg_tresult pluginIAudioProcessorQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { 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) { static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst_ProcessData* data) {
TRACE("plugin IAudioProcessor process\n"); TRACE("plugin IAudioProcessor process\n");
#ifdef PARAM_OUT_CPU_INDEX
const unsigned long long processTimeStart = fatica_time_process();
#endif
#if defined(__aarch64__) #if defined(__aarch64__)
uint64_t fpcr; uint64_t fpcr;
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(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++) { for (Steinberg_int32 i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) {
if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly)) if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly))
continue; 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]) if (v == p->parameters[i])
continue; continue;
p->parameters[i] = v; 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); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
#endif #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; return Steinberg_kResultOk;
} }
@ -861,19 +889,19 @@ static Steinberg_uint32 pluginGetTailSamples(void* thisInterface) {
static Steinberg_Vst_IAudioProcessorVtbl pluginVtblIAudioProcessor = { static Steinberg_Vst_IAudioProcessorVtbl pluginVtblIAudioProcessor = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ pluginIAudioProcessorQueryInterface, /* .queryInterface = */ pluginIAudioProcessorQueryInterface,
/* .addRef = */ pluginIAudioProcessorAddRef, /* .addRef = */ pluginIAudioProcessorAddRef,
/* .release = */ pluginIAudioProcessorRelease, /* .release = */ pluginIAudioProcessorRelease,
/* IAudioProcessor */ /* IAudioProcessor */
/* .setBusArrangements = */ pluginSetBusArrangements, /* .setBusArrangements = */ pluginSetBusArrangements,
/*. getBusArrangement = */ pluginGetBusArrangement, /*. getBusArrangement = */ pluginGetBusArrangement,
/* .canProcessSampleSize = */ pluginCanProcessSampleSize, /* .canProcessSampleSize = */ pluginCanProcessSampleSize,
/* .getLatencySamples = */ pluginGetLatencySamples, /* .getLatencySamples = */ pluginGetLatencySamples,
/* .setupProcessing = */ pluginSetupProcessing, /* .setupProcessing = */ pluginSetupProcessing,
/* .setProcessing = */ pluginSetProcessing, /* .setProcessing = */ pluginSetProcessing,
/* .process = */ pluginProcess, /* .process = */ pluginProcess,
/* .getTailSamples = */ pluginGetTailSamples /* .getTailSamples = */ pluginGetTailSamples
}; };
static Steinberg_tresult pluginIProcessContextRequirementsQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { 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 = { static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRequirements = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ pluginIProcessContextRequirementsQueryInterface, /* .queryInterface = */ pluginIProcessContextRequirementsQueryInterface,
/* .addRef = */ pluginIProcessContextRequirementsAddRef, /* .addRef = */ pluginIProcessContextRequirementsAddRef,
/* .release = */ pluginIProcessContextRequirementsRelease, /* .release = */ pluginIProcessContextRequirementsRelease,
/* IProcessContextRequirements */ /* IProcessContextRequirements */
/* .getProcessContextRequirements = */ pluginGetProcessContextRequirements /* .getProcessContextRequirements = */ pluginGetProcessContextRequirements
}; };
typedef struct plugView plugView; typedef struct plugView plugView;
typedef struct controller { typedef struct controller {
Steinberg_Vst_IEditControllerVtbl * vtblIEditController; Steinberg_Vst_IEditControllerVtbl *vtblIEditController;
Steinberg_Vst_IMidiMappingVtbl * vtblIMidiMapping; Steinberg_Vst_IMidiMappingVtbl *vtblIMidiMapping;
#ifdef DATA_UI #ifdef DATA_UI
//Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint; //Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint;
#endif #endif
Steinberg_uint32 refs; Steinberg_uint32 refs;
Steinberg_FUnknown * context; Steinberg_FUnknown *context;
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 #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 #endif
struct Steinberg_Vst_IComponentHandler * componentHandler; struct Steinberg_Vst_IComponentHandler *componentHandler;
#ifdef DATA_UI #ifdef DATA_UI
plugView ** views; plugView **views;
size_t viewsCount; size_t viewsCount;
#endif #endif
} controller; } controller;
@ -937,10 +965,10 @@ static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController;
# include <X11/Xlib.h> # include <X11/Xlib.h>
typedef struct { typedef struct {
Steinberg_ITimerHandlerVtbl * vtblITimerHandler; Steinberg_ITimerHandlerVtbl *vtblITimerHandler;
Steinberg_uint32 refs; Steinberg_uint32 refs;
void * data; void *data;
void (*cb)(void *data); void (*cb)(void *data);
} timerHandler; } timerHandler;
static Steinberg_tresult timerHandlerQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) { 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 = { static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ timerHandlerQueryInterface, /* .queryInterface = */ timerHandlerQueryInterface,
/* .addRef = */ timerHandlerAddRef, /* .addRef = */ timerHandlerAddRef,
/* .release = */ timerHandlerRelease, /* .release = */ timerHandlerRelease,
/* ITimerHandler */ /* ITimerHandler */
/* .onTimer = */ timerHandlerOnTimer /* .onTimer = */ timerHandlerOnTimer
}; };
# elif defined(__APPLE__) # elif defined(__APPLE__)
@ -1008,19 +1036,19 @@ static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = {
# endif # endif
typedef struct plugView { typedef struct plugView {
Steinberg_IPlugViewVtbl * vtblIPlugView; Steinberg_IPlugViewVtbl *vtblIPlugView;
Steinberg_uint32 refs; Steinberg_uint32 refs;
Steinberg_IPlugFrame * frame; Steinberg_IPlugFrame *frame;
plugin_ui * ui; plugin_ui *ui;
controller * ctrl; controller *ctrl;
# ifdef __linux__ # ifdef __linux__
Steinberg_IRunLoop * runLoop; Steinberg_IRunLoop *runLoop;
timerHandler timer; timerHandler timer;
Display * display; Display *display;
# elif defined(__APPLE__) # elif defined(__APPLE__)
CFRunLoopTimerRef timer; CFRunLoopTimerRef timer;
# elif defined(_WIN32) || defined(__CYGWIN__) # elif defined(_WIN32) || defined(__CYGWIN__)
UINT_PTR timer; UINT_PTR timer;
# endif # endif
} plugView; } plugView;
@ -1170,17 +1198,17 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste
return Steinberg_kInvalidArgument; return Steinberg_kInvalidArgument;
plugin_ui_callbacks cbs = { plugin_ui_callbacks cbs = {
/* .handle = */ (void *)v, /* .handle = */ (void *)v,
/* .format = */ "vst3", /* .format = */ "vst3",
/* .get_bindir = */ get_bindir_cb, /* .get_bindir = */ get_bindir_cb,
/* .get_datadir = */ get_datadir_cb, /* .get_datadir = */ get_datadir_cb,
# if DATA_PRODUCT_PARAMETERS_N > 0 # if DATA_PRODUCT_PARAMETERS_N > 0
/* .set_parameter_begin = */ plugViewSetParameterBeginCb, /* .set_parameter_begin = */ plugViewSetParameterBeginCb,
/* .set_parameter = */ plugViewSetParameterCb, /* .set_parameter = */ plugViewSetParameterCb,
/* .set_parameter_end = */ plugViewSetParameterEndCb /* .set_parameter_end = */ plugViewSetParameterEndCb
# else # else
/* .set_parameter_begin = */ NULL, /* .set_parameter_begin = */ NULL,
/* .set_parameter = */ NULL, /* .set_parameter = */ NULL,
/* .set_parameter_end = */ NULL /* .set_parameter_end = */ NULL
# endif # endif
}; };
@ -1203,11 +1231,11 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste
} }
# elif defined(__APPLE__) # elif defined(__APPLE__)
CFRunLoopTimerContext ctx = { CFRunLoopTimerContext ctx = {
/* .version = */ 0, /* .version = */ 0,
/* .info = */ v, /* .info = */ v,
/* .retain = */ NULL, /* .retain = */ NULL,
/* .release = */ NULL, /* .release = */ NULL,
/* .copyDescription = */ NULL /* .copyDescription = */ NULL
}; };
v->timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 20.0 / 1000.0, 0, 0, plugViewTimerCb, &ctx); v->timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 20.0 / 1000.0, 0, 0, plugViewTimerCb, &ctx);
CFRunLoopAddTimer(CFRunLoopGetCurrent(), v->timer, kCFRunLoopCommonModes); CFRunLoopAddTimer(CFRunLoopGetCurrent(), v->timer, kCFRunLoopCommonModes);
@ -1396,23 +1424,23 @@ static void plugViewOnTimer(void *thisInterface) {
static Steinberg_IPlugViewVtbl plugViewVtblIPlugView = { static Steinberg_IPlugViewVtbl plugViewVtblIPlugView = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ plugViewQueryInterface, /* .queryInterface = */ plugViewQueryInterface,
/* .addRef = */ plugViewAddRef, /* .addRef = */ plugViewAddRef,
/* .release = */ plugViewRelease, /* .release = */ plugViewRelease,
/* IPlugView */ /* IPlugView */
/* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported, /* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported,
/* .attached = */ plugViewAttached, /* .attached = */ plugViewAttached,
/* .removed = */ plugViewRemoved, /* .removed = */ plugViewRemoved,
/* .onWheel = */ plugViewOnWheel, /* .onWheel = */ plugViewOnWheel,
/* .onKeyDown = */ plugViewOnKeyDown, /* .onKeyDown = */ plugViewOnKeyDown,
/* .onKeyUp = */ plugViewOnKeyUp, /* .onKeyUp = */ plugViewOnKeyUp,
/* .getSize = */ plugViewGetSize, /* .getSize = */ plugViewGetSize,
/* .onSize = */ plugViewOnSize, /* .onSize = */ plugViewOnSize,
/* .onFocus = */ plugViewOnFocus, /* .onFocus = */ plugViewOnFocus,
/* .setFrame = */ plugViewSetFrame, /* .setFrame = */ plugViewSetFrame,
/* .canResize = */ plugViewCanResize, /* .canResize = */ plugViewCanResize,
/* .checkSizeConstraint = */ plugViewCheckSizeConstraint /* .checkSizeConstraint = */ plugViewCheckSizeConstraint
}; };
#endif #endif
@ -1497,7 +1525,7 @@ static Steinberg_tresult controllerInitialize(void* thisInterface, struct Steinb
#endif #endif
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 #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) { 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 + 1] = 0.5;
c->parameters[i + 2] = 0.0; c->parameters[i + 2] = 0.0;
} }
@ -1781,28 +1809,28 @@ static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Ste
static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController = { static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ controllerIEditControllerQueryInterface, /* .queryInterface = */ controllerIEditControllerQueryInterface,
/* .addRef = */ controllerIEditControllerAddRef, /* .addRef = */ controllerIEditControllerAddRef,
/* .release = */ controllerIEditControllerRelease, /* .release = */ controllerIEditControllerRelease,
/* IPluginBase */ /* IPluginBase */
/* .initialize = */ controllerInitialize, /* .initialize = */ controllerInitialize,
/* .terminate = */ controllerTerminate, /* .terminate = */ controllerTerminate,
/* IEditController */ /* IEditController */
/* .setComponentState = */ controllerSetComponentState, /* .setComponentState = */ controllerSetComponentState,
/* .setState = */ controllerSetState, /* .setState = */ controllerSetState,
/* .getState = */ controllerGetState, /* .getState = */ controllerGetState,
/* .getParameterCount = */ controllerGetParameterCount, /* .getParameterCount = */ controllerGetParameterCount,
/* .getParameterInfo = */ controllerGetParameterInfo, /* .getParameterInfo = */ controllerGetParameterInfo,
/* .getParamStringByValue = */ controllerGetParamStringByValue, /* .getParamStringByValue = */ controllerGetParamStringByValue,
/* .getParamValueByString = */ controllerGetParamValueByString, /* .getParamValueByString = */ controllerGetParamValueByString,
/* .normalizedParamToPlain = */ controllerNormalizedParamToPlain, /* .normalizedParamToPlain = */ controllerNormalizedParamToPlain,
/* .plainParamToNormalized = */ controllerPlainParamToNormalized, /* .plainParamToNormalized = */ controllerPlainParamToNormalized,
/* .getParamNormalized = */ controllerGetParamNormalized, /* .getParamNormalized = */ controllerGetParamNormalized,
/* .setParamNormalized = */ controllerSetParamNormalized, /* .setParamNormalized = */ controllerSetParamNormalized,
/* .setComponentHandler = */ controllerSetComponentHandler, /* .setComponentHandler = */ controllerSetComponentHandler,
/* .createView = */ controllerCreateView /* .createView = */ controllerCreateView
}; };
static Steinberg_tresult controllerIMidiMappingQueryInterface(void* thisInterface, const Steinberg_TUID iid, void** obj) { 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 = { static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ controllerIMidiMappingQueryInterface, /* .queryInterface = */ controllerIMidiMappingQueryInterface,
/* .addRef = */ controllerIMidiMappingAddRef, /* .addRef = */ controllerIMidiMappingAddRef,
/* .release = */ controllerIMidiMappingRelease, /* .release = */ controllerIMidiMappingRelease,
/* IMidiMapping */ /* IMidiMapping */
/* .getMidiControllerAssignment = */ controllerGetMidiControllerAssignment /* .getMidiControllerAssignment = */ controllerGetMidiControllerAssignment
}; };
#ifdef DATA_UI #ifdef DATA_UI
@ -1895,14 +1923,14 @@ static Steinberg_tresult controllerIConnectionPointNotify(void* thisInterface, s
static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint = { static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ controllerIConnectionPointQueryInterface, /* .queryInterface = */ controllerIConnectionPointQueryInterface,
/* .addRef = */ controllerIConnectionPointAddRef, /* .addRef = */ controllerIConnectionPointAddRef,
/* .release = */ controllerIConnectionPointRelease, /* .release = */ controllerIConnectionPointRelease,
/* IConnectionPoint */ /* IConnectionPoint */
/* .connect = */ controllerIConnectionPointConnect, /* .connect = */ controllerIConnectionPointConnect,
/* .disconnect = */ controllerIConnectionPointDisconnect, /* .disconnect = */ controllerIConnectionPointDisconnect,
/* .notify = */ controllerIConnectionPointNotify /* .notify = */ controllerIConnectionPointNotify
}; };
# endif # endif
#endif #endif
@ -2127,22 +2155,22 @@ static Steinberg_tresult factorySetHostContext(void* thisInterface, struct Stein
static Steinberg_IPluginFactory3Vtbl factoryVtbl = { static Steinberg_IPluginFactory3Vtbl factoryVtbl = {
/* FUnknown */ /* FUnknown */
/* .queryInterface = */ factoryQueryInterface, /* .queryInterface = */ factoryQueryInterface,
/* .addRef = */ factoryAddRef, /* .addRef = */ factoryAddRef,
/* .release = */ factoryRelease, /* .release = */ factoryRelease,
/* IPluginFactory */ /* IPluginFactory */
/* .getFactoryInfo = */ factoryGetFactoryInfo, /* .getFactoryInfo = */ factoryGetFactoryInfo,
/* .countClasses = */ factoryCountClasses, /* .countClasses = */ factoryCountClasses,
/* .getClassInfo = */ factoryGetClassInfo, /* .getClassInfo = */ factoryGetClassInfo,
/* .createInstance = */ factoryCreateInstance, /* .createInstance = */ factoryCreateInstance,
/* IPluginFactory2 */ /* IPluginFactory2 */
/* .getClassInfo2 = */ factoryGetClassInfo2, /* .getClassInfo2 = */ factoryGetClassInfo2,
/* IPluginFactory3 */ /* IPluginFactory3 */
/* .getClassInfoUnicode = */ factoryGetClassInfoUnicode, /* .getClassInfoUnicode = */ factoryGetClassInfoUnicode,
/* .setHostContext = */ factorySetHostContext /* .setHostContext = */ factorySetHostContext
}; };
static Steinberg_IPluginFactory3 factory = { &factoryVtbl }; static Steinberg_IPluginFactory3 factory = { &factoryVtbl };

View File

@ -21,27 +21,28 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "callbacks.h"
#include "data.h" #include "data.h"
#include "plugin_api.h"
#include "plugin.h" #include "plugin.h"
#include "string.h" #include "string.h"
#include "walloc.h" #include "walloc.h"
typedef struct { typedef struct {
plugin p; plugin p;
void * mem; void *mem;
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0 #if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128]; float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128];
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N]; const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
float zero_buf[128]; float zero_buf[128];
#endif #endif
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0 #if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128]; float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128];
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N]; float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
#endif #endif
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0 #if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N]; float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N];
#endif #endif
} instance; } instance;
@ -51,10 +52,10 @@ instance * processor_new(float sample_rate) {
return NULL; return NULL;
plugin_callbacks cbs = { plugin_callbacks cbs = {
/* .handle = */ NULL, /* .handle = */ NULL,
/* .format = */ "web", /* .format = */ "web",
/* .get_bindir = */ NULL, /* .get_bindir = */ NULL,
/* .get_datadir = */ NULL /* .get_datadir = */ NULL
}; };
plugin_init(&i->p, &cbs); plugin_init(&i->p, &cbs);

View File

@ -68,17 +68,17 @@ static void plugin_reset(plugin *instance) {
static void plugin_set_parameter(plugin *instance, size_t index, float value) { static void plugin_set_parameter(plugin *instance, size_t index, float value) {
switch (index) { switch (index) {
case plugin_parameter_gain: case 0:
//approx instance->gain = powf(10.f, 0.05f * value); //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); instance->gain = ((2.6039890429412597e-4f * value + 0.032131027163547855f) * value + 1.f) / ((0.0012705124328080768f * value - 0.0666763481312185f) * value + 1.f);
break; break;
case plugin_parameter_delay: case 1:
instance->delay = 0.001f * value; instance->delay = 0.001f * value;
break; break;
case plugin_parameter_cutoff: case 2:
instance->cutoff = value; instance->cutoff = value;
break; break;
case plugin_parameter_bypass: case 3:
instance->bypass = value >= 0.5f; instance->bypass = value >= 0.5f;
break; break;
} }

View File

@ -1,39 +1,32 @@
#!/bin/sh #!/bin/sh
dir=`dirname $0` 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/../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 $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 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/../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 $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 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 $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-make $dir/../out/web
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $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 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/../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 $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/keystore.jks $dir/../out/android
cp $dir/plugin.h $dir/../out/android/src 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/../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 $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 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/../templates/cmd $dir/../out/cmd
$dir/../tibia $dir/product.json,$dir/company.json,$dir/cmd-make.json $dir/../templates/cmd-make $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 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/../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 $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 cp $dir/plugin.h $dir/../out/daisy-seed/src