more web
This commit is contained in:
parent
bcc61e9a29
commit
8dabd9b3f8
2
TODO
2
TODO
@ -19,3 +19,5 @@
|
||||
* LV2 (and raw midi): uneven midi pitch bend, what to do?
|
||||
* VST3: noteOn, noteOff tuning, what to do? (https://steinbergmedia.github.io/vst3_doc/vstinterfaces/structSteinberg_1_1Vst_1_1NoteOnEvent.html, https://steinbergmedia.github.io/vst3_doc/vstinterfaces/structSteinberg_1_1Vst_1_1NoteOffEvent.html)
|
||||
* midi out
|
||||
* vst3 tail, web process return true/false
|
||||
* error checking etc. web, especially processor.js
|
||||
|
@ -8,20 +8,23 @@ LDFLAGS = \
|
||||
-Wl,--lto-O3 \
|
||||
-Wl,-strip-all \
|
||||
-Wl,--export-table \
|
||||
-Wl,--export=wrapper_new \
|
||||
-Wl,--export=wrapper_free \
|
||||
-Wl,--export=wrapper_get_ins \
|
||||
-Wl,--export=wrapper_get_outs \
|
||||
-Wl,--export=wrapper_get_param_values \
|
||||
-Wl,--export=wrapper_process \
|
||||
-Wl,--export=wrapper_set_parameter \
|
||||
-Wl,--export=processor_new \
|
||||
-Wl,--export=processor_free \
|
||||
-Wl,--export=processor_get_ins \
|
||||
-Wl,--export=processor_get_outs \
|
||||
-Wl,--export=processor_get_param_values \
|
||||
-Wl,--export=processor_process \
|
||||
-Wl,--export=processor_set_parameter \
|
||||
-Wl,-z,stack-size=$$((8*1024*1024)) \
|
||||
-nostdlib
|
||||
|
||||
all: build/${BUNDLE_NAME}.wasm
|
||||
all: build/${BUNDLE_NAME}.wasm build/${BUNDLE_NAME}_processor.js
|
||||
|
||||
build/${BUNDLE_NAME}.wasm: src/data.h src/memset.h src/plugin.h src/walloc.h src/wrapper.c | build
|
||||
${CC} src/wrapper.c -o $@ ${CFLAGS} ${LDFLAGS} ${CFLAGS_EXTRA} ${LIBS_EXTRA}
|
||||
build/${BUNDLE_NAME}.wasm: src/data.h src/memset.h src/plugin.h src/walloc.h src/processor.c | build
|
||||
${CC} src/processor.c -o $@ ${CFLAGS} ${LDFLAGS} ${CFLAGS_EXTRA} ${LIBS_EXTRA}
|
||||
|
||||
build/${BUNDLE_NAME}_processor.js: src/processor.js | build
|
||||
cp $^ $@
|
||||
|
||||
build:
|
||||
mkdir -p $@
|
||||
|
@ -27,7 +27,7 @@ typedef struct {
|
||||
#endif
|
||||
} instance;
|
||||
|
||||
instance * wrapper_new(float sample_rate) {
|
||||
instance * processor_new(float sample_rate) {
|
||||
instance * i = malloc(sizeof(instance));
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
@ -66,32 +66,32 @@ instance * wrapper_new(float sample_rate) {
|
||||
return i;
|
||||
}
|
||||
|
||||
void wrapper_free(instance * i) {
|
||||
void processor_free(instance * i) {
|
||||
plugin_fini(&i->p);
|
||||
if (i->mem)
|
||||
free(i->mem);
|
||||
free(i);
|
||||
}
|
||||
|
||||
float * wrapper_get_x_buf(instance * i) {
|
||||
float * processor_get_x_buf(instance * i) {
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
return i->x_buf;
|
||||
#else
|
||||
(void *)i;
|
||||
(void)i;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
float * wrapper_get_y_buf(instance * i) {
|
||||
float * processor_get_y_buf(instance * i) {
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
return i->y_buf;
|
||||
#else
|
||||
(void *)i;
|
||||
(void)i;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
float * wrapper_get_out_params(instance *i) {
|
||||
float * processor_get_out_params(instance *i) {
|
||||
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
|
||||
return i->out_params;
|
||||
#else
|
||||
@ -100,11 +100,11 @@ float * wrapper_get_out_params(instance *i) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void wrapper_set_parameter(instance *i, int32_t index, float value) {
|
||||
void processor_set_parameter(instance *i, int32_t index, float value) {
|
||||
plugin_set_parameter(&i->p, index, value);
|
||||
}
|
||||
|
||||
void wrapper_process(instance *i, int32_t n_samples) {
|
||||
void processor_process(instance *i, int32_t n_samples) {
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
const float **x = i->x;
|
||||
#else
|
135
templates/web/src/processor.js
Normal file
135
templates/web/src/processor.js
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2022, 2024 Orastron Srl unipersonale
|
||||
*/
|
||||
|
||||
var buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||
var parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||
|
||||
class Processor extends AudioWorkletProcessor {
|
||||
throwError(msg) {
|
||||
this.port.postMessage({ type: "error", msg: msg);
|
||||
throw msg;
|
||||
}
|
||||
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
var module = new WebAssembly.Module(options.processorOptions.wasmBytes);
|
||||
var instance = new WebAssembly.Instance(module, { env: {} });
|
||||
this.module = instance.exports;
|
||||
|
||||
this.instance = this.module.processor_new(sampleRate);
|
||||
if (!this.instance)
|
||||
this.throwError("Could not instantiate processor module");
|
||||
|
||||
function getBuffers(p, output) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < buses.length; i++) {
|
||||
if ((output && buses[i].direction == "input") || (!output && buses[i].direction == "output"))
|
||||
continue;
|
||||
if (buses[i].channels == "mono") {
|
||||
ret.push([ new Float32Array(this.module.memory.buffer, p, 128) ]);
|
||||
p += 128 * 4;
|
||||
} else {
|
||||
ret.push([
|
||||
new Float32Array(this.module.memory.buffer, p, 128),
|
||||
new Float32Array(this.module.memory.buffer, p + 128 * 4, 128)
|
||||
]);
|
||||
p += 2 * 128 * 4;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
this.x = getBuffers.call(this, this.module.processor_get_x_buf(this.instance), false);
|
||||
this.y = getBuffers.call(this, this.module.processor_get_y_buf(this.instance), true);
|
||||
|
||||
this.parametersIn = [];
|
||||
for (var i = 0; i < parameters.length; i++)
|
||||
if (parameters[i].direction == "input")
|
||||
this.parametersIn.push({ index: i, value: NaN });
|
||||
|
||||
this.parametersOut = [];
|
||||
for (var i = 0; i < parameters.length; i++)
|
||||
if (parameters[i].direction == "output")
|
||||
this.parametersOut.push({ index: i, value: NaN });
|
||||
|
||||
if (this.parametersOut.length > 0)
|
||||
this.parametersOutValues = new Float32Array(this.module.memory.buffer, this.module.processor_get_out_params(this.instance), this.parametersOut.length);
|
||||
|
||||
this.paramOutChangeMsg = { type: "paramOutChange", index: NaN, value: NaN };
|
||||
}
|
||||
|
||||
process(input, outputs, params) {
|
||||
for (var i = 0; i < this.parametersIn.length; i++) {
|
||||
var index = this.parametersIn[i].index;
|
||||
var parameter = parameters[index];
|
||||
var name = parameter.name;
|
||||
var value = params[p.name][0];
|
||||
if (value != this.parametersIn[i].value) {
|
||||
if (parameter.isBypass || parameter.toggled)
|
||||
value = value > 0 ? 0 : 1;
|
||||
else if (parameter.integer)
|
||||
value = Math.round(value);
|
||||
value = Math.min(Math.max(value, parameter.minimum), parameter.maximum);
|
||||
if (value != this.parametersIn[i].value) {
|
||||
this.module.processor_set_parameter(this.instance, index, value);
|
||||
this.parametersIn[i].value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var n = outputs[0][0].length;
|
||||
var i = 0;
|
||||
while (i < n) {
|
||||
var s = Math.min(n - i, 128);
|
||||
|
||||
for (var j = 0; j < this.x.length; j++) {
|
||||
var input = inputs[j];
|
||||
if (!input.length) {
|
||||
for (var k = 0; k < this.x[j].length; k++)
|
||||
this.x[j][k].fill(0);
|
||||
} else {
|
||||
for (var k = 0; k < this.x[j].length; k++)
|
||||
if (k <= input.length)
|
||||
this.x[j][k].set(input[k].subarray(i, s));
|
||||
else
|
||||
this.x[j][k].fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
this.module.processor_process(this.instance, s);
|
||||
|
||||
for (var j = 0; j < this.y.length; j++) {
|
||||
var output = outputs[j];
|
||||
for (var k = 0; k < this.y[j].length; k++)
|
||||
this.y[j][k].set(output[k].subarray(i, s));
|
||||
}
|
||||
|
||||
i += s;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.parametersOut.length; i++) {
|
||||
var index = this.parametersOut[i].index;
|
||||
var value = this.parametersOutValues[i];
|
||||
if (value != this.parametersOut[i].value) {
|
||||
this.paramOutChangeMsg.index = index;
|
||||
this.paramOutChangeMsg.value = value;
|
||||
this.port.postMessage(this.paramOutChangeMsg);
|
||||
this.parametersOut[i].value = value;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static get parameterDescriptors() {
|
||||
var ret = [];
|
||||
for (var i = 0; i < this.parametersIn.length; i++) {
|
||||
var p = parameters[this.parametersIn[i].index];
|
||||
ret.push({ name: p.name, minValue: p.minimum, maxValue: p.maximum, defaultValue: p.defaultValue, automationRate: "k-rate" });
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor("{{=it.product.bundleName}}", Processor);
|
@ -4,6 +4,7 @@ var sep = path.sep;
|
||||
module.exports = function (data, api) {
|
||||
api.copyFile(`src${sep}memset.h`, `src${sep}memset.h`);
|
||||
api.copyFile(`src${sep}walloc.h`, `src${sep}walloc.h`);
|
||||
api.copyFile(`src${sep}wrapper.c`, `src${sep}wrapper.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}processor.js`, `src${sep}processor.js`, data);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user