brickworks/examples/common/web/processor.js

149 lines
4.2 KiB
JavaScript
Raw Normal View History

2022-11-15 23:49:51 +00:00
/*
* 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
2022-12-06 08:01:34 +00:00
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
2022-11-15 23:49:51 +00:00
*
* 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;
case "pitchBend":
self.module.wrapper_pitch_bend(self.instance, e.data.pitchBend);
break;
case "modWheel":
self.module.wrapper_mod_wheel(self.instance, e.data.modWheel);
break;
2022-11-15 23:49:51 +00:00
}
};
}
// 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);