142 lines
4.0 KiB
JavaScript
142 lines
4.0 KiB
JavaScript
/*
|
|
* Brickworks
|
|
*
|
|
* Copyright (C) 2022 Orastron Srl unipersonale
|
|
*
|
|
* Brickworks is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 3 of the License.
|
|
*
|
|
* Brickworks is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
*
|
|
* File author: Stefano D'Angelo
|
|
*/
|
|
|
|
class BWExample extends AudioWorkletProcessor {
|
|
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.wrapper_new(sampleRate);
|
|
if (!this.instance)
|
|
// TODO: what to do if this is the case?
|
|
throw "Could not instantiate";
|
|
|
|
function getBuffers(p, output) {
|
|
var ret = [];
|
|
for (var i = 0; i < buses.length; i++) {
|
|
if ((!output && buses[i].output) || (output && !buses[i].output))
|
|
continue;
|
|
var b = [ new Float32Array(this.module.memory.buffer, p, 128) ];
|
|
p += 128 * 4;
|
|
if (buses[i].stereo) {
|
|
b.push(new Float32Array(this.module.memory.buffer, p, 128));
|
|
p += 128 * 4;
|
|
}
|
|
ret.push(b);
|
|
}
|
|
return ret;
|
|
}
|
|
this.ins = getBuffers.call(this, this.module.wrapper_get_ins(this.instance), false);
|
|
this.outs = getBuffers.call(this, this.module.wrapper_get_outs(this.instance), true);
|
|
|
|
if (parameters.length) {
|
|
this.paramValues = new Float32Array(this.module.memory.buffer, this.module.wrapper_get_param_values(this.instance), parameters.length);
|
|
this.paramValuesPrev = new Float32Array(this.paramValues);
|
|
} else {
|
|
this.paramValues = [];
|
|
this.paramValuesPrev = [];
|
|
}
|
|
|
|
var self = this;
|
|
this.port.onmessage = function (e) {
|
|
switch (e.data.type) {
|
|
case "noteOn":
|
|
self.module.wrapper_note_on(self.instance, e.data.note, e.data.velocity);
|
|
break;
|
|
case "noteOff":
|
|
self.module.wrapper_note_off(self.instance, e.data.note);
|
|
break;
|
|
}
|
|
};
|
|
}
|
|
|
|
// TODO: "destructor"
|
|
|
|
process(inputs, outputs, params) {
|
|
for (var i = 0; i < parameters.length; i++) {
|
|
if (parameters[i].output)
|
|
continue;
|
|
var n = parameters[i].name;
|
|
var v = params[n][0];
|
|
if (v != this.paramValues[n]) {
|
|
this.module.wrapper_set_parameter(this.instance, i, v);
|
|
this.paramValues[n] = v;
|
|
}
|
|
}
|
|
|
|
//mmm...
|
|
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.ins.length; j++) {
|
|
var input = inputs[j];
|
|
if (!input.length) {
|
|
for (var k = 0; k < this.ins[j].length; k++)
|
|
this.ins[j][k].fill(0);
|
|
} else {
|
|
if (this.ins[j].length != input.length)
|
|
throw "input " + j + " has " + this.ins[j].length + " channels, not " + input.length;
|
|
for (var k = 0; k < this.ins[j].length; k++)
|
|
for (var l = 0; l < s; l++)
|
|
this.ins[j][k][l] = input[k][i + l];
|
|
}
|
|
}
|
|
|
|
this.module.wrapper_process(this.instance, s);
|
|
|
|
for (var j = 0; j < this.outs.length; j++) {
|
|
var output = outputs[j];
|
|
for (var k = 0; k < output.length; k++)
|
|
for (var l = 0; l < s; l++)
|
|
output[k][i + l] = this.outs[j][k][l];
|
|
}
|
|
|
|
i += s;
|
|
}
|
|
|
|
for (var i = 0; i < parameters.length; i++) {
|
|
if (!parameters[i].output)
|
|
continue;
|
|
if (this.paramValuesPrev[i] != this.paramValues[i])
|
|
this.port.postMessage({ index: i, value: this.paramValues[i] });
|
|
}
|
|
this.paramValuesPrev.set(this.paramValues);
|
|
|
|
return true;
|
|
}
|
|
|
|
static get parameterDescriptors() {
|
|
var ret = [];
|
|
for (var i = 0; i < parameters.length; i++) {
|
|
var p = parameters[i];
|
|
if (p.output)
|
|
continue;
|
|
ret.push({ name: p.name, minValue: 0.0, maxValue: 1.0, defaultValue: p.defaultValue, automationRate: "k-rate" });
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
registerProcessor("BWExample", BWExample);
|