more android
This commit is contained in:
parent
119c5cba9a
commit
906ecf4033
@ -1,12 +1,39 @@
|
||||
#define AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain)}}
|
||||
#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_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 AUDIO_BUS_IN {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "input" && !x.cv && !x.sidechain)}}
|
||||
#define AUDIO_BUS_OUT {{=it.product.buses.findIndex(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain)}}
|
||||
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#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_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 PARAMETERS_N {{=it.product.parameters.length}}
|
||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
|
||||
#if (AUDIO_BUS_IN >= 0) || (AUDIO_BUS_OUT >= 0)
|
||||
static struct {
|
||||
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}}
|
||||
},
|
||||
{{?}}
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PARAMETERS_N {{=it.product.parameters.length}}
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
|
||||
|
@ -9,8 +9,18 @@ var data = {
|
||||
parameters: {{=JSON.stringify(it.product.parameters, null, 2)}}
|
||||
};
|
||||
|
||||
function map(index, value) {
|
||||
var p = data.parameters[index];
|
||||
return p.map == "logarithmic" ? p.minimum * Math.exp((2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) * value) : p.minimum + (p.maximum - p.minimum) * value;
|
||||
}
|
||||
|
||||
function unmap(index, value) {
|
||||
var p = data.parameters[index];
|
||||
return p.map == "logarithmic" ? Math.log(value / p.minimum) / (2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) : (value - p.minimum) / (p.maximum - p.minimum);
|
||||
}
|
||||
|
||||
var hasAudioPermission = true;
|
||||
for (var i = 0; i < buses.length; i++)
|
||||
for (var i = 0; i < data.buses.length; i++)
|
||||
if (!data.buses[i].output) {
|
||||
hasAudioPermission = Android.hasAudioPermission();
|
||||
break;
|
||||
@ -24,6 +34,77 @@ window.onload = function () {
|
||||
var paramsElem = document.getElementById("params");
|
||||
|
||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||
topButtonElem.addEventListener("click", function () {
|
||||
if (!hasAudioPermission) {
|
||||
Android.requestAudioPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
if (audioStarted) {
|
||||
clearInterval(outParamInterval);
|
||||
Android.audioStop();
|
||||
|
||||
paramsElem.innerHTML = "";
|
||||
|
||||
topButtonElem.value = "START";
|
||||
audioStarted = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Android.audioStart()) {
|
||||
alert("Could not start audio");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.parameters.length; i++) {
|
||||
var div = document.createElement("div");
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute("for", "p" + i);
|
||||
label.innerText = data.parameters[i].name;
|
||||
|
||||
var range = document.createElement("input");
|
||||
range.classList.add("range");
|
||||
range.setAttribute("type", "range");
|
||||
range.setAttribute("id", "p" + i);
|
||||
range.setAttribute("name", "p" + i);
|
||||
if (data.parameters[i].isBypass || data.parameters[i].toggled) {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", 1);
|
||||
} else {
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", data.parameters[i].integer ? 1 / (data.parameters[i].maximum - data.parameters[i].minimum) : "any");
|
||||
}
|
||||
range.value = unmap(i, data.parameters[i].defaultValue);
|
||||
if (data.parameters[i].direction == "output")
|
||||
range.setAttribute("readonly", "true");
|
||||
else {
|
||||
let index = i;
|
||||
range.addEventListener("input",
|
||||
function (ev) {
|
||||
Android.setParameter(index, map(index, parseFloat(ev.target.value)));
|
||||
});
|
||||
}
|
||||
|
||||
div.appendChild(label);
|
||||
div.appendChild(document.createElement("br"));
|
||||
div.appendChild(range);
|
||||
paramsElem.appendChild(div);
|
||||
}
|
||||
|
||||
outParamInterval = setInterval(
|
||||
function () {
|
||||
for (var i = 0; i < data.parameters.length; i++)
|
||||
if (data.parameters[i].direction == "output")
|
||||
document.getElementById("p" + i).value = unmap(i, Android.getParameter(i));
|
||||
}, 50);
|
||||
|
||||
topButtonElem.value = "STOP";
|
||||
audioStarted = true;
|
||||
});
|
||||
};
|
||||
|
||||
function gotAudioPermission() {
|
||||
|
@ -3,32 +3,6 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <jni.h>
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
|
||||
#define MA_ENABLE_AAUDIO
|
||||
#include <miniaudio.h>
|
||||
#include <amidi/AMidi.h>
|
||||
#include "config.h"
|
||||
|
||||
#define BLOCK_SIZE 32
|
||||
#define NUM_BUFS (NUM_CHANNELS_IN > NUM_CHANNELS_OUT ? NUM_CHANNELS_IN : NUM_CHANNELS_OUT)
|
||||
|
||||
ma_device device;
|
||||
P_TYPE instance;
|
||||
float paramValues[NUM_PARAMETERS];
|
||||
float bufs[NUM_BUFS][BLOCK_SIZE];
|
||||
#if NUM_CHANNELS_IN != 0
|
||||
const float *inBufs[NUM_CHANNELS_IN];
|
||||
#endif
|
||||
float *outBufs[NUM_CHANNELS_OUT];
|
||||
std::mutex mutex;
|
||||
#ifdef P_MEM_REQ
|
||||
void *mem;
|
||||
#endif
|
||||
#ifdef P_NOTE_ON
|
||||
struct PortData {
|
||||
AMidiDevice *device;
|
||||
@ -157,6 +131,7 @@ Java_com_orastron_@JNI_NAME@_MainActivity_removeMidiPort(JNIEnv* env, jobject th
|
||||
#include "data.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0
|
||||
# include <mutex>
|
||||
@ -178,14 +153,25 @@ static ma_device device;
|
||||
#endif
|
||||
static plugin instance;
|
||||
static void * mem;
|
||||
#if (NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN) || (NUM_NON_OPT_CHANNELS_OUT > NUM_CHANNELS_OUT)
|
||||
float zero[BLOCK_SIZE];
|
||||
#endif
|
||||
#if NUM_CHANNELS_IN > 0
|
||||
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
||||
#endif
|
||||
#if NUM_ALL_CHANNELS_IN > 0
|
||||
const float * x[NUM_ALL_CHANNELS_IN];
|
||||
#else
|
||||
const float ** x;
|
||||
#endif
|
||||
#if NUM_CHANNELS_OUT > 0
|
||||
float y_buf[NUM_CHANNELS_OUT * BLOCK_SIZE];
|
||||
#endif
|
||||
const float ** x;
|
||||
#if NUM_ALL_CHANNELS_OUT > 0
|
||||
float * y[NUM_ALL_CHANNELS_IN];
|
||||
#else
|
||||
float ** y;
|
||||
#endif
|
||||
#if PARAMETERS_N > 0
|
||||
std::mutex mutex;
|
||||
float param_values[PARAMETERS_N];
|
||||
@ -225,13 +211,17 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
||||
x_buf[BLOCK_SIZE * k + j] = in_buf[ix];
|
||||
#endif
|
||||
|
||||
#if (NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN) || (NUM_NON_OPT_CHANNELS_OUT > NUM_CHANNELS_OUT)
|
||||
memset(zero, 0, BLOCK_SIZE * sizeof(float));
|
||||
#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];
|
||||
out_buf[iy] = y_buf[BLOCK_SIZE * k + j];
|
||||
#endif
|
||||
|
||||
i += n;
|
||||
@ -300,15 +290,55 @@ 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;
|
||||
#if NUM_ALL_CHANNELS_IN > 0
|
||||
# if AUDIO_BUS_IN >= 0
|
||||
size_t ix = 0;
|
||||
size_t ixb = 0;
|
||||
for (size_t j = 0; j < NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT; j++) {
|
||||
if (audio_bus_data[j].out)
|
||||
continue;
|
||||
if (audio_bus_data[j].index == AUDIO_BUS_IN)
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, ix++, ixb++)
|
||||
x[ix] = x_buf + BLOCK_SIZE * ixb;
|
||||
# if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||
else if (!audio_bus_data[j].optional)
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, ix++)
|
||||
x[ix] = zero;
|
||||
# endif
|
||||
else
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, ix++)
|
||||
x[ix] = NULL;
|
||||
}
|
||||
# else
|
||||
for (size_t i = 0; i < NUM_ALL_CHANNELS_IN; i++)
|
||||
x[i] = NULL;
|
||||
# endif
|
||||
#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;
|
||||
#if NUM_ALL_CHANNELS_OUT > 0
|
||||
# if AUDIO_BUS_OUT >= 0
|
||||
size_t iy = 0;
|
||||
size_t iyb = 0;
|
||||
for (size_t j = 0; j < NUM_AUDIO_BUSES_IN + NUM_AUDIO_BUSES_OUT; j++) {
|
||||
if (!audio_bus_data[j].out)
|
||||
continue;
|
||||
if (audio_bus_data[j].index == AUDIO_BUS_OUT)
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, iy++, iyb++)
|
||||
y[iy] = y_buf + BLOCK_SIZE * iyb;
|
||||
# if NUM_NON_OPT_CHANNELS_OUT > NUM_CHANNELS_OUT
|
||||
else if (!audio_bus_data[j].optional)
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, iy++)
|
||||
y[iy] = zero;
|
||||
# endif
|
||||
else
|
||||
for (char k = 0; k < audio_bus_data[j].channels; k++, iy++)
|
||||
y[iy] = NULL;
|
||||
}
|
||||
# else
|
||||
for (size_t i = 0; i < NUM_ALL_CHANNELS_OUT; i++)
|
||||
y[i] = NULL;
|
||||
# endif
|
||||
#else
|
||||
y = NULL;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user