From c39b5ed9930588a17dd4eb5eb3e2046c13aba083 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Tue, 9 Jul 2024 12:21:11 +0200 Subject: [PATCH] cpumeter android --- templates/android/src/data.h | 55 +++++++++------- templates/android/src/jni.cpp | 121 +++++++++++++++++++++------------- test/run.sh | 1 + 3 files changed, 106 insertions(+), 71 deletions(-) diff --git a/templates/android/src/data.h b/templates/android/src/data.h index 4c99f3a..bc7ab8c 100644 --- a/templates/android/src/data.h +++ b/templates/android/src/data.h @@ -18,37 +18,37 @@ * File author: Stefano D'Angelo */ -#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} -#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} +#define NUM_AUDIO_BUSES_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}} +#define NUM_AUDIO_BUSES_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}} -#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} -#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)}} +#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)}} -#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} -#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input") .reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} +#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}} -#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} +#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} -#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} +#define MIDI_BUS_IN {{=it.product.buses.findIndex(x => x.type == "midi" && x.direction == "input")}} #if NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT > 0 static struct { - size_t index; - char out; - char optional; - char channels; + size_t index; + char out; + char optional; + char channels; } audio_bus_data[NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT] = { {{~it.product.buses :b:i}} {{?b.type == "audio"}} { - /* .index = */ {{=i}}, - /* .out = */ {{=b.direction == "output" ? 1 : 0}}, - /* .optional = */ {{=b.optional ? 1 : 0}}, - /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} + /* .index = */ {{=i}}, + /* .out = */ {{=b.direction == "output" ? 1 : 0}}, + /* .optional = */ {{=b.optional ? 1 : 0}}, + /* .channels = */ {{=b.channels == "mono" ? 1 : 2}} }, {{?}} {{~}} @@ -72,14 +72,19 @@ static struct { } param_data[PARAMETERS_N] = { {{~it.product.parameters :p}} { - /* .out = */ {{=p.direction == "output" ? 1 : 0}}, - /* .def = */ {{=p.defaultValue.toExponential()}}, - /* .min = */ {{=p.minimum.toExponential()}}f, - /* .max = */ {{=p.maximum.toExponential()}}f, - /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} + /* .out = */ {{=p.direction == "output" ? 1 : 0}}, + /* .def = */ {{=p.defaultValue.toExponential()}}, + /* .min = */ {{=p.minimum.toExponential()}}f, + /* .max = */ {{=p.maximum.toExponential()}}f, + /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} }, {{~}} }; + +{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}} +# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}} +{{?}} + #endif #define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x diff --git a/templates/android/src/jni.cpp b/templates/android/src/jni.cpp index f935597..b062f7d 100644 --- a/templates/android/src/jni.cpp +++ b/templates/android/src/jni.cpp @@ -22,10 +22,10 @@ #include typedef struct { - void * handle; - const char * format; - const char * (*get_bindir)(void *handle); - const char * (*get_datadir)(void *handle); + void *handle; + const char *format; + const char *(*get_bindir)(void *handle); + const char *(*get_datadir)(void *handle); } plugin_callbacks; #include "data.h" @@ -52,60 +52,71 @@ typedef struct { #if NUM_MIDI_INPUTS > 0 # include - # include #endif +#ifdef PARAM_OUT_CPU_INDEX +# include "fatica.h" +#endif + #if defined(__i386__) || defined(__x86_64__) #include #include #endif -static ma_device device; -static plugin instance; -static void * mem; +static ma_device device; +static plugin instance; +static void *mem; #if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN -float zero[BLOCK_SIZE]; +float zero[BLOCK_SIZE]; #endif #if NUM_CHANNELS_IN > 0 -float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; -float * x_in[NUM_CHANNELS_IN]; +float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; +float *x_in[NUM_CHANNELS_IN]; #endif #if NUM_ALL_CHANNELS_IN > 0 -const float * x[NUM_ALL_CHANNELS_IN]; +const float *x[NUM_ALL_CHANNELS_IN]; #else -const float ** x; +const float **x; #endif #if NUM_NON_OPT_CHANNELS_OUT > 0 -float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; +float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE]; #endif #if NUM_CHANNELS_OUT > 0 -float * y_out[NUM_CHANNELS_OUT]; +float *y_out[NUM_CHANNELS_OUT]; #endif #if NUM_ALL_CHANNELS_OUT > 0 -float * y[NUM_ALL_CHANNELS_OUT]; +float *y[NUM_ALL_CHANNELS_OUT]; #else -float ** y; +float **y; #endif #if PARAMETERS_N > 0 -std::mutex mutex; -float param_values[PARAMETERS_N]; -float param_values_prev[PARAMETERS_N]; +std::mutex mutex; +float param_values[PARAMETERS_N]; +float param_values_prev[PARAMETERS_N]; #endif #if NUM_MIDI_INPUTS > 0 struct PortData { - AMidiDevice *device; - int portNumber; - AMidiOutputPort *port; + AMidiDevice *device; + int portNumber; + AMidiOutputPort *port; }; std::vector midiPorts; # define MIDI_BUFFER_SIZE 1024 -uint8_t midiBuffer[MIDI_BUFFER_SIZE]; +uint8_t midiBuffer[MIDI_BUFFER_SIZE]; +#endif +#ifdef PARAM_OUT_CPU_INDEX +float cpu_meter = 0.f; +float sample_rate = 1.f; #endif static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { (void)pDevice; +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeStart = fatica_time_process(); +#endif + #if defined(__aarch64__) uint64_t fpcr; __asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr)); @@ -122,8 +133,15 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, if (mutex.try_lock()) { # if PARAMETERS_N > 0 for (size_t i = 0; i < PARAMETERS_N; i++) { - if (param_data[i].out) + if (param_data[i].out) { +# ifdef PARAM_OUT_CPU_INDEX + if (i == PARAM_OUT_CPU_INDEX) { + param_values_prev[i] = param_values[i] = cpu_meter; + continue; + } +# endif param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i); + } else if (param_values_prev[i] != param_values[i]) { plugin_set_parameter(&instance, i, param_values[i]); param_values_prev[i] = param_values[i]; @@ -188,6 +206,13 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, _MM_SET_FLUSH_ZERO_MODE(flush_zero_mode); _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); #endif + +#ifdef PARAM_OUT_CPU_INDEX + const unsigned long long processTimeEnd = fatica_time_process(); + const unsigned long long processTime100n = processTimeEnd - processTimeStart; + const double processTimeS = ((double) processTime100n) * 1.0e-7; + cpu_meter = cpu_meter * 0.9f + ((float) (processTimeS * sample_rate)) * 0.1f; +#endif } extern "C" @@ -208,35 +233,35 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback); #endif - deviceConfig.periodSizeInFrames = BLOCK_SIZE; - deviceConfig.periods = 1; - deviceConfig.performanceProfile = ma_performance_profile_low_latency; - deviceConfig.noPreSilencedOutputBuffer = 1; - deviceConfig.noClip = 0; - deviceConfig.noDisableDenormals = 0; - deviceConfig.noFixedSizedCallback = 1; - deviceConfig.dataCallback = data_callback; - deviceConfig.capture.pDeviceID = NULL; - deviceConfig.capture.format = ma_format_f32; - deviceConfig.capture.channels = NUM_CHANNELS_IN; - deviceConfig.capture.shareMode = ma_share_mode_shared; - deviceConfig.playback.pDeviceID = NULL; - deviceConfig.playback.format = ma_format_f32; + deviceConfig.periodSizeInFrames = BLOCK_SIZE; + deviceConfig.periods = 1; + deviceConfig.performanceProfile = ma_performance_profile_low_latency; + deviceConfig.noPreSilencedOutputBuffer = 1; + deviceConfig.noClip = 0; + deviceConfig.noDisableDenormals = 0; + deviceConfig.noFixedSizedCallback = 1; + deviceConfig.dataCallback = data_callback; + deviceConfig.capture.pDeviceID = NULL; + deviceConfig.capture.format = ma_format_f32; + deviceConfig.capture.channels = NUM_CHANNELS_IN; + deviceConfig.capture.shareMode = ma_share_mode_shared; + deviceConfig.playback.pDeviceID = NULL; + deviceConfig.playback.format = ma_format_f32; #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 - deviceConfig.playback.channels = NUM_CHANNELS_OUT; + deviceConfig.playback.channels = NUM_CHANNELS_OUT; #else - deviceConfig.playback.channels = 1; // Fake & muted + deviceConfig.playback.channels = 1; // Fake & muted #endif - deviceConfig.playback.shareMode = ma_share_mode_shared; + deviceConfig.playback.shareMode = ma_share_mode_shared; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) return false; plugin_callbacks cbs = { - /* .handle = */ NULL, - /* .format = */ "android", - /* .get_bindir = */ NULL, - /* .get_datadir = */ NULL + /* .handle = */ NULL, + /* .format = */ "android", + /* .get_bindir = */ NULL, + /* .get_datadir = */ NULL }; plugin_init(&instance, &cbs); @@ -249,6 +274,10 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); +#ifdef PARAM_OUT_CPU_INDEX + sample_rate = (float)device.sampleRate; +#endif + size_t req = plugin_mem_req(&instance); if (req != 0) { mem = malloc(req); diff --git a/test/run.sh b/test/run.sh index f949268..94bda7e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -18,6 +18,7 @@ cp $dir/plugin.h $dir/../out/web/src $dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android $dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json,$dir/android-make.json $dir/../templates/android-make $dir/../out/android +cp $dir/../templates/common/* $dir/../out/android/src/ cp $dir/keystore.jks $dir/../out/android cp $dir/plugin.h $dir/../out/android/src