From 119c5cba9ae35669b120535252dcbc10cda0c7ab Mon Sep 17 00:00:00 2001 From: Stefano D'Angelo Date: Thu, 25 Jan 2024 11:00:39 +0100 Subject: [PATCH] more android --- templates/android/src/MainActivity.java | 4 - templates/android/src/data.h | 21 ++- templates/android/src/index.html | 58 +++++- templates/android/src/jni.cpp | 237 ++++++++++++------------ 4 files changed, 196 insertions(+), 124 deletions(-) diff --git a/templates/android/src/MainActivity.java b/templates/android/src/MainActivity.java index f17aac8..bed1431 100644 --- a/templates/android/src/MainActivity.java +++ b/templates/android/src/MainActivity.java @@ -57,10 +57,6 @@ public class MainActivity extends Activity { public void setParameter(int i, float v) { nativeSetParameter(i, v); } - - @JavascriptInterface - public void dummyFunc() { - } } public void onCreate(Bundle savedInstanceState) { diff --git a/templates/android/src/data.h b/templates/android/src/data.h index d58fb19..1705a7f 100644 --- a/templates/android/src/data.h +++ b/templates/android/src/data.h @@ -4,17 +4,30 @@ #define NUM_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain) ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain)[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) ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain)[0].channels == "mono" ? 1 : 2) : 0}} +#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}} + #define PARAMETERS_N {{=it.product.parameters.length}} #if PARAMETERS_N > 0 + +# define PARAM_BYPASS 1 +# define PARAM_TOGGLED (1<<1) +# define PARAM_INTEGER (1<<2) + static struct { - char out; - float def; + char out; + float def; + float min; + float max; + uint32_t flags; } param_data[PARAMETERS_N] = { {{~it.product.parameters :p}} { - /* .out = */ {{=p.direction == "output" ? 1 : 0}}, - /* .def = */ {{=p.defaultValue.toExponential()}} + /* .out = */ {{=p.direction == "output" ? 1 : 0}}, + /* .def = */ {{=p.defaultValue.toExponential()}}, + /* .min = */ {{=p.minimum.toExponential()}}f, + /* .max = */ {{=p.maximum.toExponential()}}f, + /* .flags = */ {{?p.isBypass}}PARAM_BYPASS{{??p.isLatency}}PARAM_INTEGER{{??}}0{{?p.toggled}} | PARAM_TOGGLED{{?}}{{?p.integer}} | PARAM_INTEGER{{?}}{{?}} }, {{~}} }; diff --git a/templates/android/src/index.html b/templates/android/src/index.html index 3babf36..dc0f1dd 100644 --- a/templates/android/src/index.html +++ b/templates/android/src/index.html @@ -1,9 +1,65 @@ + {{=it.product.name}} + + - Prova + +
diff --git a/templates/android/src/jni.cpp b/templates/android/src/jni.cpp index f46621f..b55e812 100644 --- a/templates/android/src/jni.cpp +++ b/templates/android/src/jni.cpp @@ -114,118 +114,6 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, } } -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_orastron_@JNI_NAME@_MainActivity_nativeAudioStart(JNIEnv* env, jobject thiz) { - (void)env; - (void)thiz; - -#if NUM_CHANNELS_IN == 0 - ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback); -#else - ma_device_config deviceConfig = ma_device_config_init(ma_device_type_duplex); -#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.playback.channels = NUM_CHANNELS_OUT; - deviceConfig.playback.shareMode = ma_share_mode_shared; - - if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) - return false; - - P_INIT(&instance); - P_SET_SAMPLE_RATE(&instance, (float)device.sampleRate); -#ifdef P_MEM_REQ - size_t req = P_MEM_REQ(&instance); - if (req) { - mem = malloc(req); - if (mem == NULL) { - ma_device_uninit(&device); - return false; - } - P_MEM_SET(&instance, mem); - } else - mem = NULL; -#endif - - for (int i = 0; i < NUM_PARAMETERS; i++) { - paramValues[i] = config_parameters[i].defaultValueUnmapped; - if (!config_parameters[i].out) - P_SET_PARAMETER(&instance, i, paramValues[i]); - } - - P_RESET(&instance); - -#if NUM_CHANNELS_IN != 0 - for (int i = 0; i < NUM_CHANNELS_IN; i++) - inBufs[i] = bufs[i]; -#endif - for (int i = 0; i < NUM_CHANNELS_OUT; i++) - outBufs[i] = bufs[i]; - - if (ma_device_start(&device) != MA_SUCCESS) { -#ifdef P_MEM_REQ - free(mem); -#endif - ma_device_uninit(&device); - return false; - } - - return true; -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_orastron_@JNI_NAME@_MainActivity_nativeAudioStop(JNIEnv* env, jobject thiz) { - (void)env; - (void)thiz; - -#ifdef P_MEM_REQ - free(mem); -#endif -#ifdef P_FINI - P_FINI(&instance); -#endif - ma_device_stop(&device); - ma_device_uninit(&device); -} - -extern "C" -JNIEXPORT jfloat JNICALL -Java_com_orastron_@JNI_NAME@_MainActivity_nativeGetParameter(JNIEnv* env, jobject thiz, jint i) { - (void)env; - (void)thiz; - - mutex.lock(); - float v = paramValues[i]; - mutex.unlock(); - return v; -} - - -extern "C" -JNIEXPORT void JNICALL -Java_com_orastron_@JNI_NAME@_MainActivity_nativeSetParameter(JNIEnv* env, jobject thiz, jint i, jfloat v) { - (void)env; - (void)thiz; - - mutex.lock(); - paramValues[i] = v; - mutex.unlock(); -} - #ifdef P_NOTE_ON extern "C" JNIEXPORT void JNICALL @@ -270,6 +158,12 @@ Java_com_orastron_@JNI_NAME@_MainActivity_removeMidiPort(JNIEnv* env, jobject th #include "plugin.h" #include +#if PARAMETERS_N + NUM_MIDI_INPUTS > 0 +# include +#endif +#if PARAMETERS_N > 0 +# include +#endif #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 # define MINIAUDIO_IMPLEMENTATION # define MA_ENABLE_ONLY_SPECIFIC_BACKENDS @@ -277,14 +171,71 @@ Java_com_orastron_@JNI_NAME@_MainActivity_removeMidiPort(JNIEnv* env, jobject th # include # define BLOCK_SIZE 32 -# define NUM_BUFS (NUM_CHANNELS_IN > NUM_CHANNELS_OUT ? NUM_CHANNELS_IN : NUM_CHANNELS_OUT) +#endif +#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 static ma_device device; #endif static plugin instance; static void * mem; +#if NUM_CHANNELS_IN > 0 +float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE]; +#endif +#if NUM_CHANNELS_OUT > 0 +float y_buf[NUM_CHANNELS_OUT * BLOCK_SIZE]; +#endif +const float ** x; +float ** y; +#if PARAMETERS_N > 0 +std::mutex mutex; +float param_values[PARAMETERS_N]; +float param_values_prev[PARAMETERS_N]; +#endif static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { + (void)pDevice; + +#if PARAMETERS_N + NUM_MIDI_INPUTS > 0 + if (mutex.try_lock()) { +# if PARAMETERS_N > 0 + for (size_t i = 0; i < PARAMETERS_N; i++) { + if (param_data[i].out) + 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]; + } + // TODO: midi + } +# endif + mutex.unlock(); + } +#endif + + const float * in_buf = reinterpret_cast(pInput); + float * out_buf = reinterpret_cast(pOutput); + ma_uint32 i = 0; + while (i < frameCount) { + ma_uint32 n = std::min(frameCount - i, static_cast(BLOCK_SIZE)); + +#if NUM_CHANNELS_IN > 0 + size_t ix = NUM_CHANNELS_IN * i; + for (ma_uint32 j = 0; j < n; j++) + for (size_t k = 0; k < NUM_CHANNELS_IN; k++, ix++) + x_buf[BLOCK_SIZE * k + j] = in_buf[ix]; +#endif + + plugin_process(&instance, x, y, n); + +#if NUM_CHANNELS_OUT > 0 + size_t iy = NUM_CHANNELS_OUT * i; + for (ma_uint32 j = 0; j < n; j++) + for (size_t k = 0; k < NUM_CHANNELS_OUT; k++, iy++) + y_buf[BLOCK_SIZE * k + j] = out_buf[ix]; +#endif + + i += n; + } } extern "C" @@ -325,9 +276,11 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { plugin_init(&instance); #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) plugin_set_parameter(&instance, i, param_data[i].def); + param_values_prev[i] = param_values[i] = param_data[i].def; + } #endif plugin_set_sample_rate(&instance, (float)device.sampleRate); @@ -347,6 +300,28 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) { plugin_reset(&instance); +#if NUM_CHANNELS_IN > 0 + for (size_t i = 0; i < NUM_CHANNELS_IN; i++) + x[i] = x_buf + BLOCK_SIZE * i; +#else + x = NULL; +#endif +#if NUM_CHANNELS_OUT > 0 + for (size_t i = 0; i < NUM_CHANNELS_OUT; i++) + y[i] = y_buf + BLOCK_SIZE * i; +#else + y = NULL; +#endif + +#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 + if (ma_device_start(&device) != MA_SUCCESS) { + if (mem != NULL) + free(mem); + ma_device_uninit(&device); + return false; + } +#endif + return true; } @@ -356,8 +331,9 @@ JNI_FUNC(nativeAudioStop)(JNIEnv* env, jobject thiz) { (void)env; (void)thiz; + if (mem != NULL) + free(mem); plugin_fini(&instance); - #if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0 ma_device_stop(&device); ma_device_uninit(&device); @@ -367,20 +343,51 @@ JNI_FUNC(nativeAudioStop)(JNIEnv* env, jobject thiz) { extern "C" JNIEXPORT jfloat JNICALL JNI_FUNC(nativeGetParameter)(JNIEnv* env, jobject thiz, jint i) { + (void)env; + (void)thiz; + +#if PARAMETERS_N > 0 + mutex.lock(); + float v = param_values[i]; + mutex.unlock(); + return v; +#else return 0.f; +#endif } extern "C" JNIEXPORT void JNICALL JNI_FUNC(nativeSetParameter)(JNIEnv* env, jobject thiz, jint i, jfloat v) { + (void)env; + (void)thiz; + + if (param_data[i].flags & (PARAM_BYPASS | PARAM_TOGGLED)) + v = v > 0.5f ? 1.f : 0.f; + else if (param_data[i].flags & PARAM_INTEGER) + v = (int32_t)(v + 0.5f); + v = std::min(std::max(v, param_data[i].min), param_data[i].max); +#if PARAMETERS_N > 0 + mutex.lock(); + param_values[i] = v; + mutex.unlock(); +#endif } extern "C" JNIEXPORT void JNICALL JNI_FUNC(addMidiPort)(JNIEnv* env, jobject thiz, jobject d, jint p) { + (void)env; + (void)thiz; + + //TBD } extern "C" JNIEXPORT void JNICALL JNI_FUNC(removeMidiPort)(JNIEnv* env, jobject thiz, jobject d, jint p) { + (void)env; + (void)thiz; + + //TBD }