brickworks/examples/fx_bitcrush/web/index.html
2022-12-11 10:36:56 +01:00

211 lines
5.4 KiB
HTML

<!DOCTYPE html>
<!--
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
along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
File author: Stefano D'Angelo
-->
<html>
<head>
<title>Brickworks web effect example</title>
<script src="config.js"></script>
<script>
var audioCtx;
var Effect = {
node: null,
moduleAdded: false,
wasmBytes: null,
init: async function () {
if (!this.moduleAdded) {
await audioCtx.audioWorklet.addModule("processor.js");
this.moduleAdded = true;
}
if (!this.wasmBytes)
this.wasmBytes = await fetch("module.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => bytes);
if (!this.wasmBytes.byteLength) {
this.wasmBytes = null;
throw "could not fetch WebAssembly module";
}
if (!this.node)
this.node = new AudioWorkletNode(audioCtx, "BWExample",
{
numberOfInputs: 1,
numberOfOutputs: 1,
outputChannelCount: [ 1 ],
processorOptions: {
wasmBytes: this.wasmBytes
}
});
this.node.connect(audioCtx.destination);
}
};
var Player = {
sourceBuffer: null,
playing: false,
started: false,
load: function (buffer, successCb, errorCb) {
let t = this;
audioCtx.decodeAudioData(buffer,
function (data) {
if (t.started)
t.sourceBuffer.stop();
if (t.playing)
t.sourceBuffer.disconnect();
t.sourceBuffer = audioCtx.createBufferSource();
t.sourceBuffer.buffer = data;
t.sourceBuffer.loop = true;
if (t.started)
t.sourceBuffer.start();
if (t.playing) {
t.started = true;
t.sourceBuffer.connect(Effect.node);
}
successCb();
},
function () { errorCb(); });
},
togglePlayPause: function () {
if (this.playing) {
this.sourceBuffer.disconnect();
this.playing = false;
} else {
if (!this.started) {
this.sourceBuffer.start();
this.started = true;
}
this.sourceBuffer.connect(Effect.node);
this.playing = true;
}
}
};
var initState = 0; // 0 = not inited, 1 = in progress, 2 = inited
window.addEventListener("load", function (e) {
var start = document.getElementById("start");
var starting = document.getElementById("starting");
var main = document.getElementById("main");
var file = document.getElementById("file");
var playPause = document.getElementById("playPause");
var controls = document.getElementById("controls");
// reset on refresh
file.value = "";
playPause.disabled = true;
for (var i = 0; i < parameters.length; i++) {
var div = document.createElement("div");
controls.appendChild(div);
var label = document.createElement("label");
label.setAttribute("for", "p" + i);
label.innerText = parameters[i].name;
div.appendChild(label);
var range = document.createElement("input");
range.setAttribute("type", "range");
range.setAttribute("id", "p" + i);
range.setAttribute("name", "p" + i);
range.setAttribute("min", "0");
range.setAttribute("max", "1");
if (!parameters[i].step)
range.setAttribute("step", "any");
else
range.setAttribute("step", 1 / parameters[i].step);
range.value = parameters[i].defaultValue;
if (parameters[i].output)
range.setAttribute("readonly", "true");
else {
let index = i;
range.addEventListener("input", function (e) {
var p = Effect.node.parameters.get(parameters[index].name);
p.setValueAtTime(e.target.value, 0);
});
}
div.appendChild(range);
}
start.addEventListener("click", async function () {
initState = 1;
start.disabled = true;
starting.hidden = false;
try {
if (!audioCtx)
audioCtx = new AudioContext();
await Effect.init();
Effect.node.port.onmessage = function (e) { document.getElementById("p" + e.data.index).value = e.data.value; };
initState = 2;
start.hidden = true;
starting.hidden = true;
main.hidden = false;
} catch (err) {
alert("Colud not initialize: " + err);
initState = 0;
start.disabled = false;
starting.hidden = true;
}
});
file.addEventListener("change", function () {
var fileReader = new FileReader();
fileReader.readAsArrayBuffer(this.files[0]);
fileReader.onload = function (e) {
Player.load(e.target.result,
function () { playPause.disabled = false; },
function () { alert("Could not decode the chosen file"); });
};
fileReader.onerror = function (e) { alert("Could not read file"); };
});
playPause.addEventListener("click", function () {
Player.togglePlayPause();
playPause.innerText = Player.playing ? "Pause" : "Play";
});
});
</script>
</head>
<body>
<h1>Brickworks web effect example</h1>
<input id="start" type="button" value="Start">
<p id="starting" hidden>Starting...</p>
<div id="main" hidden>
<h2>Player</h2>
<label for="file">Choose a file:</label>
<input type="file" id="file" name="file" accept="audio/*">
<br>
<button id="playPause" disabled>Play</button>
<h2>Effect</h2>
<div id="controls">
</div>
</div>
</body>
</html>