Files
strudel/packages/superdough/worklets-common.mjs
2025-12-04 22:12:54 -06:00

71 lines
2.5 KiB
JavaScript

/*
worklets-common.mjs - Common worklet code
Copyright (C) 2025 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/superdough/worklets-common.mjs>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Mixin to make class "reusable" (i.e. have a begin and end and properly handle `initialize` messages)
export const makeReusable = (Base) =>
class extends Base {
static get parameterDescriptors() {
return [
...(super.parameterDescriptors ?? []),
{
name: 'begin',
defaultValue: 0,
min: 0,
max: Number.POSITIVE_INFINITY,
automationRate: 'k-rate',
},
{
name: 'end',
defaultValue: 0,
min: 0,
max: Number.POSITIVE_INFINITY,
automationRate: 'k-rate',
},
];
}
constructor(options) {
super(options);
this.isAlive = true;
this.graceSeconds = options?.processorOptions?.graceSeconds ?? 0.5;
this.port.onmessage = (e) => {
const { type, payload } = e.data || {};
if (type === 'initialize') {
this.initialize(payload);
} else if (this.handlePortMessage) {
this.handlePortMessage(type, payload, e);
}
};
}
initialize(_options) {
// defined on subclasses
}
processActive(_inputs, _outputs, _params) {
// processing subclasses should do when we're between begin/end
return true;
}
process(inputs, outputs, params) {
const begin = params.begin[0];
const end = params.end[0];
if (currentTime >= end + this.graceSeconds) {
if (this.isAlive) {
this.port.postMessage({ type: 'died' });
this.isAlive = false;
}
return false;
}
if (currentTime < begin || currentTime >= end) {
return true;
}
return this.processActive(inputs, outputs, params);
}
};