Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
e7c33becd2 | |||
![]() |
5cbc630249 | ||
![]() |
01fc0d8430 | ||
![]() |
fb8a80f3e5 | ||
![]() |
394b7ac1d7 | ||
393eac9207 | |||
f90ec7abda | |||
9727e377af | |||
207b4cb6ee | |||
99d0d34c50 | |||
b1bb7bfab6 | |||
b0c213ac27 | |||
e6bfa583a6 | |||
c4e60c745e | |||
cc1ecbf678 | |||
7302a19c23 | |||
e32ee4f4c2 | |||
8951042404 | |||
5f90c2e2e6 | |||
76e1b4bd8a | |||
91049ee490 | |||
8976c54698 | |||
ee9771b96a | |||
b2ec5c092e | |||
![]() |
20727f5f09 | ||
42d03ee749 | |||
10b2626ab6 | |||
09430b6901 | |||
7aba91abc9 | |||
35b20f66df | |||
30af875911 | |||
![]() |
d417383820 | ||
![]() |
1587e1ec9f | ||
![]() |
af99a702c3 | ||
![]() |
f3f028938b | ||
![]() |
d9cd79754d | ||
693730ea69 | |||
75585f3d48 | |||
3552a5e68e | |||
f9c0a8dd70 | |||
93c74432f4 | |||
472cfbfbf4 | |||
8dccc52b08 | |||
f1a8552f45 | |||
09af4d9af9 | |||
086b6f719b | |||
ac718119b7 | |||
29e4e11de4 | |||
6a291efa37 | |||
![]() |
e092600b4d | ||
![]() |
c39b5ed993 | ||
![]() |
619ff345a3 | ||
![]() |
5ef05ef959 | ||
![]() |
6fa2728e76 | ||
25f7d76d3f | |||
21a2cf68c8 | |||
1565eaabf3 | |||
f366841c2c | |||
acf92dd51d | |||
4d0ab165b3 | |||
992eebc8a2 | |||
0babfc9b5d | |||
5d07c39170 | |||
ebf2a2052c | |||
67cddf552b | |||
8ffbd207fe | |||
0fa25e8dc7 | |||
5b5f0618d1 |
19
notes
19
notes
@ -84,7 +84,7 @@ product {
|
||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
ios: data.h, index.html
|
||||
type:
|
||||
"audio" or "midi", required
|
||||
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
||||
@ -92,7 +92,7 @@ product {
|
||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
ios: data.h, index.html
|
||||
channels:
|
||||
"mono" or "stereo", audio type only, required
|
||||
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
||||
@ -100,7 +100,7 @@ product {
|
||||
web: AudioWorkletNode.outputChannelCount - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
ios: data.h
|
||||
sidechain:
|
||||
bus is not part of main audio path (sidechain)? boolean, default false
|
||||
VST3: BusInfo busType
|
||||
@ -108,6 +108,7 @@ product {
|
||||
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
|
||||
cv:
|
||||
bus is control voltage audio-rate? boolean, audio type only, default false
|
||||
VST3: BusInfo flags
|
||||
@ -167,7 +168,7 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
ios: data.h, index.html
|
||||
isBypass:
|
||||
parameter is bypass/enabled? boolean - lots of implications, default false
|
||||
VST3: ParameterInfo, controller get/set parameter/state
|
||||
@ -182,8 +183,16 @@ product {
|
||||
LV2: manifest.ttl lv2:port, TBD round output value
|
||||
web: not (yet) used
|
||||
cmd: not (yet) used
|
||||
ios: not used
|
||||
android: not (yet) used
|
||||
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
|
||||
android: data.h jni.cpp
|
||||
ios: data.h native.mm
|
||||
defaultValue:
|
||||
default value, number, mapped, required for non-bypass
|
||||
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
||||
|
@ -18,38 +18,38 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.android_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.android_make?.cxxflags ?? ""}}
|
||||
JFLAGS_EXTRA := {{=it.make?.jflags ?? ""}} {{=it.android_make?.jflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.android_make?.ldflags ?? ""}}
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.android_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.android_make?.cxxflags ?? ""}}
|
||||
JFLAGS_EXTRA := {{=it.make?.jflags ?? ""}} {{=it.android_make?.jflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.android_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.android_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.android_make?.cxxSrcs ?? ""}}
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.android_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.android_make?.cxxSrcs ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
KEY_STORE := {{=it.android_make.keyStore}}
|
||||
KEY_ALIAS := {{=it.android_make.keyAlias}}
|
||||
STORE_PASS := {{=it.android_make.storePass}}
|
||||
KEY_PASS := {{=it.android_make.keyPass}}
|
||||
KEY_STORE := {{=it.android_make.keyStore}}
|
||||
KEY_ALIAS := {{=it.android_make.keyAlias}}
|
||||
STORE_PASS := {{=it.android_make.storePass}}
|
||||
KEY_PASS := {{=it.android_make.keyPass}}
|
||||
|
||||
ANDROID_SDK_DIR := {{=it.android_make.sdkDir}}
|
||||
ANDROID_NDK_DIR := ${ANDROID_SDK_DIR}/ndk/{{=it.android_make.ndkVersion}}
|
||||
BUILD_TOOLS_DIR := ${ANDROID_SDK_DIR}/build-tools/{{=it.android_make.buildToolsVersion}}
|
||||
ANDROIDX_DIR := {{=it.android_make.androidxDir}}
|
||||
KOTLIN_DIR := {{=it.android_make.kotlinDir}}
|
||||
ANDROID_SDK_DIR := {{=it.android_make.sdkDir}}
|
||||
ANDROID_NDK_DIR := ${ANDROID_SDK_DIR}/ndk/{{=it.android_make.ndkVersion}}
|
||||
BUILD_TOOLS_DIR := ${ANDROID_SDK_DIR}/build-tools/{{=it.android_make.buildToolsVersion}}
|
||||
ANDROIDX_DIR := {{=it.android_make.androidxDir}}
|
||||
KOTLIN_DIR := {{=it.android_make.kotlinDir}}
|
||||
|
||||
ANDROID_JAR_FILE := ${ANDROID_SDK_DIR}/platforms/android-{{=it.android_make.androidVersion}}/android.jar
|
||||
ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-{{=it.android_make.androidxCoreVersion}}.jar
|
||||
ANDROIDX_LIFECYCLE_COMMON_FILE := ${ANDROIDX_DIR}/lifecycle-common-{{=it.android_make.androidxLifecycleCommonVersion}}.jar
|
||||
ANDROID_JAR_FILE := ${ANDROID_SDK_DIR}/platforms/android-{{=it.android_make.androidVersion}}/android.jar
|
||||
ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-{{=it.android_make.androidxCoreVersion}}.jar
|
||||
ANDROIDX_LIFECYCLE_COMMON_FILE := ${ANDROIDX_DIR}/lifecycle-common-{{=it.android_make.androidxLifecycleCommonVersion}}.jar
|
||||
ANDROIDX_VERSIONEDPARCELABLE_FILE := ${ANDROIDX_DIR}/versionedparcelable-{{=it.android_make.androidxVersionedparcelableVersion}}.jar
|
||||
KOTLIN_STDLIB_FILE := ${KOTLIN_DIR}/kotlin-stdlib-{{=it.android_make.kotlinStdlibVersion}}.jar
|
||||
KOTLINX_COROUTINES_CORE_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-{{=it.android_make.kotlinxCoroutinesCoreVersion}}.jar
|
||||
KOTLINX_COROUTINES_CORE_JVM_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-jvm-{{=it.android_make.kotlinxCoroutinesCoreJVMVersion}}.jar
|
||||
KOTLIN_STDLIB_FILE := ${KOTLIN_DIR}/kotlin-stdlib-{{=it.android_make.kotlinStdlibVersion}}.jar
|
||||
KOTLINX_COROUTINES_CORE_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-{{=it.android_make.kotlinxCoroutinesCoreVersion}}.jar
|
||||
KOTLINX_COROUTINES_CORE_JVM_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-jvm-{{=it.android_make.kotlinxCoroutinesCoreJVMVersion}}.jar
|
||||
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
|
@ -18,37 +18,37 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
|
||||
#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
|
||||
#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input") .reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
|
||||
#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}}
|
||||
#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}}
|
||||
|
||||
#if NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT > 0
|
||||
static struct {
|
||||
size_t index;
|
||||
char out;
|
||||
char optional;
|
||||
char channels;
|
||||
size_t index;
|
||||
char out;
|
||||
char optional;
|
||||
char channels;
|
||||
} audio_bus_data[NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT] = {
|
||||
{{~it.product.buses :b:i}}
|
||||
{{?b.type == "audio"}}
|
||||
{
|
||||
/* .index = */ {{=i}},
|
||||
/* .out = */ {{=b.direction == "output" ? 1 : 0}},
|
||||
/* .optional = */ {{=b.optional ? 1 : 0}},
|
||||
/* .channels = */ {{=b.channels == "mono" ? 1 : 2}}
|
||||
/* .index = */ {{=i}},
|
||||
/* .out = */ {{=b.direction == "output" ? 1 : 0}},
|
||||
/* .optional = */ {{=b.optional ? 1 : 0}},
|
||||
/* .channels = */ {{=b.channels == "mono" ? 1 : 2}}
|
||||
},
|
||||
{{?}}
|
||||
{{~}}
|
||||
@ -72,14 +72,19 @@ static struct {
|
||||
} param_data[PARAMETERS_N] = {
|
||||
{{~it.product.parameters :p}}
|
||||
{
|
||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
/* .max = */ {{=p.maximum.toExponential()}}f,
|
||||
/* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}}
|
||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
/* .max = */ {{=p.maximum.toExponential()}}f,
|
||||
/* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
|
||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||
{{?}}
|
||||
|
||||
#endif
|
||||
|
||||
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
||||
|
@ -46,60 +46,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 +127,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 +200,11 @@ 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();
|
||||
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@ -202,35 +225,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 +266,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);
|
||||
|
@ -27,4 +27,5 @@ module.exports = function (data, api) {
|
||||
api.copyFile(`src${sep}jni.cpp`, `src${sep}jni.cpp`);
|
||||
api.generateFileFromTemplateFile(`src${sep}MainActivity.java`, `src${sep}MainActivity.java`, data);
|
||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
||||
};
|
||||
|
@ -18,20 +18,20 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.cmd_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.cmd_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.cmd_make?.ldflags ?? ""}}
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.cmd_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.cmd_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.cmd_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}}
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
TINYWAV_DIR := {{=it.cmd_make.tinywavDir}}
|
||||
TINYWAV_DIR := {{=it.cmd_make.tinywavDir}}
|
||||
MIDI_PARSER_DIR := {{=it.cmd_make.midiParserDir}}
|
||||
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
|
75
templates/common/fatica.h
Normal file
75
templates/common/fatica.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef FATICA_H
|
||||
#define FATICA_H
|
||||
|
||||
// API
|
||||
|
||||
// unit = 100-nanosecond starting from somewhen
|
||||
unsigned long long fatica_time_process(void);
|
||||
void fatica_cpu_meter(float *value, unsigned long long start, unsigned long long end, uint32_t sample_count, float sample_rate);
|
||||
|
||||
// Implementation
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
static ULONGLONG filetime_to_ull(const FILETIME* ft) {
|
||||
return (((ULONGLONG)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
|
||||
}
|
||||
|
||||
unsigned long long fatica_time_process(void) {
|
||||
FILETIME creationTime, exitTime, kernelTime, userTime;
|
||||
const DWORD threadId = GetCurrentThreadId();
|
||||
const HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId);
|
||||
if (!GetThreadTimes(hThread, &creationTime, &exitTime, &kernelTime, &userTime))
|
||||
return 0ull;
|
||||
CloseHandle(hThread);
|
||||
return (unsigned long long) (filetime_to_ull(&kernelTime) + filetime_to_ull(&userTime));
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
# ifndef _XOPEN_SOURCE
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# define _XOPEN_SOURCE 600
|
||||
# else
|
||||
# define _XOPEN_SOURCE 500
|
||||
# endif
|
||||
# endif
|
||||
# include <time.h>
|
||||
# include <unistd.h>
|
||||
|
||||
unsigned long long fatica_time_process(void) {
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0)
|
||||
return 0ull;
|
||||
return (unsigned long long) (ts.tv_sec * 1e7 + ts.tv_nsec / 1e2);
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
# include <unistd.h>
|
||||
# include <mach/mach.h>
|
||||
# include <mach/thread_act.h>
|
||||
|
||||
unsigned long long fatica_time_process(void) {
|
||||
thread_t thread = mach_thread_self();
|
||||
thread_basic_info_data_t info;
|
||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||
if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count) != KERN_SUCCESS)
|
||||
return 0ull;
|
||||
return (info.user_time.seconds + info.system_time.seconds) * 1000
|
||||
+ (info.user_time.microseconds + info.system_time.microseconds) / 1000;
|
||||
}
|
||||
|
||||
#else
|
||||
# error "System not supported"
|
||||
#endif
|
||||
|
||||
void fatica_cpu_meter(float *value, unsigned long long start, unsigned long long end, uint32_t sample_count, float sample_rate) {
|
||||
const unsigned long long processTime100n = end - start;
|
||||
const double processTimeMs = ((double) processTime100n) * 1.0e-4;
|
||||
*value = *value * 0.99f + ((float) (processTimeMs * sample_count / (sample_rate * 1000))) * 0.01f;
|
||||
}
|
||||
|
||||
#endif // FATICA_H
|
@ -21,21 +21,25 @@
|
||||
#ifndef PLUGIN_API_H
|
||||
#define PLUGIN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
void * handle;
|
||||
const char * format;
|
||||
const char * (*get_bindir)(void *handle);
|
||||
void *handle;
|
||||
const char *format;
|
||||
|
||||
const char * (*get_bindir) (void *handle);
|
||||
const char * (*get_datadir)(void *handle);
|
||||
} plugin_callbacks;
|
||||
|
||||
typedef struct {
|
||||
void * handle;
|
||||
const char * format;
|
||||
const char * (*get_bindir)(void *handle);
|
||||
const char * (*get_datadir)(void *handle);
|
||||
void (*set_parameter_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);
|
||||
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}}
|
||||
@ -43,6 +47,8 @@ enum {
|
||||
{{~it.product.parameters :p}}
|
||||
plugin_parameter_{{=p.id}},
|
||||
{{~}}
|
||||
|
||||
plugin_parameter_count
|
||||
};
|
||||
{{?}}
|
||||
|
||||
|
@ -18,17 +18,17 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.daisy_seed_make?.cflags ?? ""}}
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.daisy_seed_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.daisy_seed_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.daisy_seed_make?.ldflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.daisy_seed_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.daisy_seed_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.daisy_seed_make?.cxxSrcs ?? ""}}
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.daisy_seed_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.daisy_seed_make?.cxxSrcs ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}}
|
||||
LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}}
|
||||
|
@ -21,7 +21,7 @@
|
||||
include vars.mk
|
||||
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
SOURCES := \
|
||||
@ -31,6 +31,7 @@ SOURCES := \
|
||||
$(COMMON_DIR)/src/native.mm \
|
||||
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
||||
$(PLUGIN_DIR)/plugin.h \
|
||||
$(PLUGIN_DIR)/fatica.h \
|
||||
$(C_SRCS_EXTRA) \
|
||||
$(CXX_SRCS_EXTRA) \
|
||||
$(SRCS_EXTRA)
|
||||
|
@ -30,6 +30,10 @@ targets:
|
||||
type: application
|
||||
sources:
|
||||
- path: src
|
||||
{{?it.ios_make.dependencies}}
|
||||
dependencies: {{~it.ios_make.dependencies :d}}
|
||||
- target: {{=d}}{{~}}
|
||||
{{?}}
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
||||
|
@ -18,12 +18,12 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}}
|
||||
SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}}
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.ios_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.ios_make?.cxxSrcs ?? ""}}
|
||||
SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
@ -97,12 +97,12 @@ struct templateApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
|
||||
audioPause()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
||||
audioResume()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
|
||||
audioPause()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
||||
audioResume()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,66 +18,70 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
|
||||
#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}}
|
||||
|
||||
#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
|
||||
#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}}
|
||||
#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}}
|
||||
|
||||
#if NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT > 0
|
||||
static struct {
|
||||
size_t index;
|
||||
char out;
|
||||
char optional;
|
||||
char channels;
|
||||
size_t index;
|
||||
char out;
|
||||
char optional;
|
||||
char channels;
|
||||
} audio_bus_data[NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT] = {
|
||||
{{~it.product.buses :b:i}}
|
||||
{{?b.type == "audio"}}
|
||||
{
|
||||
/* .index = */ {{=i}},
|
||||
/* .out = */ {{=b.direction == "output" ? 1 : 0}},
|
||||
/* .optional = */ {{=b.optional ? 1 : 0}},
|
||||
/* .channels = */ {{=b.channels == "mono" ? 1 : 2}}
|
||||
/* .index = */ {{=i}},
|
||||
/* .out = */ {{=b.direction == "output" ? 1 : 0}},
|
||||
/* .optional = */ {{=b.optional ? 1 : 0}},
|
||||
/* .channels = */ {{=b.channels == "mono" ? 1 : 2}}
|
||||
},
|
||||
{{?}}
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PARAMETERS_N {{=it.product.parameters.length}}
|
||||
#define PARAMETERS_N {{=it.product.parameters.length}}
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
|
||||
# define PARAM_BYPASS 1
|
||||
# define PARAM_TOGGLED (1<<1)
|
||||
# define PARAM_INTEGER (1<<2)
|
||||
# define PARAM_BYPASS 1
|
||||
# define PARAM_TOGGLED (1<<1)
|
||||
# define PARAM_INTEGER (1<<2)
|
||||
|
||||
static struct {
|
||||
char out;
|
||||
float def;
|
||||
float min;
|
||||
float max;
|
||||
uint32_t flags;
|
||||
char out;
|
||||
float def;
|
||||
float min;
|
||||
float max;
|
||||
uint32_t flags;
|
||||
} param_data[PARAMETERS_N] = {
|
||||
{{~it.product.parameters :p}}
|
||||
{
|
||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
/* .max = */ {{=p.maximum.toExponential()}}f,
|
||||
/* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??p.isLatency}}PARAM_INTEGER{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}}
|
||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
/* .max = */ {{=p.maximum.toExponential()}}f,
|
||||
/* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??p.isLatency}}PARAM_INTEGER{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
|
||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||
{{?}}
|
||||
#endif
|
||||
|
@ -21,14 +21,15 @@
|
||||
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<title>{{=it.product.name}}</title>
|
||||
<script type="text/javascript">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<title>{{=it.product.name}}</title>
|
||||
<script type="text/javascript">
|
||||
|
||||
function request(data) {
|
||||
return window.webkit.messageHandlers.listener.postMessage(data);
|
||||
}
|
||||
|
||||
|
||||
function needAudioPermission() {
|
||||
return request({ name: "needAudioPermission" });
|
||||
}
|
||||
@ -40,15 +41,15 @@ function requestAudioPermission() {
|
||||
function audioStart() {
|
||||
return request({ name: "audioStart" });
|
||||
}
|
||||
|
||||
|
||||
function audioStop() {
|
||||
return request({ name: "audioStop" });
|
||||
}
|
||||
|
||||
|
||||
function setParameter(index, value) {
|
||||
return request({ name: "setParameter", index: index, value: value });
|
||||
}
|
||||
|
||||
|
||||
function getParameter(index) {
|
||||
return request({ name: "getParameter", index: index });
|
||||
}
|
||||
@ -75,125 +76,126 @@ var outParamInterval;
|
||||
|
||||
window.onload = async function () {
|
||||
topButtonElem = document.getElementById("topButton");
|
||||
var paramsElem = document.getElementById("params");
|
||||
var paramsElem = document.getElementById("params");
|
||||
|
||||
for (var i = 0; i < data.buses.length; i++)
|
||||
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
||||
hasAudioPermission = !await needAudioPermission();
|
||||
break;
|
||||
}
|
||||
for (var i = 0; i < data.buses.length; i++) {
|
||||
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
||||
hasAudioPermission = !await needAudioPermission();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||
topButtonElem.addEventListener("click", async function () {
|
||||
if (hasAudioPermission) {
|
||||
if (audioStarted) {
|
||||
clearInterval(outParamInterval);
|
||||
await audioStop();
|
||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||
topButtonElem.addEventListener("click", async function () {
|
||||
if (hasAudioPermission) {
|
||||
if (audioStarted) {
|
||||
clearInterval(outParamInterval);
|
||||
await audioStop();
|
||||
|
||||
paramsElem.innerHTML = "";
|
||||
paramsElem.innerHTML = "";
|
||||
|
||||
topButtonElem.value = "START";
|
||||
audioStarted = false;
|
||||
} else {
|
||||
if (await audioStart()) {
|
||||
for (var i = 0; i < data.parameters.length; i++) {
|
||||
var div = document.createElement("div");
|
||||
topButtonElem.value = "START";
|
||||
audioStarted = false;
|
||||
} else {
|
||||
if (await audioStart()) {
|
||||
for (var i = 0; i < data.parameters.length; i++) {
|
||||
var div = document.createElement("div");
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute("for", "p" + i);
|
||||
label.innerText = data.parameters[i].name;
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute("for", "p" + i);
|
||||
label.innerText = data.parameters[i].name;
|
||||
|
||||
var range = document.createElement("input");
|
||||
range.classList.add("range");
|
||||
range.setAttribute("type", "range");
|
||||
range.setAttribute("id", "p" + i);
|
||||
range.setAttribute("name", "p" + i);
|
||||
if (data.parameters[i].isBypass || data.parameters[i].toggled) {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", 1);
|
||||
} else {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", data.parameters[i].integer ? 1 / (data.parameters[i].maximum - data.parameters[i].minimum) : "any");
|
||||
}
|
||||
range.value = unmap(i, data.parameters[i].defaultValue);
|
||||
if (data.parameters[i].direction == "output")
|
||||
range.setAttribute("readonly", "true");
|
||||
else {
|
||||
let index = i;
|
||||
range.addEventListener("input",
|
||||
async function (ev) {
|
||||
await setParameter(index, map(index, parseFloat(ev.target.value)));
|
||||
});
|
||||
}
|
||||
var range = document.createElement("input");
|
||||
range.classList.add("range");
|
||||
range.setAttribute("type", "range");
|
||||
range.setAttribute("id", "p" + i);
|
||||
range.setAttribute("name", "p" + i);
|
||||
if (data.parameters[i].isBypass || data.parameters[i].toggled) {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", 1);
|
||||
} else {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", data.parameters[i].integer ? 1 / (data.parameters[i].maximum - data.parameters[i].minimum) : "any");
|
||||
}
|
||||
range.value = unmap(i, data.parameters[i].defaultValue);
|
||||
if (data.parameters[i].direction == "output")
|
||||
range.setAttribute("readonly", "true");
|
||||
else {
|
||||
let index = i;
|
||||
range.addEventListener("input",
|
||||
async function (ev) {
|
||||
await setParameter(index, map(index, parseFloat(ev.target.value)));
|
||||
});
|
||||
}
|
||||
|
||||
div.appendChild(label);
|
||||
div.appendChild(document.createElement("br"));
|
||||
div.appendChild(range);
|
||||
paramsElem.appendChild(div);
|
||||
}
|
||||
div.appendChild(label);
|
||||
div.appendChild(document.createElement("br"));
|
||||
div.appendChild(range);
|
||||
paramsElem.appendChild(div);
|
||||
}
|
||||
|
||||
outParamInterval = setInterval(
|
||||
async function () {
|
||||
for (var i = 0; i < data.parameters.length; i++)
|
||||
if (data.parameters[i].direction == "output") {
|
||||
document.getElementById("p" + i).value = unmap(i, await getParameter(i));
|
||||
}
|
||||
}, 50);
|
||||
|
||||
topButtonElem.value = "STOP";
|
||||
audioStarted = true;
|
||||
} else
|
||||
alert("Could not start audio");
|
||||
}
|
||||
} else {
|
||||
await requestAudioPermission();
|
||||
var interval = setInterval(
|
||||
async function () {
|
||||
if (!await needAudioPermission()) {
|
||||
gotAudioPermission();
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
outParamInterval = setInterval(
|
||||
async function () {
|
||||
for (var i = 0; i < data.parameters.length; i++)
|
||||
if (data.parameters[i].direction == "output") {
|
||||
document.getElementById("p" + i).value = unmap(i, await getParameter(i));
|
||||
}
|
||||
}, 50);
|
||||
|
||||
topButtonElem.value = "STOP";
|
||||
audioStarted = true;
|
||||
} else
|
||||
alert("Could not start audio");
|
||||
}
|
||||
} else {
|
||||
await requestAudioPermission();
|
||||
var interval = setInterval(
|
||||
async function () {
|
||||
if (!await needAudioPermission()) {
|
||||
gotAudioPermission();
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function gotAudioPermission() {
|
||||
hasAudioPermission = true;
|
||||
topButtonElem.value = "START";
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 1em;
|
||||
}
|
||||
body {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#topButton {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
background-color: #04aa6d;
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
#topButton {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
background-color: #04aa6d;
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.range {
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input id="topButton" type="button">
|
||||
<div id="params"></div>
|
||||
</body>
|
||||
.range {
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input id="topButton" type="button">
|
||||
<div id="params"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -25,63 +25,74 @@
|
||||
#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 +103,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 +170,11 @@ 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();
|
||||
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (NUM_MIDI_INPUTS > 0)
|
||||
@ -176,7 +199,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 +225,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 +277,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 +293,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) {
|
||||
|
@ -27,4 +27,5 @@ module.exports = function (data, api) {
|
||||
api.copyFile(`src${sep}native.mm`, `src${sep}native.mm`);
|
||||
api.copyFile(`src${sep}app-Bridging-Header.h`, `src${sep}app-Bridging-Header.h`);
|
||||
api.copyFile(`src${sep}app.swift`, `src${sep}app.swift`, data);
|
||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
||||
};
|
||||
|
@ -68,11 +68,17 @@ endif
|
||||
|
||||
BUNDLE_DIR := $(BUNDLE_NAME).lv2
|
||||
|
||||
BUNDLE_DATA_PATH := build/$(BUNDLE_DIR)
|
||||
BUNDLE_BIN_PATH := build/$(BUNDLE_DIR)
|
||||
|
||||
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||
|
||||
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
M_SRCS := $(M_SRCS_EXTRA)
|
||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
||||
|
||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
|
||||
@ -86,10 +92,10 @@ build/$(BUNDLE_DIR)/manifest.ttl: $(DATA_DIR)/data/manifest.ttl.in | build/$(BUN
|
||||
cat $^ | sed s/@DLL_SUFFIX@/$(DLL_SUFFIX)/g | sed s/@UI_TYPE@/$(UI_TYPE)/g > $@
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) | build/$(BUNDLE_DIR)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
else
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
endif
|
||||
|
||||
@ -138,6 +144,9 @@ PERCENT := %
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
|
@ -18,15 +18,17 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.lv2_make?.cflags ?? ""}}
|
||||
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.lv2_make?.cSrcs ?? ""}}
|
||||
M_SRCS_EXTRA := {{=it.make?.mSrcs ?? ""}} {{=it.lv2_make?.mSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.lv2_make?.cxxSrcs ?? ""}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.lv2_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.lv2_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.lv2_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.lv2_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.lv2_make?.cxxSrcs ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.lv2_make?.ldflags ?? ""}}
|
||||
|
@ -63,6 +63,9 @@ static struct {
|
||||
static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
||||
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}}
|
||||
};
|
||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||
{{?}}
|
||||
#endif
|
||||
|
||||
{{?it.lv2.ui}}
|
||||
|
@ -52,6 +52,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 +71,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 +122,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 +137,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 +176,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 +242,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 +300,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 +320,12 @@ 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();
|
||||
fatica_cpu_meter(&i->cpu_meter, processTimeStart, processTimeEnd, sample_count, i->sample_rate);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void cleanup(LV2_Handle instance) {
|
||||
@ -309,14 +338,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 +354,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 +428,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 +500,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) {
|
||||
|
@ -122,4 +122,5 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
api.generateFileFromTemplateFile(`data${sep}manifest.ttl.in`, `data${sep}manifest.ttl.in`, data);
|
||||
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
||||
};
|
||||
|
@ -83,9 +83,15 @@ BUNDLE_DIR := $(BUNDLE_NAME).vst3
|
||||
DLL_DIR := Contents/$(PLATFORM)
|
||||
DLL_FILE := $(DLL_DIR)/$(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||
|
||||
BUNDLE_DATA_PATH := build/$(BUNDLE_DIR)/Contents/Resources
|
||||
BUNDLE_BIN_PATH := build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
|
||||
C_SRCS := $(COMMON_DIR)/src/vst3.c $(C_SRCS_EXTRA)
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
M_SRCS := $(M_SRCS_EXTRA)
|
||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
||||
|
||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
|
||||
@ -100,10 +106,10 @@ endif
|
||||
all: $(ALL)
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
else
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
endif
|
||||
|
||||
@ -118,6 +124,9 @@ endif
|
||||
build/$(BUNDLE_DIR)/Contents build/$(BUNDLE_DIR)/$(DLL_DIR) build/obj:
|
||||
mkdir -p $@
|
||||
|
||||
${BUNDLE_DATA_PATH}:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
@ -160,6 +169,9 @@ PERCENT := %
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
|
@ -18,17 +18,19 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.vst3_make?.cflags ?? ""}}
|
||||
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.vst3_make?.cSrcs ?? ""}}
|
||||
M_SRCS_EXTRA := {{=it.make?.mSrcs ?? ""}} {{=it.vst3_make?.mSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.vst3_make?.cxxSrcs ?? ""}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.vst3_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.vst3_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.vst3_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.vst3_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.vst3_make?.cxxSrcs ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.vst3_make?.ldflags ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
||||
|
@ -18,54 +18,54 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#define DATA_COMPANY_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.company.name, 63)}}"
|
||||
#define DATA_COMPANY_URL "{{=it.tibia.CGetUTF8StringLiteral(it.company.url, 255)}}"
|
||||
#define DATA_COMPANY_EMAIL "{{=it.tibia.CGetUTF8StringLiteral(it.company.email, 127)}}"
|
||||
#define DATA_COMPANY_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.company.name, 63)}}"
|
||||
#define DATA_COMPANY_URL "{{=it.tibia.CGetUTF8StringLiteral(it.company.url, 255)}}"
|
||||
#define DATA_COMPANY_EMAIL "{{=it.tibia.CGetUTF8StringLiteral(it.company.email, 127)}}"
|
||||
|
||||
#define DATA_PRODUCT_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.product.name, 63)}}"
|
||||
#define DATA_PRODUCT_VERSION "{{=(it.product.version + '.' + it.product.buildVersion).substring(0, 63)}}"
|
||||
#define DATA_PRODUCT_NAME "{{=it.tibia.CGetUTF8StringLiteral(it.product.name, 63)}}"
|
||||
#define DATA_PRODUCT_VERSION "{{=(it.product.version + '.' + it.product.buildVersion).substring(0, 63)}}"
|
||||
|
||||
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
|
||||
#define DATA_VST3_SDK_VERSION "VST 3.7.9"
|
||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
#define DATA_VST3_SDK_VERSION "VST 3.7.9"
|
||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
|
||||
static Steinberg_char16 dataVST3ControllerNameW[64] = { {{~Array.from(it.product.name + " Controller").slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
|
||||
#define DATA_VST3_PLUGIN_CID_1 0x{{=it.vst3.plugin.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_PLUGIN_CID_2 0x{{=it.vst3.plugin.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_PLUGIN_CID_3 0x{{=it.vst3.plugin.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_PLUGIN_CID_4 0x{{=it.vst3.plugin.cid.substring(24, 32)}}
|
||||
#define DATA_VST3_PLUGIN_CID_1 0x{{=it.vst3.plugin.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_PLUGIN_CID_2 0x{{=it.vst3.plugin.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_PLUGIN_CID_3 0x{{=it.vst3.plugin.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_PLUGIN_CID_4 0x{{=it.vst3.plugin.cid.substring(24, 32)}}
|
||||
|
||||
#define DATA_VST3_CONTROLLER_CID_1 0x{{=it.vst3.controller.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_2 0x{{=it.vst3.controller.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_3 0x{{=it.vst3.controller.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_4 0x{{=it.vst3.controller.cid.substring(24, 32)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_1 0x{{=it.vst3.controller.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_2 0x{{=it.vst3.controller.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_3 0x{{=it.vst3.controller.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_4 0x{{=it.vst3.controller.cid.substring(24, 32)}}
|
||||
|
||||
static const Steinberg_TUID dataPluginCID = SMTG_INLINE_UID(DATA_VST3_PLUGIN_CID_1, DATA_VST3_PLUGIN_CID_2, DATA_VST3_PLUGIN_CID_3, DATA_VST3_PLUGIN_CID_4);
|
||||
static const Steinberg_TUID dataPluginCID = SMTG_INLINE_UID(DATA_VST3_PLUGIN_CID_1, DATA_VST3_PLUGIN_CID_2, DATA_VST3_PLUGIN_CID_3, DATA_VST3_PLUGIN_CID_4);
|
||||
static const Steinberg_TUID dataControllerCID = SMTG_INLINE_UID(DATA_VST3_CONTROLLER_CID_1, DATA_VST3_CONTROLLER_CID_2, DATA_VST3_CONTROLLER_CID_3, DATA_VST3_CONTROLLER_CID_4);
|
||||
|
||||
#define DATA_VST3_SUBCATEGORY "{{=it.vst3.subCategory}}"
|
||||
#define DATA_VST3_SUBCATEGORY "{{=it.vst3.subCategory}}"
|
||||
|
||||
#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_BUSES_MIDI_OUTPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_BUSES_MIDI_OUTPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||
|
||||
#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||
|
||||
#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_AUDIO_INPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "audio" && x.direction == "input") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
@ -75,12 +75,12 @@ static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_AUDIO_I
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "audio" && x.direction == "output") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ {{=b.channels == "mono" ? 1 : 2}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?b.cv}} | Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{?}}{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
@ -90,12 +90,12 @@ static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PRODUCT_BUSES_AUDIO_
|
||||
static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ 16,
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ 16,
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
@ -105,12 +105,12 @@ static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INP
|
||||
static struct Steinberg_Vst_BusInfo busInfoMidiOutput[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "output") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ 16,
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ 16,
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
@ -122,104 +122,108 @@ static uint32_t midiInIndex[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
||||
|
||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||
{
|
||||
{{?p.isBypass}}
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 1,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 1,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
{{??}}
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .stepCount = */ {{=p.toggled ? 1 : (p.list && p.scalePoints.length > 1 ? p.scalePoints.length - 1 : (p.integer ? p.maximum - p.minimum : 0))}},
|
||||
/* .defaultNormalizedValue = */ {{?p.map == "logarithmic"}}{{=Number(Math.log(p.defaultValue / p.minimum) / (2 * Math.log(Math.sqrt(p.minimum * p.maximum) / Math.abs(p.minimum)))).toExponential()}}{{??}}{{=Number((p.defaultValue - p.minimum) / (p.maximum - p.minimum)).toExponential()}}{{?}},
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ {{?p.direction == "input"}}Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate{{??}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly{{?}}
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .stepCount = */ {{=p.toggled ? 1 : (p.list && p.scalePoints.length > 1 ? p.scalePoints.length - 1 : (p.integer ? p.maximum - p.minimum : 0))}},
|
||||
/* .defaultNormalizedValue = */ {{?p.map == "logarithmic"}}{{=Number(Math.log(p.defaultValue / p.minimum) / (2 * Math.log(Math.sqrt(p.minimum * p.maximum) / Math.abs(p.minimum)))).toExponential()}}{{??}}{{=Number((p.defaultValue - p.minimum) / (p.maximum - p.minimum)).toExponential()}}{{?}},
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ {{?p.direction == "input"}}Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate{{??}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly{{?}}
|
||||
{{?}}
|
||||
},
|
||||
{{~}}
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
},
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.5,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.5,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
},
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
|
||||
# if DATA_PRODUCT_PARAMETERS_N > 0
|
||||
|
||||
# define DATA_PARAM_BYPASS 1
|
||||
# define DATA_PARAM_TOGGLED (1<<1)
|
||||
# define DATA_PARAM_INTEGER (1<<2)
|
||||
# define DATA_PARAM_MAP_LOG (1<<3)
|
||||
# define DATA_PARAM_BYPASS 1
|
||||
# define DATA_PARAM_TOGGLED (1<<1)
|
||||
# define DATA_PARAM_INTEGER (1<<2)
|
||||
# define DATA_PARAM_MAP_LOG (1<<3)
|
||||
|
||||
static struct {
|
||||
size_t index;
|
||||
double min;
|
||||
double max;
|
||||
double def;
|
||||
uint32_t flags;
|
||||
double mapK;
|
||||
size_t index;
|
||||
double min;
|
||||
double max;
|
||||
double def;
|
||||
uint32_t flags;
|
||||
double mapK;
|
||||
// scalePoints?
|
||||
} parameterData[DATA_PRODUCT_PARAMETERS_N] = {
|
||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||
{
|
||||
/* .index = */ {{=p.paramIndex}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}},
|
||||
/* .max = */ {{=p.maximum.toExponential()}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .flags = */ {{?p.isBypass}}DATA_PARAM_BYPASS{{??}}0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?p.map == "logarithmic"}} | DATA_PARAM_MAP_LOG{{?}}{{?}},
|
||||
/* .mapK = */ {{?p.map == "logarithmic"}}{{=Number(2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))).toExponential()}}{{??}}0.0{{?}}
|
||||
/* .index = */ {{=p.paramIndex}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}},
|
||||
/* .max = */ {{=p.maximum.toExponential()}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||
/* .flags = */ {{?p.isBypass}}DATA_PARAM_BYPASS{{??}}0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?p.map == "logarithmic"}} | DATA_PARAM_MAP_LOG{{?}}{{?}},
|
||||
/* .mapK = */ {{?p.map == "logarithmic"}}{{=Number(2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))).toExponential()}}{{??}}0.0{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
|
||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||
{{?}}
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
{{?it.product.parameters.find(x => x.isLatency)}}
|
||||
#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}}
|
||||
#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}}
|
||||
{{?}}
|
||||
|
||||
{{?it.product.ui}}
|
||||
#define DATA_UI
|
||||
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
||||
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
||||
{{?}}
|
||||
|
@ -53,6 +53,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 +76,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 +94,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 +113,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 +186,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 +290,10 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_
|
||||
p->context = context;
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ (void *)p,
|
||||
/* .format = */ "vst3",
|
||||
/* .get_bindir = */ get_bindir_cb,
|
||||
/* .get_datadir = */ get_datadir_cb
|
||||
/* .handle = */ (void *)p,
|
||||
/* .format = */ "vst3",
|
||||
/* .get_bindir = */ get_bindir_cb,
|
||||
/* .get_datadir = */ get_datadir_cb
|
||||
};
|
||||
plugin_init(&p->p, &cbs);
|
||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||
@ -316,6 +323,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;
|
||||
}
|
||||
|
||||
@ -332,7 +342,7 @@ static Steinberg_tresult pluginTerminate(void *thisInterface) {
|
||||
static Steinberg_tresult pluginGetControllerClassId(void *thisInterface, Steinberg_TUID classId) {
|
||||
(void)thisInterface;
|
||||
|
||||
TRACE("plugin get controller class id %p %p\n", thisInterface, classId);
|
||||
TRACE("plugin get controller class id %p %s\n", thisInterface, classId);
|
||||
if (classId != NULL) {
|
||||
memcpy(classId, dataControllerCID, sizeof(Steinberg_TUID));
|
||||
return Steinberg_kResultTrue;
|
||||
@ -554,24 +564,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 +747,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 +838,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 +868,11 @@ 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();
|
||||
fatica_cpu_meter(&p->cpu_meter, processTimeStart, processTimeEnd, data->numSamples, p->sampleRate);
|
||||
#endif
|
||||
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
@ -861,19 +886,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 +925,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 +962,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 +1016,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 +1033,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;
|
||||
|
||||
@ -1104,7 +1129,7 @@ static void plugViewUpdateAllParameters(plugView *view) {
|
||||
}
|
||||
|
||||
static void plugViewSetParameterBeginCb(void *handle, size_t index) {
|
||||
TRACE("set parameter begin cb\n");
|
||||
TRACE("set parameter begin cb %zu \n", index);
|
||||
|
||||
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||
if (index == DATA_PARAM_LATENCY_INDEX)
|
||||
@ -1116,7 +1141,7 @@ static void plugViewSetParameterBeginCb(void *handle, size_t index) {
|
||||
}
|
||||
|
||||
static void plugViewSetParameterCb(void *handle, size_t index, float value) {
|
||||
TRACE("set parameter cb\n");
|
||||
TRACE("set parameter cb A %zu %f \n", index, value);
|
||||
|
||||
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||
if (index == DATA_PARAM_LATENCY_INDEX)
|
||||
@ -1129,7 +1154,7 @@ static void plugViewSetParameterCb(void *handle, size_t index, float value) {
|
||||
}
|
||||
|
||||
static void plugViewSetParameterEndCb(void *handle, size_t index) {
|
||||
TRACE("set parameter end cb\n");
|
||||
TRACE("set parameter end cb %zu \n", index);
|
||||
|
||||
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||
if (index == DATA_PARAM_LATENCY_INDEX)
|
||||
@ -1170,17 +1195,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 +1228,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);
|
||||
@ -1280,12 +1305,9 @@ static Steinberg_tresult plugViewGetSize(void* thisInterface, struct Steinberg_V
|
||||
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||
size->left = 0;
|
||||
size->top = 0;
|
||||
if (!v->ui) {
|
||||
uint32_t width, height;
|
||||
plugin_ui_get_default_size(&width, &height);
|
||||
size->right = width;
|
||||
size->bottom = height;
|
||||
} else {
|
||||
size->right = 0;
|
||||
size->bottom = 0;
|
||||
if (v->ui) {
|
||||
# ifdef __linux__
|
||||
XWindowAttributes attr;
|
||||
TRACE(" window %u\n", (Window)(*((char **)v->ui)));
|
||||
@ -1293,13 +1315,35 @@ static Steinberg_tresult plugViewGetSize(void* thisInterface, struct Steinberg_V
|
||||
size->right = attr.width;
|
||||
size->bottom = attr.height;
|
||||
# endif
|
||||
# ifdef __APPLE__
|
||||
SEL boundsSelector = sel_registerName("bounds");
|
||||
CGRect (*boundsMsgSend)(id, SEL) = (CGRect (*)(id, SEL))objc_msgSend;
|
||||
CGRect bounds = boundsMsgSend((id)(*((char **)v->ui)), boundsSelector);
|
||||
CGFloat width = bounds.size.width;
|
||||
CGFloat height = bounds.size.height;
|
||||
size->right = width;
|
||||
size->bottom = height;
|
||||
# endif
|
||||
# ifdef _WIN32
|
||||
RECT rect;
|
||||
if (GetWindowRect((HWND)*((char **)v->ui), &rect)) {
|
||||
size->right = rect.right - rect.left;
|
||||
size->bottom = rect.bottom - rect.top;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
if (!v->ui || size->right < 1 || size->bottom < 1) {
|
||||
uint32_t width, height;
|
||||
plugin_ui_get_default_size(&width, &height);
|
||||
size->right = width;
|
||||
size->bottom = height;
|
||||
}
|
||||
TRACE(" %u x %u\n", size->right, size->bottom);
|
||||
return Steinberg_kResultTrue;
|
||||
}
|
||||
|
||||
static Steinberg_tresult plugViewOnSize(void* thisInterface, struct Steinberg_ViewRect* newSize) {
|
||||
TRACE("plugView onSize %p\n", thisInterface);
|
||||
TRACE("plugView onSize %p %d %d\n", thisInterface, newSize->right - newSize->left, newSize->bottom - newSize->top);
|
||||
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||
// TODO: if not resizable by both user and plugin just return false
|
||||
if (!v->ui)
|
||||
@ -1396,23 +1440,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 +1541,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;
|
||||
}
|
||||
@ -1652,7 +1696,7 @@ void TCharToD(Steinberg_Vst_TChar* s, double *v) {
|
||||
static Steinberg_tresult controllerGetParamValueByString(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_TChar* string, Steinberg_Vst_ParamValue* valueNormalized) {
|
||||
(void)thisInterface;
|
||||
|
||||
TRACE("controller get param value by string\n");
|
||||
TRACE("controller get param value by string %d %s \n", parameterGetIndexById(id), string);
|
||||
int pi = parameterGetIndexById(id);
|
||||
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
||||
return Steinberg_kResultFalse;
|
||||
@ -1665,7 +1709,7 @@ static Steinberg_tresult controllerGetParamValueByString(void* thisInterface, St
|
||||
static Steinberg_Vst_ParamValue controllerNormalizedParamToPlain(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized) {
|
||||
(void)thisInterface;
|
||||
|
||||
TRACE("controller normalized param to plain\n");
|
||||
TRACE("controller normalized param to plain %d %f\n", parameterGetIndexById(id), valueNormalized);
|
||||
int pi = parameterGetIndexById(id);
|
||||
return pi >= DATA_PRODUCT_PARAMETERS_N ? valueNormalized : parameterMap(pi, valueNormalized);
|
||||
}
|
||||
@ -1673,13 +1717,13 @@ static Steinberg_Vst_ParamValue controllerNormalizedParamToPlain(void* thisInter
|
||||
static Steinberg_Vst_ParamValue controllerPlainParamToNormalized(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue plainValue) {
|
||||
(void)thisInterface;
|
||||
|
||||
TRACE("controller plain param to normalized\n");
|
||||
TRACE("controller plain param to normalized %d %f\n", parameterGetIndexById(id), plainValue);
|
||||
int pi = parameterGetIndexById(id);
|
||||
return pi >= DATA_PRODUCT_PARAMETERS_N ? plainValue : parameterUnmap(pi, plainValue);
|
||||
}
|
||||
|
||||
static Steinberg_Vst_ParamValue controllerGetParamNormalized(void* thisInterface, Steinberg_Vst_ParamID id) {
|
||||
TRACE("controller get param normalized\n");
|
||||
TRACE("controller get param normalized %d \n", parameterGetIndexById(id));
|
||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
||||
int pi = parameterGetIndexById(id);
|
||||
@ -1696,7 +1740,7 @@ static Steinberg_Vst_ParamValue controllerGetParamNormalized(void* thisInterface
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerSetParamNormalized(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue value) {
|
||||
TRACE("controller set param normalized\n");
|
||||
TRACE("controller set param normalized %d %f\n", parameterGetIndexById(id), value);
|
||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
int pi = parameterGetIndexById(id);
|
||||
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
||||
@ -1781,28 +1825,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 +1892,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 +1939,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 +2171,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 };
|
||||
|
||||
|
@ -67,4 +67,5 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
<head>
|
||||
<title>{{=it.product.name}}</title>
|
||||
<script type="module">
|
||||
import * as demo from "./{{=it.product.bundleName}}.js";
|
||||
import * as demo from "./{{=it.product.bundleName}}/module.js";
|
||||
window.demo = demo;
|
||||
</script>
|
||||
<script>
|
||||
@ -212,7 +212,7 @@ window.addEventListener("load", function (e) {
|
||||
module = new demo.Module();
|
||||
if (!midi && hasMidiInput)
|
||||
midi = await navigator.requestMIDIAccess();
|
||||
await module.init(audioCtx, "{{=it.product.bundleName}}_processor.js", "{{=it.product.bundleName}}.wasm");
|
||||
await module.init(audioCtx, "{{=it.product.bundleName}}/processor.js", "{{=it.product.bundleName}}/module.wasm");
|
||||
node = new demo.Node(module);
|
||||
node.connect(audioCtx.destination, audioOutputIndex);
|
||||
|
||||
|
@ -72,27 +72,30 @@ CXX_SRCS := $(COMMON_DIR)/src/new.cpp $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
endif
|
||||
|
||||
ALL := build/web/$(BUNDLE_NAME).wasm build/web/$(BUNDLE_NAME)_processor.js build/web/$(BUNDLE_NAME).js
|
||||
BUNDLE_DATA_PATH := build/web
|
||||
BUNDLE_BIN_PATH := build/web
|
||||
|
||||
ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
||||
|
||||
-include $(COMMON_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/web/$(BUNDLE_NAME).wasm: $(C_OBJS) | build/web
|
||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) | build/web/$(BUNDLE_NAME)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
else
|
||||
build/web/$(BUNDLE_NAME).wasm: $(C_OBJS) $(CXX_OBJS) | build/web
|
||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) $(CXX_OBJS) | build/web/$(BUNDLE_NAME)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
endif
|
||||
|
||||
build/web/$(BUNDLE_NAME)_processor.js: $(DATA_DIR)/src/processor.js | build/web
|
||||
build/web/$(BUNDLE_NAME)/processor.js: $(DATA_DIR)/res/processor.js | build/web/$(BUNDLE_NAME)
|
||||
cp $^ $@
|
||||
|
||||
build/web/$(BUNDLE_NAME).js: $(DATA_DIR)/src/module.js | build/web
|
||||
build/web/$(BUNDLE_NAME)/module.js: $(DATA_DIR)/res/module.js | build/web/$(BUNDLE_NAME)
|
||||
cp $^ $@
|
||||
|
||||
build/web build/obj:
|
||||
build/obj build/web build/web/$(BUNDLE_NAME):
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
|
@ -18,17 +18,17 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.web_make?.cflags ?? ""}}
|
||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.web_make?.cflags ?? ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.web_make?.cxxflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.web_make?.ldflags ?? ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.web_make?.ldflags ?? ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.web_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.web_make?.cxxSrcs ?? ""}}
|
||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.web_make?.cSrcs ?? ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.web_make?.cxxSrcs ?? ""}}
|
||||
|
||||
COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||
DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||
PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
|
@ -18,17 +18,17 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.length}}
|
||||
#define DATA_PRODUCT_PARAMETERS_OUTPUT_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.length}}
|
||||
#define DATA_PRODUCT_PARAMETERS_OUTPUT_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
||||
|
||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||
static struct {
|
||||
char out;
|
||||
float def;
|
||||
char out;
|
||||
float def;
|
||||
} param_data[DATA_PRODUCT_PARAMETERS_N] = {
|
||||
{{~it.product.parameters :p}}
|
||||
{
|
||||
|
@ -29,19 +29,19 @@
|
||||
#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 +51,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);
|
||||
|
||||
|
@ -18,14 +18,19 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
var buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||
var parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||
const buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||
const parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||
|
||||
var busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
||||
var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
||||
const busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
||||
const busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
||||
|
||||
var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||
var nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||
const nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||
const nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||
|
||||
let cpu_meter = 0.0;
|
||||
|
||||
// performance is not available, and there's no better option than Date atm
|
||||
const now = Date.now;
|
||||
|
||||
class Processor extends AudioWorkletProcessor {
|
||||
constructor(options) {
|
||||
@ -71,6 +76,8 @@ class Processor extends AudioWorkletProcessor {
|
||||
}
|
||||
|
||||
process(inputs, outputs, params) {
|
||||
const processTimeStart = now();
|
||||
|
||||
for (var i = 0; i < this.parametersIn.length; i++) {
|
||||
var index = this.parametersIn[i].index;
|
||||
var parameter = parameters[index];
|
||||
@ -141,7 +148,11 @@ class Processor extends AudioWorkletProcessor {
|
||||
|
||||
for (var i = 0; i < this.parametersOut.length; i++) {
|
||||
var index = this.parametersOut[i].index;
|
||||
var value = this.parametersOutValues[i];
|
||||
var value;
|
||||
if (parameters[index].isCpumeter)
|
||||
value = cpu_meter;
|
||||
else
|
||||
value = this.parametersOutValues[i];
|
||||
if (value != this.parametersOut[i].value) {
|
||||
this.paramOutChangeMsg.index = index;
|
||||
this.paramOutChangeMsg.value = value;
|
||||
@ -149,6 +160,9 @@ class Processor extends AudioWorkletProcessor {
|
||||
this.parametersOut[i].value = value;
|
||||
}
|
||||
}
|
||||
const processTimeEnd = now();
|
||||
const processTimeMs = processTimeEnd - processTimeStart;
|
||||
cpu_meter = cpu_meter * 0.99 + (processTimeMs * 0.128 / sampleRate) * 0.01; // TODO: something better than 0.99?
|
||||
|
||||
return true; // because Chrome sucks: https://bugs.chromium.org/p/chromium/issues/detail?id=921354
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ extern unsigned char __heap_base;
|
||||
typedef struct _header {
|
||||
struct _header *next;
|
||||
struct _header *prev;
|
||||
char free;
|
||||
char free;
|
||||
} header;
|
||||
|
||||
static char inited = 0;
|
||||
|
@ -29,6 +29,6 @@ module.exports = function (data, api) {
|
||||
api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`);
|
||||
api.copyFile(`src${sep}processor.c`, `src${sep}processor.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
api.generateFileFromTemplateFile(`src${sep}processor.js`, `src${sep}processor.js`, data);
|
||||
api.generateFileFromTemplateFile(`src${sep}module.js`, `src${sep}module.js`, data);
|
||||
api.generateFileFromTemplateFile(`src${sep}processor.js`, `res${sep}processor.js`, data);
|
||||
api.generateFileFromTemplateFile(`src${sep}module.js`, `res${sep}module.js`, data);
|
||||
};
|
||||
|
@ -1,21 +1,21 @@
|
||||
{
|
||||
"android_make": {
|
||||
"cxxflags": "-I../../../miniaudio",
|
||||
"keyStore": "keystore.jks",
|
||||
"keyAlias": "androidkey",
|
||||
"storePass": "android",
|
||||
"keyPass": "android",
|
||||
"sdkDir": "${HOME}/Android/Sdk",
|
||||
"ndkVersion": "25.2.9519653",
|
||||
"buildToolsVersion": "34.0.0",
|
||||
"androidxDir": "${HOME}/Android/androidx",
|
||||
"kotlinDir": "${HOME}/Android/kotlin",
|
||||
"androidVersion": "34",
|
||||
"androidxCoreVersion": "1.10.1",
|
||||
"androidxLifecycleCommonVersion": "2.6.1",
|
||||
"androidxVersionedparcelableVersion": "1.1.1",
|
||||
"kotlinStdlibVersion": "1.9.0",
|
||||
"kotlinxCoroutinesCoreVersion": "1.7.3",
|
||||
"kotlinxCoroutinesCoreJVMVersion": "1.7.3"
|
||||
"cxxflags" : "-I../../../miniaudio",
|
||||
"keyStore" : "keystore.jks",
|
||||
"keyAlias" : "androidkey",
|
||||
"storePass" : "android",
|
||||
"keyPass" : "android",
|
||||
"sdkDir" : "${HOME}/Android/Sdk",
|
||||
"ndkVersion" : "27.0.11902837",
|
||||
"buildToolsVersion" : "35.0.0",
|
||||
"androidxDir" : "${HOME}/Android/androidx",
|
||||
"kotlinDir" : "${HOME}/Android/kotlin",
|
||||
"androidVersion" : "35",
|
||||
"androidxCoreVersion" : "1.13.1",
|
||||
"androidxLifecycleCommonVersion" : "2.8.3",
|
||||
"androidxVersionedparcelableVersion" : "1.2.0",
|
||||
"kotlinStdlibVersion" : "2.0.0",
|
||||
"kotlinxCoroutinesCoreVersion" : "1.8.0",
|
||||
"kotlinxCoroutinesCoreJVMVersion" : "1.8.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"android": {
|
||||
"javaPackageName": "com.example.tibia_test"
|
||||
"javaPackageName" : "com.example.tibia_test"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"cmd_make": {
|
||||
"tinywavDir": "../../../tinywav",
|
||||
"midiParserDir": "../../../midi-parser"
|
||||
"tinywavDir" : "../../../tinywav",
|
||||
"midiParserDir" : "../../../midi-parser"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"company": {
|
||||
"name": "Example company",
|
||||
"url": "https://www.example.com/",
|
||||
"email": "info@example.com"
|
||||
"name": "Example company",
|
||||
"url": "https://www.example.com/",
|
||||
"email": "info@example.com",
|
||||
"domain": "com.example"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"daisy_seed_make": {
|
||||
"libdaisyDir": "../../../libDaisy"
|
||||
"libdaisyDir" : "../../../libDaisy"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"daisy_seed": {
|
||||
"parameterPins": [ 15, 16, 17, 18, 22 ]
|
||||
"parameterPins" : [ 15, 16, 17, 18, 22 ]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ios_make": {
|
||||
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
||||
"deploymentTarget": 16.6
|
||||
"headerSearchPaths" : [ "../../../../../miniaudio" ],
|
||||
"deploymentTarget" : 16.6
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"ios": {
|
||||
"productBundleIdentifier": "com.example.tibia-test"
|
||||
"productBundleIdentifier" : "com.example.tibia-test"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"lv2_make": {
|
||||
"cflags": "$(shell pkg-config --cflags pugl-cairo-0 pugl-0 cairo)",
|
||||
"ldflags": "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
||||
"cflags" : "$(shell pkg-config --cflags pugl-cairo-0 pugl-0 cairo)",
|
||||
"ldflags" : "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,19 @@
|
||||
*/
|
||||
|
||||
typedef struct plugin {
|
||||
float sample_rate;
|
||||
size_t delay_line_length;
|
||||
float sample_rate;
|
||||
size_t delay_line_length;
|
||||
|
||||
float gain;
|
||||
float delay;
|
||||
float cutoff;
|
||||
char bypass;
|
||||
float gain;
|
||||
float delay;
|
||||
float cutoff;
|
||||
char bypass;
|
||||
|
||||
float * delay_line;
|
||||
size_t delay_line_cur;
|
||||
float z1;
|
||||
float cutoff_k;
|
||||
float yz1;
|
||||
float *delay_line;
|
||||
size_t delay_line_cur;
|
||||
float z1;
|
||||
float cutoff_k;
|
||||
float yz1;
|
||||
} plugin;
|
||||
|
||||
static void plugin_init(plugin *instance, plugin_callbacks *cbs) {
|
||||
|
@ -132,6 +132,24 @@
|
||||
"list": false,
|
||||
"unit": "",
|
||||
"map": "linear"
|
||||
},
|
||||
{
|
||||
"name": "cpu",
|
||||
"shortName": "cpu",
|
||||
"id": "cpu",
|
||||
"direction": "output",
|
||||
"isBypass": false,
|
||||
"isLatency": false,
|
||||
"isCpumeter": true,
|
||||
"defaultValue": 0.0,
|
||||
"minimum": 0.0,
|
||||
"maximum": 1.0,
|
||||
"toggled": false,
|
||||
"optional": false,
|
||||
"integer": false,
|
||||
"list": false,
|
||||
"unit": "",
|
||||
"map": "linear"
|
||||
}
|
||||
],
|
||||
"ui": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"vst3_make": {
|
||||
"cflags": "-I../../../vst3_c_api $(shell pkg-config --cflags pugl-cairo-0)",
|
||||
"ldflags": "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
||||
"cflags" : "-I../../../vst3_c_api $(shell pkg-config --cflags pugl-cairo-0)",
|
||||
"ldflags" : "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user