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
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
ios: data.h, index.html
|
||||||
type:
|
type:
|
||||||
"audio" or "midi", required
|
"audio" or "midi", required
|
||||||
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
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
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
ios: data.h, index.html
|
||||||
channels:
|
channels:
|
||||||
"mono" or "stereo", audio type only, required
|
"mono" or "stereo", audio type only, required
|
||||||
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
||||||
@ -100,7 +100,7 @@ product {
|
|||||||
web: AudioWorkletNode.outputChannelCount - lots of implications
|
web: AudioWorkletNode.outputChannelCount - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
ios: data.h
|
||||||
sidechain:
|
sidechain:
|
||||||
bus is not part of main audio path (sidechain)? boolean, default false
|
bus is not part of main audio path (sidechain)? boolean, default false
|
||||||
VST3: BusInfo busType
|
VST3: BusInfo busType
|
||||||
@ -108,6 +108,7 @@ product {
|
|||||||
web: web-demo choice of audio I/O buses
|
web: web-demo choice of audio I/O buses
|
||||||
cmd: choice of audio I/O buses
|
cmd: choice of audio I/O buses
|
||||||
android: choice of audio I/O buses
|
android: choice of audio I/O buses
|
||||||
|
ios: choice of audio I/O buses
|
||||||
cv:
|
cv:
|
||||||
bus is control voltage audio-rate? boolean, audio type only, default false
|
bus is control voltage audio-rate? boolean, audio type only, default false
|
||||||
VST3: BusInfo flags
|
VST3: BusInfo flags
|
||||||
@ -167,7 +168,7 @@ product {
|
|||||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
ios: data.h, index.html
|
||||||
isBypass:
|
isBypass:
|
||||||
parameter is bypass/enabled? boolean - lots of implications, default false
|
parameter is bypass/enabled? boolean - lots of implications, default false
|
||||||
VST3: ParameterInfo, controller get/set parameter/state
|
VST3: ParameterInfo, controller get/set parameter/state
|
||||||
@ -182,8 +183,16 @@ product {
|
|||||||
LV2: manifest.ttl lv2:port, TBD round output value
|
LV2: manifest.ttl lv2:port, TBD round output value
|
||||||
web: not (yet) used
|
web: not (yet) used
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
|
ios: not used
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
ios: not (yet) used
|
isCpumeter:
|
||||||
|
parameter is output cpu meter? boolean. It must be an output parameter. It is handled within the wrappers, and not by the plugin user code
|
||||||
|
VST3: data.h, vst3.c
|
||||||
|
LV2: data.h, lv2.c
|
||||||
|
web: processor.js
|
||||||
|
cmd: TODO
|
||||||
|
android: data.h jni.cpp
|
||||||
|
ios: data.h native.mm
|
||||||
defaultValue:
|
defaultValue:
|
||||||
default value, number, mapped, required for non-bypass
|
default value, number, mapped, required for non-bypass
|
||||||
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#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_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_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_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_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_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}}
|
||||||
@ -80,6 +80,11 @@ static struct {
|
|||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||||
|
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
||||||
|
@ -46,10 +46,13 @@
|
|||||||
|
|
||||||
#if NUM_MIDI_INPUTS > 0
|
#if NUM_MIDI_INPUTS > 0
|
||||||
# include <vector>
|
# include <vector>
|
||||||
|
|
||||||
# include <amidi/AMidi.h>
|
# include <amidi/AMidi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
# include "fatica.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#include <pmmintrin.h>
|
#include <pmmintrin.h>
|
||||||
@ -57,29 +60,29 @@
|
|||||||
|
|
||||||
static ma_device device;
|
static ma_device device;
|
||||||
static plugin instance;
|
static plugin instance;
|
||||||
static void * mem;
|
static void *mem;
|
||||||
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||||
float zero[BLOCK_SIZE];
|
float zero[BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_IN > 0
|
#if NUM_CHANNELS_IN > 0
|
||||||
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
||||||
float * x_in[NUM_CHANNELS_IN];
|
float *x_in[NUM_CHANNELS_IN];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_IN > 0
|
#if NUM_ALL_CHANNELS_IN > 0
|
||||||
const float * x[NUM_ALL_CHANNELS_IN];
|
const float *x[NUM_ALL_CHANNELS_IN];
|
||||||
#else
|
#else
|
||||||
const float ** x;
|
const float **x;
|
||||||
#endif
|
#endif
|
||||||
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
||||||
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_OUT > 0
|
||||||
float * y_out[NUM_CHANNELS_OUT];
|
float *y_out[NUM_CHANNELS_OUT];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_OUT > 0
|
#if NUM_ALL_CHANNELS_OUT > 0
|
||||||
float * y[NUM_ALL_CHANNELS_OUT];
|
float *y[NUM_ALL_CHANNELS_OUT];
|
||||||
#else
|
#else
|
||||||
float ** y;
|
float **y;
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
@ -96,10 +99,18 @@ std::vector<PortData> midiPorts;
|
|||||||
# define MIDI_BUFFER_SIZE 1024
|
# define MIDI_BUFFER_SIZE 1024
|
||||||
uint8_t midiBuffer[MIDI_BUFFER_SIZE];
|
uint8_t midiBuffer[MIDI_BUFFER_SIZE];
|
||||||
#endif
|
#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) {
|
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
||||||
(void)pDevice;
|
(void)pDevice;
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeStart = fatica_time_process();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -116,8 +127,15 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
if (mutex.try_lock()) {
|
if (mutex.try_lock()) {
|
||||||
# if PARAMETERS_N > 0
|
# if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
if (param_data[i].out)
|
if (param_data[i].out) {
|
||||||
|
# ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
if (i == PARAM_OUT_CPU_INDEX) {
|
||||||
|
param_values_prev[i] = param_values[i] = cpu_meter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
||||||
|
}
|
||||||
else if (param_values_prev[i] != param_values[i]) {
|
else if (param_values_prev[i] != param_values[i]) {
|
||||||
plugin_set_parameter(&instance, i, param_values[i]);
|
plugin_set_parameter(&instance, i, param_values[i]);
|
||||||
param_values_prev[i] = param_values[i];
|
param_values_prev[i] = param_values[i];
|
||||||
@ -182,6 +200,11 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeEnd = fatica_time_process();
|
||||||
|
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -243,6 +266,10 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
sample_rate = (float)device.sampleRate;
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t req = plugin_mem_req(&instance);
|
size_t req = plugin_mem_req(&instance);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
mem = malloc(req);
|
mem = malloc(req);
|
||||||
|
@ -27,4 +27,5 @@ module.exports = function (data, api) {
|
|||||||
api.copyFile(`src${sep}jni.cpp`, `src${sep}jni.cpp`);
|
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}MainActivity.java`, `src${sep}MainActivity.java`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||||
|
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
||||||
};
|
};
|
||||||
|
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
|
#ifndef PLUGIN_API_H
|
||||||
#define PLUGIN_API_H
|
#define PLUGIN_API_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void * handle;
|
void *handle;
|
||||||
const char * format;
|
const char *format;
|
||||||
const char * (*get_bindir)(void *handle);
|
|
||||||
|
const char * (*get_bindir) (void *handle);
|
||||||
const char * (*get_datadir)(void *handle);
|
const char * (*get_datadir)(void *handle);
|
||||||
} plugin_callbacks;
|
} plugin_callbacks;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void * handle;
|
void *handle;
|
||||||
const char * format;
|
const char *format;
|
||||||
const char * (*get_bindir)(void *handle);
|
|
||||||
const char * (*get_datadir)(void *handle);
|
const char * (*get_bindir) (void *handle);
|
||||||
|
const char * (*get_datadir) (void *handle);
|
||||||
void (*set_parameter_begin)(void *handle, size_t index);
|
void (*set_parameter_begin)(void *handle, size_t index);
|
||||||
void (*set_parameter)(void *handle, size_t index, float value);
|
void (*set_parameter) (void *handle, size_t index, float value);
|
||||||
void (*set_parameter_end)(void *handle, size_t index);
|
void (*set_parameter_end) (void *handle, size_t index);
|
||||||
} plugin_ui_callbacks;
|
} plugin_ui_callbacks;
|
||||||
|
|
||||||
{{?it.product.parameters.length > 0}}
|
{{?it.product.parameters.length > 0}}
|
||||||
@ -43,6 +47,8 @@ enum {
|
|||||||
{{~it.product.parameters :p}}
|
{{~it.product.parameters :p}}
|
||||||
plugin_parameter_{{=p.id}},
|
plugin_parameter_{{=p.id}},
|
||||||
{{~}}
|
{{~}}
|
||||||
|
|
||||||
|
plugin_parameter_count
|
||||||
};
|
};
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ SOURCES := \
|
|||||||
$(COMMON_DIR)/src/native.mm \
|
$(COMMON_DIR)/src/native.mm \
|
||||||
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
||||||
$(PLUGIN_DIR)/plugin.h \
|
$(PLUGIN_DIR)/plugin.h \
|
||||||
|
$(PLUGIN_DIR)/fatica.h \
|
||||||
$(C_SRCS_EXTRA) \
|
$(C_SRCS_EXTRA) \
|
||||||
$(CXX_SRCS_EXTRA) \
|
$(CXX_SRCS_EXTRA) \
|
||||||
$(SRCS_EXTRA)
|
$(SRCS_EXTRA)
|
||||||
|
@ -30,6 +30,10 @@ targets:
|
|||||||
type: application
|
type: application
|
||||||
sources:
|
sources:
|
||||||
- path: src
|
- path: src
|
||||||
|
{{?it.ios_make.dependencies}}
|
||||||
|
dependencies: {{~it.ios_make.dependencies :d}}
|
||||||
|
- target: {{=d}}{{~}}
|
||||||
|
{{?}}
|
||||||
settings:
|
settings:
|
||||||
base:
|
base:
|
||||||
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}}
|
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.ios_make?.cSrcs ?? ""}}
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}}
|
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.ios_make?.cxxSrcs ?? ""}}
|
||||||
SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}}
|
SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}}
|
||||||
|
|
||||||
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
@ -80,4 +80,8 @@ static struct {
|
|||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||||
|
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||||
|
{{?}}
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,10 +21,11 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
<title>{{=it.product.name}}</title>
|
<title>{{=it.product.name}}</title>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
function request(data) {
|
function request(data) {
|
||||||
return window.webkit.messageHandlers.listener.postMessage(data);
|
return window.webkit.messageHandlers.listener.postMessage(data);
|
||||||
}
|
}
|
||||||
@ -77,11 +78,12 @@ window.onload = async function () {
|
|||||||
topButtonElem = document.getElementById("topButton");
|
topButtonElem = document.getElementById("topButton");
|
||||||
var paramsElem = document.getElementById("params");
|
var paramsElem = document.getElementById("params");
|
||||||
|
|
||||||
for (var i = 0; i < data.buses.length; i++)
|
for (var i = 0; i < data.buses.length; i++) {
|
||||||
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
||||||
hasAudioPermission = !await needAudioPermission();
|
hasAudioPermission = !await needAudioPermission();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||||
topButtonElem.addEventListener("click", async function () {
|
topButtonElem.addEventListener("click", async function () {
|
||||||
@ -166,17 +168,17 @@ function gotAudioPermission() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#topButton {
|
#topButton {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
background-color: #04aa6d;
|
background-color: #04aa6d;
|
||||||
@ -185,15 +187,15 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.range {
|
.range {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input id="topButton" type="button">
|
<input id="topButton" type="button">
|
||||||
<div id="params"></div>
|
<div id="params"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -25,44 +25,47 @@
|
|||||||
#include "plugin_api.h"
|
#include "plugin_api.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
#include <algorithm>
|
# include <algorithm>
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0
|
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0
|
||||||
#include <mutex>
|
# include <mutex>
|
||||||
#endif
|
#endif
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#define MINIAUDIO_IMPLEMENTATION
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
#define MA_NO_RUNTIME_LINKING
|
#define MA_NO_RUNTIME_LINKING
|
||||||
#include "miniaudio.h"
|
#include "miniaudio.h"
|
||||||
#define BLOCK_SIZE 32
|
#define BLOCK_SIZE 32
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
# include "fatica.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static ma_device device;
|
static ma_device device;
|
||||||
static ma_device_config deviceConfig;
|
static ma_device_config deviceConfig;
|
||||||
char device_inited = 0;
|
char device_inited = 0;
|
||||||
static plugin instance;
|
static plugin instance;
|
||||||
static void * mem;
|
static void *mem;
|
||||||
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||||
float zero[BLOCK_SIZE];
|
float zero[BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_IN > 0
|
#if NUM_CHANNELS_IN > 0
|
||||||
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
||||||
float * x_in[NUM_CHANNELS_IN];
|
float *x_in[NUM_CHANNELS_IN];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_IN > 0
|
#if NUM_ALL_CHANNELS_IN > 0
|
||||||
const float * x[NUM_ALL_CHANNELS_IN];
|
const float *x[NUM_ALL_CHANNELS_IN];
|
||||||
#else
|
#else
|
||||||
const float ** x;
|
const float **x;
|
||||||
#endif
|
#endif
|
||||||
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
||||||
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_OUT > 0
|
||||||
float * y_out[NUM_CHANNELS_OUT];
|
float *y_out[NUM_CHANNELS_OUT];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_OUT > 0
|
#if NUM_ALL_CHANNELS_OUT > 0
|
||||||
float * y[NUM_ALL_CHANNELS_OUT];
|
float *y[NUM_ALL_CHANNELS_OUT];
|
||||||
#else
|
#else
|
||||||
float ** y;
|
float **y;
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
@ -78,10 +81,18 @@ MIDIPortRef midiPort = NULL;
|
|||||||
uint8_t midiBuffer[MIDIBUFFERLEN];
|
uint8_t midiBuffer[MIDIBUFFERLEN];
|
||||||
int midiBuffer_i = 0;
|
int midiBuffer_i = 0;
|
||||||
#endif
|
#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) {
|
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
||||||
(void)pDevice;
|
(void)pDevice;
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeStart = fatica_time_process();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -92,8 +103,15 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
if (mutex.try_lock()) {
|
if (mutex.try_lock()) {
|
||||||
# if PARAMETERS_N > 0
|
# if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
if (param_data[i].out)
|
if (param_data[i].out) {
|
||||||
|
# ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
if (i == PARAM_OUT_CPU_INDEX) {
|
||||||
|
param_values_prev[i] = param_values[i] = cpu_meter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
||||||
|
}
|
||||||
else if (param_values_prev[i] != param_values[i]) {
|
else if (param_values_prev[i] != param_values[i]) {
|
||||||
plugin_set_parameter(&instance, i, param_values[i]);
|
plugin_set_parameter(&instance, i, param_values[i]);
|
||||||
param_values_prev[i] = param_values[i];
|
param_values_prev[i] = param_values[i];
|
||||||
@ -152,6 +170,11 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
|
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeEnd = fatica_time_process();
|
||||||
|
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (NUM_MIDI_INPUTS > 0)
|
#if (NUM_MIDI_INPUTS > 0)
|
||||||
@ -270,6 +293,9 @@ char audioStart() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
sample_rate = (float)device.sampleRate;
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t req = plugin_mem_req(&instance);
|
size_t req = plugin_mem_req(&instance);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
|
@ -27,4 +27,5 @@ module.exports = function (data, api) {
|
|||||||
api.copyFile(`src${sep}native.mm`, `src${sep}native.mm`);
|
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-Bridging-Header.h`, `src${sep}app-Bridging-Header.h`);
|
||||||
api.copyFile(`src${sep}app.swift`, `src${sep}app.swift`, data);
|
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_DIR := $(BUNDLE_NAME).lv2
|
||||||
|
|
||||||
|
BUNDLE_DATA_PATH := build/$(BUNDLE_DIR)
|
||||||
|
BUNDLE_BIN_PATH := build/$(BUNDLE_DIR)
|
||||||
|
|
||||||
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||||
|
|
||||||
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
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_SRCS := $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
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 > $@
|
cat $^ | sed s/@DLL_SUFFIX@/$(DLL_SUFFIX)/g | sed s/@UI_TYPE@/$(UI_TYPE)/g > $@
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
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)
|
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
else
|
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)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -138,6 +144,9 @@ PERCENT := %
|
|||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
$(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_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
|
@ -20,13 +20,15 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
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 ?? "")}}
|
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
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 ?? ""}}
|
||||||
|
@ -63,6 +63,9 @@ static struct {
|
|||||||
static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
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.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
|
#endif
|
||||||
|
|
||||||
{{?it.lv2.ui}}
|
{{?it.lv2.ui}}
|
||||||
|
@ -52,6 +52,10 @@
|
|||||||
# include <pmmintrin.h>
|
# include <pmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
# include "fatica.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline float clampf(float x, float m, float M) {
|
static inline float clampf(float x, float m, float M) {
|
||||||
return x < m ? m : (x > M ? M : x);
|
return x < m ? m : (x > M ? M : x);
|
||||||
}
|
}
|
||||||
@ -69,16 +73,16 @@ static float adjust_param(size_t index, float value) {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
plugin p;
|
plugin p;
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||||
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
const LV2_Atom_Sequence * x_midi[DATA_PRODUCT_MIDI_INPUTS_N];
|
const LV2_Atom_Sequence *x_midi[DATA_PRODUCT_MIDI_INPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
LV2_Atom_Sequence * y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N];
|
LV2_Atom_Sequence *y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||||
float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N];
|
float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N];
|
||||||
@ -86,13 +90,17 @@ typedef struct {
|
|||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
void * mem;
|
void *mem;
|
||||||
char * bundle_path;
|
char *bundle_path;
|
||||||
LV2_Log_Logger logger;
|
LV2_Log_Logger logger;
|
||||||
LV2_URID_Map * map;
|
LV2_URID_Map *map;
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
LV2_URID uri_midi_MidiEvent;
|
LV2_URID uri_midi_MidiEvent;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
float cpu_meter;
|
||||||
|
float sample_rate;
|
||||||
|
#endif
|
||||||
} plugin_instance;
|
} plugin_instance;
|
||||||
|
|
||||||
static const char * get_bundle_path_cb(void *handle) {
|
static const char * get_bundle_path_cb(void *handle) {
|
||||||
@ -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++)
|
for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++)
|
||||||
instance->c[i] = NULL;
|
instance->c[i] = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
instance->cpu_meter = 0.f;
|
||||||
|
instance->sample_rate = sample_rate;
|
||||||
|
#endif
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
|
|
||||||
@ -230,6 +242,10 @@ static void activate(LV2_Handle instance) {
|
|||||||
static void run(LV2_Handle instance, uint32_t sample_count) {
|
static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||||
plugin_instance * i = (plugin_instance *)instance;
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeStart = fatica_time_process();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -284,9 +300,16 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
|
||||||
uint32_t k = param_out_index[j];
|
uint32_t k = param_out_index[j];
|
||||||
if (i->c[k] != NULL)
|
if (i->c[k] != NULL) {
|
||||||
|
# ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
if (k == PARAM_OUT_CPU_INDEX) {
|
||||||
|
*i->c[k] = i->cpu_meter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
*i->c[k] = plugin_get_parameter(&i->p, k);
|
*i->c[k] = plugin_get_parameter(&i->p, k);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
(void)plugin_get_parameter;
|
(void)plugin_get_parameter;
|
||||||
#endif
|
#endif
|
||||||
@ -297,6 +320,12 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeEnd = fatica_time_process();
|
||||||
|
fatica_cpu_meter(&i->cpu_meter, processTimeStart, processTimeEnd, sample_count, i->sample_rate);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(LV2_Handle instance) {
|
static void cleanup(LV2_Handle instance) {
|
||||||
@ -325,8 +354,8 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
|||||||
|
|
||||||
#ifdef DATA_UI
|
#ifdef DATA_UI
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin_ui * ui;
|
plugin_ui *ui;
|
||||||
char * bundle_path;
|
char *bundle_path;
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
LV2UI_Write_Function write;
|
LV2UI_Write_Function write;
|
||||||
LV2UI_Controller controller;
|
LV2UI_Controller controller;
|
||||||
|
@ -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.generateFileFromTemplateFile(`data${sep}manifest.ttl.in`, `data${sep}manifest.ttl.in`, data);
|
||||||
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
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_DIR := Contents/$(PLATFORM)
|
||||||
DLL_FILE := $(DLL_DIR)/$(BUNDLE_NAME)$(DLL_SUFFIX)
|
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_SRCS := $(COMMON_DIR)/src/vst3.c $(C_SRCS_EXTRA)
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
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_SRCS := $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
@ -100,10 +106,10 @@ endif
|
|||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
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)
|
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
else
|
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)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -118,6 +124,9 @@ endif
|
|||||||
build/$(BUNDLE_DIR)/Contents build/$(BUNDLE_DIR)/$(DLL_DIR) build/obj:
|
build/$(BUNDLE_DIR)/Contents build/$(BUNDLE_DIR)/$(DLL_DIR) build/obj:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
|
${BUNDLE_DATA_PATH}:
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
@ -160,6 +169,9 @@ PERCENT := %
|
|||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
$(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_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
|
@ -20,15 +20,17 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
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 ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
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 ?? ""}}
|
||||||
|
|
||||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
||||||
|
@ -211,6 +211,10 @@ static struct {
|
|||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
||||||
|
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,6 +53,10 @@
|
|||||||
#include <pmmintrin.h>
|
#include <pmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
# include "fatica.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// COM in C doc:
|
// COM in C doc:
|
||||||
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
|
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
|
||||||
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
|
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
|
||||||
@ -182,21 +186,21 @@ static double parameterAdjust(int i, double v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct pluginInstance {
|
typedef struct pluginInstance {
|
||||||
Steinberg_Vst_IComponentVtbl * vtblIComponent;
|
Steinberg_Vst_IComponentVtbl *vtblIComponent;
|
||||||
Steinberg_Vst_IAudioProcessorVtbl * vtblIAudioProcessor;
|
Steinberg_Vst_IAudioProcessorVtbl *vtblIAudioProcessor;
|
||||||
Steinberg_Vst_IProcessContextRequirementsVtbl * vtblIProcessContextRequirements;
|
Steinberg_Vst_IProcessContextRequirementsVtbl *vtblIProcessContextRequirements;
|
||||||
Steinberg_uint32 refs;
|
Steinberg_uint32 refs;
|
||||||
Steinberg_FUnknown * context;
|
Steinberg_FUnknown *context;
|
||||||
plugin p;
|
plugin p;
|
||||||
float sampleRate;
|
float sampleRate;
|
||||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||||
float parameters[DATA_PRODUCT_PARAMETERS_N];
|
float parameters[DATA_PRODUCT_PARAMETERS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N > 0
|
#if DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N > 0
|
||||||
const float * inputs[DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N];
|
const float *inputs[DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N > 0
|
#if DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N > 0
|
||||||
float * outputs[DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N];
|
float *outputs[DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N + DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N + DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
// see https://github.com/steinbergmedia/vst3sdk/issues/128
|
// see https://github.com/steinbergmedia/vst3sdk/issues/128
|
||||||
@ -214,7 +218,10 @@ typedef struct pluginInstance {
|
|||||||
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N];
|
char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N];
|
||||||
#endif
|
#endif
|
||||||
void * mem;
|
void *mem;
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
float cpu_meter;
|
||||||
|
#endif
|
||||||
} pluginInstance;
|
} pluginInstance;
|
||||||
|
|
||||||
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
|
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
|
||||||
@ -316,6 +323,9 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
p->mem = NULL;
|
p->mem = NULL;
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
p->cpu_meter = 0.f;
|
||||||
|
#endif
|
||||||
return Steinberg_kResultOk;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +342,7 @@ static Steinberg_tresult pluginTerminate(void *thisInterface) {
|
|||||||
static Steinberg_tresult pluginGetControllerClassId(void *thisInterface, Steinberg_TUID classId) {
|
static Steinberg_tresult pluginGetControllerClassId(void *thisInterface, Steinberg_TUID classId) {
|
||||||
(void)thisInterface;
|
(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) {
|
if (classId != NULL) {
|
||||||
memcpy(classId, dataControllerCID, sizeof(Steinberg_TUID));
|
memcpy(classId, dataControllerCID, sizeof(Steinberg_TUID));
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
@ -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) {
|
static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst_ProcessData* data) {
|
||||||
TRACE("plugin IAudioProcessor process\n");
|
TRACE("plugin IAudioProcessor process\n");
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeStart = fatica_time_process();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -824,7 +838,13 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst
|
|||||||
for (Steinberg_int32 i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) {
|
for (Steinberg_int32 i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) {
|
||||||
if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly))
|
if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly))
|
||||||
continue;
|
continue;
|
||||||
float v = plugin_get_parameter(&p->p, parameterData[i].index);
|
float v;
|
||||||
|
# ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
if (i == PARAM_OUT_CPU_INDEX)
|
||||||
|
v = p->cpu_meter;
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
v = plugin_get_parameter(&p->p, parameterData[i].index);
|
||||||
if (v == p->parameters[i])
|
if (v == p->parameters[i])
|
||||||
continue;
|
continue;
|
||||||
p->parameters[i] = v;
|
p->parameters[i] = v;
|
||||||
@ -848,6 +868,11 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst
|
|||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAM_OUT_CPU_INDEX
|
||||||
|
const unsigned long long processTimeEnd = fatica_time_process();
|
||||||
|
fatica_cpu_meter(&p->cpu_meter, processTimeStart, processTimeEnd, data->numSamples, p->sampleRate);
|
||||||
|
#endif
|
||||||
|
|
||||||
return Steinberg_kResultOk;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,19 +936,19 @@ static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRe
|
|||||||
typedef struct plugView plugView;
|
typedef struct plugView plugView;
|
||||||
|
|
||||||
typedef struct controller {
|
typedef struct controller {
|
||||||
Steinberg_Vst_IEditControllerVtbl * vtblIEditController;
|
Steinberg_Vst_IEditControllerVtbl *vtblIEditController;
|
||||||
Steinberg_Vst_IMidiMappingVtbl * vtblIMidiMapping;
|
Steinberg_Vst_IMidiMappingVtbl *vtblIMidiMapping;
|
||||||
#ifdef DATA_UI
|
#ifdef DATA_UI
|
||||||
//Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint;
|
//Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint;
|
||||||
#endif
|
#endif
|
||||||
Steinberg_uint32 refs;
|
Steinberg_uint32 refs;
|
||||||
Steinberg_FUnknown * context;
|
Steinberg_FUnknown *context;
|
||||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N];
|
double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N];
|
||||||
#endif
|
#endif
|
||||||
struct Steinberg_Vst_IComponentHandler * componentHandler;
|
struct Steinberg_Vst_IComponentHandler *componentHandler;
|
||||||
#ifdef DATA_UI
|
#ifdef DATA_UI
|
||||||
plugView ** views;
|
plugView **views;
|
||||||
size_t viewsCount;
|
size_t viewsCount;
|
||||||
#endif
|
#endif
|
||||||
} controller;
|
} controller;
|
||||||
@ -937,9 +962,9 @@ static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController;
|
|||||||
# include <X11/Xlib.h>
|
# include <X11/Xlib.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Steinberg_ITimerHandlerVtbl * vtblITimerHandler;
|
Steinberg_ITimerHandlerVtbl *vtblITimerHandler;
|
||||||
Steinberg_uint32 refs;
|
Steinberg_uint32 refs;
|
||||||
void * data;
|
void *data;
|
||||||
void (*cb)(void *data);
|
void (*cb)(void *data);
|
||||||
} timerHandler;
|
} timerHandler;
|
||||||
|
|
||||||
@ -1008,15 +1033,15 @@ static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = {
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
typedef struct plugView {
|
typedef struct plugView {
|
||||||
Steinberg_IPlugViewVtbl * vtblIPlugView;
|
Steinberg_IPlugViewVtbl *vtblIPlugView;
|
||||||
Steinberg_uint32 refs;
|
Steinberg_uint32 refs;
|
||||||
Steinberg_IPlugFrame * frame;
|
Steinberg_IPlugFrame *frame;
|
||||||
plugin_ui * ui;
|
plugin_ui *ui;
|
||||||
controller * ctrl;
|
controller *ctrl;
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
Steinberg_IRunLoop * runLoop;
|
Steinberg_IRunLoop *runLoop;
|
||||||
timerHandler timer;
|
timerHandler timer;
|
||||||
Display * display;
|
Display *display;
|
||||||
# elif defined(__APPLE__)
|
# elif defined(__APPLE__)
|
||||||
CFRunLoopTimerRef timer;
|
CFRunLoopTimerRef timer;
|
||||||
# elif defined(_WIN32) || defined(__CYGWIN__)
|
# elif defined(_WIN32) || defined(__CYGWIN__)
|
||||||
@ -1104,7 +1129,7 @@ static void plugViewUpdateAllParameters(plugView *view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void plugViewSetParameterBeginCb(void *handle, size_t index) {
|
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
|
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||||
if (index == 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) {
|
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
|
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||||
if (index == 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) {
|
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
|
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||||
if (index == DATA_PARAM_LATENCY_INDEX)
|
if (index == DATA_PARAM_LATENCY_INDEX)
|
||||||
@ -1280,12 +1305,9 @@ static Steinberg_tresult plugViewGetSize(void* thisInterface, struct Steinberg_V
|
|||||||
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||||
size->left = 0;
|
size->left = 0;
|
||||||
size->top = 0;
|
size->top = 0;
|
||||||
if (!v->ui) {
|
size->right = 0;
|
||||||
uint32_t width, height;
|
size->bottom = 0;
|
||||||
plugin_ui_get_default_size(&width, &height);
|
if (v->ui) {
|
||||||
size->right = width;
|
|
||||||
size->bottom = height;
|
|
||||||
} else {
|
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
TRACE(" window %u\n", (Window)(*((char **)v->ui)));
|
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->right = attr.width;
|
||||||
size->bottom = attr.height;
|
size->bottom = attr.height;
|
||||||
# endif
|
# 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);
|
TRACE(" %u x %u\n", size->right, size->bottom);
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Steinberg_tresult plugViewOnSize(void* thisInterface, struct Steinberg_ViewRect* newSize) {
|
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));
|
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||||
// TODO: if not resizable by both user and plugin just return false
|
// TODO: if not resizable by both user and plugin just return false
|
||||||
if (!v->ui)
|
if (!v->ui)
|
||||||
@ -1497,7 +1541,7 @@ static Steinberg_tresult controllerInitialize(void* thisInterface, struct Steinb
|
|||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
for (int i = DATA_PRODUCT_PARAMETERS_N; i < DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N; i += 3) {
|
for (int i = DATA_PRODUCT_PARAMETERS_N; i < DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N; i += 3) {
|
||||||
c->parameters[i] = 0.0;
|
c->parameters[i ] = 0.0;
|
||||||
c->parameters[i + 1] = 0.5;
|
c->parameters[i + 1] = 0.5;
|
||||||
c->parameters[i + 2] = 0.0;
|
c->parameters[i + 2] = 0.0;
|
||||||
}
|
}
|
||||||
@ -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) {
|
static Steinberg_tresult controllerGetParamValueByString(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_TChar* string, Steinberg_Vst_ParamValue* valueNormalized) {
|
||||||
(void)thisInterface;
|
(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);
|
int pi = parameterGetIndexById(id);
|
||||||
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
||||||
return Steinberg_kResultFalse;
|
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) {
|
static Steinberg_Vst_ParamValue controllerNormalizedParamToPlain(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized) {
|
||||||
(void)thisInterface;
|
(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);
|
int pi = parameterGetIndexById(id);
|
||||||
return pi >= DATA_PRODUCT_PARAMETERS_N ? valueNormalized : parameterMap(pi, valueNormalized);
|
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) {
|
static Steinberg_Vst_ParamValue controllerPlainParamToNormalized(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue plainValue) {
|
||||||
(void)thisInterface;
|
(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);
|
int pi = parameterGetIndexById(id);
|
||||||
return pi >= DATA_PRODUCT_PARAMETERS_N ? plainValue : parameterUnmap(pi, plainValue);
|
return pi >= DATA_PRODUCT_PARAMETERS_N ? plainValue : parameterUnmap(pi, plainValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Steinberg_Vst_ParamValue controllerGetParamNormalized(void* thisInterface, Steinberg_Vst_ParamID id) {
|
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
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
||||||
int pi = parameterGetIndexById(id);
|
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) {
|
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
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
int pi = parameterGetIndexById(id);
|
int pi = parameterGetIndexById(id);
|
||||||
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
if (pi >= DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N || pi < 0)
|
||||||
|
@ -67,4 +67,5 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
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>
|
<head>
|
||||||
<title>{{=it.product.name}}</title>
|
<title>{{=it.product.name}}</title>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as demo from "./{{=it.product.bundleName}}.js";
|
import * as demo from "./{{=it.product.bundleName}}/module.js";
|
||||||
window.demo = demo;
|
window.demo = demo;
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
@ -212,7 +212,7 @@ window.addEventListener("load", function (e) {
|
|||||||
module = new demo.Module();
|
module = new demo.Module();
|
||||||
if (!midi && hasMidiInput)
|
if (!midi && hasMidiInput)
|
||||||
midi = await navigator.requestMIDIAccess();
|
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 = new demo.Node(module);
|
||||||
node.connect(audioCtx.destination, audioOutputIndex);
|
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)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
endif
|
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
|
-include $(COMMON_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
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)
|
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
else
|
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)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
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 $^ $@
|
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 $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
build/web build/obj:
|
build/obj build/web build/web/$(BUNDLE_NAME):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -30,15 +30,15 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin p;
|
plugin p;
|
||||||
void * mem;
|
void *mem;
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128];
|
float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128];
|
||||||
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||||
float zero_buf[128];
|
float zero_buf[128];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||||
float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128];
|
float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128];
|
||||||
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
|
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
|
||||||
float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N];
|
float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N];
|
||||||
|
@ -18,14 +18,19 @@
|
|||||||
* File author: Stefano D'Angelo
|
* File author: Stefano D'Angelo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
const buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||||
var parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
const parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||||
|
|
||||||
var busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
const busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
||||||
var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
const busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
||||||
|
|
||||||
var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
const 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 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 {
|
class Processor extends AudioWorkletProcessor {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
@ -71,6 +76,8 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process(inputs, outputs, params) {
|
process(inputs, outputs, params) {
|
||||||
|
const processTimeStart = now();
|
||||||
|
|
||||||
for (var i = 0; i < this.parametersIn.length; i++) {
|
for (var i = 0; i < this.parametersIn.length; i++) {
|
||||||
var index = this.parametersIn[i].index;
|
var index = this.parametersIn[i].index;
|
||||||
var parameter = parameters[index];
|
var parameter = parameters[index];
|
||||||
@ -141,7 +148,11 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
|
|
||||||
for (var i = 0; i < this.parametersOut.length; i++) {
|
for (var i = 0; i < this.parametersOut.length; i++) {
|
||||||
var index = this.parametersOut[i].index;
|
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) {
|
if (value != this.parametersOut[i].value) {
|
||||||
this.paramOutChangeMsg.index = index;
|
this.paramOutChangeMsg.index = index;
|
||||||
this.paramOutChangeMsg.value = value;
|
this.paramOutChangeMsg.value = value;
|
||||||
@ -149,6 +160,9 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
this.parametersOut[i].value = value;
|
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
|
return true; // because Chrome sucks: https://bugs.chromium.org/p/chromium/issues/detail?id=921354
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,6 @@ module.exports = function (data, api) {
|
|||||||
api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`);
|
api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`);
|
||||||
api.copyFile(`src${sep}processor.c`, `src${sep}processor.c`);
|
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}data.h`, `src${sep}data.h`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}processor.js`, `src${sep}processor.js`, data);
|
api.generateFileFromTemplateFile(`src${sep}processor.js`, `res${sep}processor.js`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}module.js`, `src${sep}module.js`, data);
|
api.generateFileFromTemplateFile(`src${sep}module.js`, `res${sep}module.js`, data);
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"android_make": {
|
"android_make": {
|
||||||
"cxxflags": "-I../../../miniaudio",
|
"cxxflags" : "-I../../../miniaudio",
|
||||||
"keyStore": "keystore.jks",
|
"keyStore" : "keystore.jks",
|
||||||
"keyAlias": "androidkey",
|
"keyAlias" : "androidkey",
|
||||||
"storePass": "android",
|
"storePass" : "android",
|
||||||
"keyPass": "android",
|
"keyPass" : "android",
|
||||||
"sdkDir": "${HOME}/Android/Sdk",
|
"sdkDir" : "${HOME}/Android/Sdk",
|
||||||
"ndkVersion": "25.2.9519653",
|
"ndkVersion" : "27.0.11902837",
|
||||||
"buildToolsVersion": "34.0.0",
|
"buildToolsVersion" : "35.0.0",
|
||||||
"androidxDir": "${HOME}/Android/androidx",
|
"androidxDir" : "${HOME}/Android/androidx",
|
||||||
"kotlinDir": "${HOME}/Android/kotlin",
|
"kotlinDir" : "${HOME}/Android/kotlin",
|
||||||
"androidVersion": "34",
|
"androidVersion" : "35",
|
||||||
"androidxCoreVersion": "1.10.1",
|
"androidxCoreVersion" : "1.13.1",
|
||||||
"androidxLifecycleCommonVersion": "2.6.1",
|
"androidxLifecycleCommonVersion" : "2.8.3",
|
||||||
"androidxVersionedparcelableVersion": "1.1.1",
|
"androidxVersionedparcelableVersion" : "1.2.0",
|
||||||
"kotlinStdlibVersion": "1.9.0",
|
"kotlinStdlibVersion" : "2.0.0",
|
||||||
"kotlinxCoroutinesCoreVersion": "1.7.3",
|
"kotlinxCoroutinesCoreVersion" : "1.8.0",
|
||||||
"kotlinxCoroutinesCoreJVMVersion": "1.7.3"
|
"kotlinxCoroutinesCoreJVMVersion" : "1.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"android": {
|
"android": {
|
||||||
"javaPackageName": "com.example.tibia_test"
|
"javaPackageName" : "com.example.tibia_test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"cmd_make": {
|
"cmd_make": {
|
||||||
"tinywavDir": "../../../tinywav",
|
"tinywavDir" : "../../../tinywav",
|
||||||
"midiParserDir": "../../../midi-parser"
|
"midiParserDir" : "../../../midi-parser"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"company": {
|
"company": {
|
||||||
"name": "Example company",
|
"name": "Example company",
|
||||||
"url": "https://www.example.com/",
|
"url": "https://www.example.com/",
|
||||||
"email": "info@example.com"
|
"email": "info@example.com",
|
||||||
|
"domain": "com.example"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"daisy_seed_make": {
|
"daisy_seed_make": {
|
||||||
"libdaisyDir": "../../../libDaisy"
|
"libdaisyDir" : "../../../libDaisy"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"daisy_seed": {
|
"daisy_seed": {
|
||||||
"parameterPins": [ 15, 16, 17, 18, 22 ]
|
"parameterPins" : [ 15, 16, 17, 18, 22 ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ios_make": {
|
"ios_make": {
|
||||||
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
"headerSearchPaths" : [ "../../../../../miniaudio" ],
|
||||||
"deploymentTarget": 16.6
|
"deploymentTarget" : 16.6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ios": {
|
"ios": {
|
||||||
"productBundleIdentifier": "com.example.tibia-test"
|
"productBundleIdentifier" : "com.example.tibia-test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"lv2_make": {
|
"lv2_make": {
|
||||||
"cflags": "$(shell pkg-config --cflags pugl-cairo-0 pugl-0 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)"
|
"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)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ typedef struct plugin {
|
|||||||
float cutoff;
|
float cutoff;
|
||||||
char bypass;
|
char bypass;
|
||||||
|
|
||||||
float * delay_line;
|
float *delay_line;
|
||||||
size_t delay_line_cur;
|
size_t delay_line_cur;
|
||||||
float z1;
|
float z1;
|
||||||
float cutoff_k;
|
float cutoff_k;
|
||||||
|
@ -132,6 +132,24 @@
|
|||||||
"list": false,
|
"list": false,
|
||||||
"unit": "",
|
"unit": "",
|
||||||
"map": "linear"
|
"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": {
|
"ui": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"vst3_make": {
|
"vst3_make": {
|
||||||
"cflags": "-I../../../vst3_c_api $(shell pkg-config --cflags pugl-cairo-0)",
|
"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)"
|
"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