rationalize web make

This commit is contained in:
Stefano D'Angelo 2023-01-17 17:36:17 +01:00
parent d72f1beca7
commit 483bad7196
22 changed files with 129 additions and 2139 deletions

1
TODO
View File

@ -31,6 +31,5 @@ build system:
* make autodependencies (.d?)
* make from... directories
* order-only prerequisites to avoid multiple make updates? (https://interrupt.memfault.com/blog/gnu-make-guidelines#order-only-prerequisites)
* clang + Ofast & bulk memory (maybe using old binaryen) - or implement memset etc.
* put common parts of Makefiles together somewhere/somehow (DRY)
* recursive make?

View File

@ -0,0 +1,28 @@
/*
* Brickworks
*
* Copyright (C) 2021, 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
*/
#include <stddef.h>
void *memset(void *ptr, int value, size_t num) {
unsigned char *p = (unsigned char *)ptr;
for (size_t i = 0; i < num; i++)
p[i] = (unsigned char)value;
return ptr;
}

View File

@ -0,0 +1,71 @@
CC := clang
CFLAGS := \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS := \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ifdef SYNTH
LDFLAGS += \
-Wl,--export=wrapper_note_on \
-Wl,--export=wrapper_note_off
INDEX := ${ROOT_DIR}/../../common/web/index-synth.html
else
INDEX := ${ROOT_DIR}/../../common/web/index-fx.html
endif
SOURCES_COMMON := \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
ifdef NEEDS_MEMSET
SOURCES_COMMON += \
${ROOT_DIR}/../../common/web/memset.c
LDFLAGS += \
-Wl,--export=memset
endif
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${INDEX}
cp ${INDEX} $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_bitcrush.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_bitcrush.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_comp.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_comp.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_mm1.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_mm1.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_mm2.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_mm2.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_noise_gate.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_noise_gate.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_satur.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_satur.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,56 +1,4 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
-Ofast
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_wah.c
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_fx_wah.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,210 +0,0 @@
<!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>

View File

@ -1,60 +1,6 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
#-Ofast - had to turn this off as there are issues with wasm bulk memory
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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=wrapper_note_on \
-Wl,--export=wrapper_note_off \
-Wl,--export=wrapper_pitch_bend \
-Wl,--export=wrapper_mod_wheel \
-Wl,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_synth_mono.c
SYNTH := yes
NEEDS_MEMSET := yes
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_synth_mono.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,58 +1,5 @@
CC=clang
CFLAGS= \
-D__WASM__ \
-I${ROOT_DIR}/../src \
-I${ROOT_DIR}/../../common/web \
-I${ROOT_DIR}/../../../include \
--target=wasm32 \
-flto \
-fvisibility=hidden \
#-Ofast - had to turn this off as there are issues with wasm bulk memory
LDFLAGS= \
-Wl,--allow-undefined \
-Wl,--no-entry \
-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=wrapper_note_on \
-Wl,--export=wrapper_note_off \
-Wl,-z,stack-size=$$((8*1024*1024)) \
-nostdlib
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_synth_simple.c
SYNTH := yes
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCES= \
${ROOT_DIR}/../src/bw_example_synth_simple.c \
${ROOT_DIR}/../../common/web/walloc.c \
${ROOT_DIR}/../../common/web/wrapper.c
all: build/web/module.wasm build/web/index.html build/web/config.js build/web/processor.js build/web/cert.pem build/web/key.pem
build/web/module.wasm: build/web ${SOURCES}
${CC} ${SOURCES} ${CFLAGS} ${LDFLAGS} -o $@
build/web/index.html: build/web ${ROOT_DIR}/index.html
cp ${ROOT_DIR}/index.html $@
build/web/processor.js: build/web ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web/processor.js
cat ${ROOT_DIR}/config.js ${ROOT_DIR}/../../common/web//processor.js > $@
build/web/config.js: build/web ${ROOT_DIR}/config.js
cp ${ROOT_DIR}/config.js $@
build/web/key.pem: build/web/cert.pem
build/web/cert.pem: build/web
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
build/web:
mkdir -p build/web
clean:
rm -fr build/web
include ${ROOT_DIR}/../../common/web/web.mk

View File

@ -1,167 +0,0 @@
<!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
<html>
<head>
<title>Brickworks web synth example</title>
<script src="config.js"></script>
<script>
var audioCtx;
var midi;
var Synth = {
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: 0,
numberOfOutputs: 1,
outputChannelCount: [ 1 ],
processorOptions: { wasmBytes: this.wasmBytes }
});
this.node.connect(audioCtx.destination);
},
noteOn: function (note, velocity) {
this.node.port.postMessage({ type: "noteOn", note: note, velocity: velocity });
},
noteOff: function (note) {
this.node.port.postMessage({ type: "noteOff", note: note });
}
};
var initState = 0; // 0 = not inited, 1 = in progress, 2 = inited
window.addEventListener("load", async function (e) {
var start = document.getElementById("start");
var starting = document.getElementById("starting");
var main = document.getElementById("main");
var controls = document.getElementById("controls");
if (!navigator.requestMIDIAccess) {
alert("This won't work. Your browser doesn't support the Web MIDI API.");
return;
}
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 = Synth.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();
midi = await navigator.requestMIDIAccess();
await Synth.init();
Synth.node.port.onmessage = function (e) { document.getElementById("p" + e.data.index).value = e.data.value; };
function onMIDIMessage(e) {
switch (e.data[0] & 0xf0) {
case 0x90:
Synth.noteOn(e.data[1], e.data[2]);
break;
case 0x80:
Synth.noteOff(e.data[1]);
break;
}
}
midi.inputs.forEach((entry) => { entry.onmidimessage = onMIDIMessage; });
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;
}
});
});
</script>
</head>
<body>
<h1>Brickworks web synth example</h1>
<input id="start" type="button" value="Start">
<p id="starting" hidden>Starting...</p>
<div id="main" hidden>
<p>Just play notes on your MIDI device.</p>
<div id="controls">
</div>
</div>
</body>
</html>