Skip to content

Commit

Permalink
simplify WebAudio Csound by using SINGLE_FILE to embed wasm into libc…
Browse files Browse the repository at this point in the history
…sound.js; embed FileList.js with --pre-js; update AudioWorklet build to use ES6 module for CsoundProcesor.js and libcsound-worklet.js
  • Loading branch information
kunstmusik committed Oct 16, 2018
1 parent cf559ad commit 155c335
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 92 deletions.
15 changes: 8 additions & 7 deletions Emscripten/build.sh
Expand Up @@ -28,28 +28,29 @@ emcc -s LINKABLE=1 -s ASSERTIONS=0 ../src/CsoundObj.c -I../../include -Iinclude


## First build for WASM/ScriptProcessorNode (async compilation = 1, assertions = 1)
emcc -v -O2 -g4 -DINIT_STATIC_MODULES=0 -s WASM=1 -s ASSERTIONS=1 -s "BINARYEN_METHOD='native-wasm'" -s LINKABLE=1 -s RESERVED_FUNCTION_POINTERS=1 -s TOTAL_MEMORY=268435456 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s BINARYEN_ASYNC_COMPILATION=1 -s MODULARIZE=1 -s EXPORT_NAME=\"'libcsound'\" -s EXTRA_EXPORTED_RUNTIME_METHODS='["FS", "ccall", "cwrap"]' CsoundObj.bc FileList.bc libcsound.a ../deps/libsndfile-1.0.25/libsndfile-wasm.a -o libcsound.js
emcc -v -O2 -g4 -DINIT_STATIC_MODULES=0 -s WASM=1 -s ASSERTIONS=1 -s "BINARYEN_METHOD='native-wasm'" -s LINKABLE=1 -s RESERVED_FUNCTION_POINTERS=1 -s TOTAL_MEMORY=268435456 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s SINGLE_FILE=1 --pre-js ../src/FileList.js -s BINARYEN_ASYNC_COMPILATION=1 -s MODULARIZE=1 -s EXPORT_NAME=\"'libcsound'\" -s EXTRA_EXPORTED_RUNTIME_METHODS='["FS", "ccall", "cwrap"]' CsoundObj.bc FileList.bc libcsound.a ../deps/libsndfile-1.0.25/libsndfile-wasm.a -o libcsound.js

## Second build for WASM/AudioWorklet (async compilation = 0, assertions = 0)
emcc -v -O2 -g4 -DINIT_STATIC_MODULES=0 -s WASM=1 -s ASSERTIONS=0 -s "BINARYEN_METHOD='native-wasm'" -s LINKABLE=1 -s RESERVED_FUNCTION_POINTERS=1 -s TOTAL_MEMORY=268435456 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s BINARYEN_ASYNC_COMPILATION=0 -s MODULARIZE=1 -s EXPORT_NAME=\"'libcsound'\" -s EXTRA_EXPORTED_RUNTIME_METHODS='["FS", "ccall", "cwrap"]' CsoundObj.bc FileList.bc libcsound.a ../deps/libsndfile-1.0.25/libsndfile-wasm.a -o libcsound-worklet.js
emcc -v -O2 -g4 -DINIT_STATIC_MODULES=0 -s WASM=1 -s ASSERTIONS=0 -s "BINARYEN_METHOD='native-wasm'" -s LINKABLE=1 -s RESERVED_FUNCTION_POINTERS=1 -s TOTAL_MEMORY=268435456 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s SINGLE_FILE=1 --pre-js ../src/FileList.js -s BINARYEN_ASYNC_COMPILATION=0 -s MODULARIZE=1 -s EXPORT_NAME=\"'libcsound'\" -s EXTRA_EXPORTED_RUNTIME_METHODS='["FS", "ccall", "cwrap"]' CsoundObj.bc FileList.bc libcsound.a ../deps/libsndfile-1.0.25/libsndfile-wasm.a -o libcsound-worklet.js

node ../convert.js
# node ../convert.js

echo "AudioWorkletGlobalScope.libcsound = libcsound" >> libcsound.js
echo "AudioWorkletGlobalScope.libcsound = libcsound" >> libcsound-worklet.js
# echo "AudioWorkletGlobalScope.libcsound = libcsound" >> libcsound-worklet.js

# --post-js does not work with MODULARIZE, use this for ES6 Module
echo "export default libcsound;" >> libcsound-worklet.js


cd ..
rm -rf dist
mkdir dist
cp src/FileList.js dist/
cp src/CsoundProcessor.js dist/
cp src/CsoundNode.js dist/
cp src/CsoundScriptProcessorNode.js dist/
cp src/CsoundObj.js dist/
cp src/csound.js dist/
cp build/libcsound.js dist/
cp build/libcsound.wasm dist/
cp build/libcsound-worklet.js dist/
cp build/libcsound-worklet.wasm.js dist/


8 changes: 3 additions & 5 deletions Emscripten/src/CsoundNode.js
Expand Up @@ -289,11 +289,9 @@ class CsoundNodeFactory {
static importScripts(script_base='./') {
let actx = CSOUND_AUDIO_CONTEXT;
return new Promise( (resolve) => {
actx.audioWorklet.addModule(script_base + 'libcsound-worklet.wasm.js').then(() => {
actx.audioWorklet.addModule(script_base + 'libcsound-worklet.js').then(() => {
actx.audioWorklet.addModule(script_base + 'CsoundProcessor.js').then(() => {
resolve();
}) }) })
actx.audioWorklet.addModule(script_base + 'CsoundProcessor.js').then(() => {
resolve();
})
})
}

Expand Down
78 changes: 39 additions & 39 deletions Emscripten/src/CsoundProcessor.js
Expand Up @@ -21,54 +21,54 @@
02110-1301 USA
*/

'use strict';
import libcsound from './libcsound-worklet.js'

const WAM = AudioWorkletGlobalScope.WAM;
const CSMOD = {}

WAM["ENVIRONMENT"] = "WEB";
WAM["print"] = (t) => console.log(t);
WAM["printErr"] = (t) => console.log(t);
CSMOD["ENVIRONMENT"] = "WEB";
CSMOD["print"] = (t) => console.log(t);
CSMOD["printErr"] = (t) => console.log(t);


// INITIALIAZE WASM
AudioWorkletGlobalScope.libcsound(WAM);
libcsound(CSMOD);

// SETUP FS

let FS = WAM["FS"];
let FS = CSMOD["FS"];



// Get cwrap-ed functions
const Csound = {

new: WAM.cwrap('CsoundObj_new', ['number'], null),
compileCSD: WAM.cwrap('CsoundObj_compileCSD', ['number'], ['number', 'string']),
evaluateCode: WAM.cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']),
readScore: WAM.cwrap('CsoundObj_readScore', ['number'], ['number', 'string']),

reset: WAM.cwrap('CsoundObj_reset', null, ['number']),
getOutputBuffer: WAM.cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']),
getInputBuffer: WAM.cwrap('CsoundObj_getInputBuffer', ['number'], ['number']),
getControlChannel: WAM.cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']),
setControlChannel: WAM.cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']),
setStringChannel: WAM.cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']),
getKsmps: WAM.cwrap('CsoundObj_getKsmps', ['number'], ['number']),
performKsmps: WAM.cwrap('CsoundObj_performKsmps', ['number'], ['number']),

render: WAM.cwrap('CsoundObj_render', null, ['number']),
getInputChannelCount: WAM.cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']),
getOutputChannelCount: WAM.cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']),
getTableLength: WAM.cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']),
getTable: WAM.cwrap('CsoundObj_getTable', ['number'], ['number', 'number']),
getZerodBFS: WAM.cwrap('CsoundObj_getZerodBFS', ['number'], ['number']),
compileOrc: WAM.cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']),
setOption: WAM.cwrap('CsoundObj_setOption', null, ['number', 'string']),
prepareRT: WAM.cwrap('CsoundObj_prepareRT', null, ['number']),
getScoreTime: WAM.cwrap('CsoundObj_getScoreTime', null, ['number']),
setTable: WAM.cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']),
pushMidiMessage: WAM.cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']),
setMidiCallbacks: WAM.cwrap('CsoundObj_setMidiCallbacks', null, ['number']),
new: CSMOD.cwrap('CsoundObj_new', ['number'], null),
compileCSD: CSMOD.cwrap('CsoundObj_compileCSD', ['number'], ['number', 'string']),
evaluateCode: CSMOD.cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']),
readScore: CSMOD.cwrap('CsoundObj_readScore', ['number'], ['number', 'string']),

reset: CSMOD.cwrap('CsoundObj_reset', null, ['number']),
getOutputBuffer: CSMOD.cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']),
getInputBuffer: CSMOD.cwrap('CsoundObj_getInputBuffer', ['number'], ['number']),
getControlChannel: CSMOD.cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']),
setControlChannel: CSMOD.cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']),
setStringChannel: CSMOD.cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']),
getKsmps: CSMOD.cwrap('CsoundObj_getKsmps', ['number'], ['number']),
performKsmps: CSMOD.cwrap('CsoundObj_performKsmps', ['number'], ['number']),

render: CSMOD.cwrap('CsoundObj_render', null, ['number']),
getInputChannelCount: CSMOD.cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']),
getOutputChannelCount: CSMOD.cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']),
getTableLength: CSMOD.cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']),
getTable: CSMOD.cwrap('CsoundObj_getTable', ['number'], ['number', 'number']),
getZerodBFS: CSMOD.cwrap('CsoundObj_getZerodBFS', ['number'], ['number']),
compileOrc: CSMOD.cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']),
setOption: CSMOD.cwrap('CsoundObj_setOption', null, ['number', 'string']),
prepareRT: CSMOD.cwrap('CsoundObj_prepareRT', null, ['number']),
getScoreTime: CSMOD.cwrap('CsoundObj_getScoreTime', null, ['number']),
setTable: CSMOD.cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']),
pushMidiMessage: CSMOD.cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']),
setMidiCallbacks: CSMOD.cwrap('CsoundObj_setMidiCallbacks', null, ['number']),

}

Expand All @@ -81,10 +81,10 @@ class CsoundProcessor extends AudioWorkletProcessor {
constructor(options) {
super(options);
let p = this.port;
WAM["print"] = (t) => {
CSMOD["print"] = (t) => {
p.postMessage(["log", t]);
};
WAM["printErr"] = (t) => {
CSMOD["printErr"] = (t) => {
p.postMessage(["log", t]);
};

Expand Down Expand Up @@ -177,9 +177,9 @@ class CsoundProcessor extends AudioWorkletProcessor {
this.cnt = ksmps;

let outputPointer = Csound.getOutputBuffer(csObj);
this.csoundOutputBuffer = new Float32Array(WAM.HEAP8.buffer, outputPointer, ksmps * this.nchnls);
this.csoundOutputBuffer = new Float32Array(CSMOD.HEAP8.buffer, outputPointer, ksmps * this.nchnls);
let inputPointer = Csound.getInputBuffer(csObj);
this.csoundInputBuffer = new Float32Array(WAM.HEAP8.buffer, inputPointer, ksmps * this.nchnls_i);
this.csoundInputBuffer = new Float32Array(CSMOD.HEAP8.buffer, inputPointer, ksmps * this.nchnls_i);
this.zerodBFS = Csound.getZerodBFS(csObj);
this.started = true;
}
Expand Down Expand Up @@ -271,7 +271,7 @@ class CsoundProcessor extends AudioWorkletProcessor {
case "getTable":
let buffer = Csound.getTable(this.csObj, data[1]);
let len = Csound.getTableLength(this.csObj, data[1]);
let src = new Float32Array(WAM.HEAP8.buffer, buffer, len);
let src = new Float32Array(CSMOD.HEAP8.buffer, buffer, len);
let table = new Float32Array(src);
p.postMessage(["table", data[1], table]);
break;
Expand Down
82 changes: 41 additions & 41 deletions Emscripten/src/CsoundScriptProcessorNode.js
Expand Up @@ -63,45 +63,45 @@ class CsoundScriptProcessorNodeFactory {
static importScripts(script_base='./') {
return new Promise((resolve) => {
CsoundScriptProcessorNodeFactory.loadScript(script_base + 'libcsound.js', () => {
AudioWorkletGlobalScope.WAM = {}
let WAM = AudioWorkletGlobalScope.WAM;
AudioWorkletGlobalScope.CSMOD = {}
let CSMOD = AudioWorkletGlobalScope.CSMOD;

WAM["ENVIRONMENT"] = "WEB";
WAM["print"] = (t) => console.log(t);
WAM["printErr"] = (t) => console.log(t);
WAM["locateFile"] = (f) => script_base + f;
//CSMOD["ENVIRONMENT"] = "WEB";
CSMOD["print"] = (t) => console.log(t);
CSMOD["printErr"] = (t) => console.log(t);
CSMOD["locateFile"] = (f) => script_base + f;

AudioWorkletGlobalScope.libcsound(WAM).then(() => {
AudioWorkletGlobalScope.libcsound(CSMOD).then(() => {

// Cache cwrap functions into CSOUND global object
CSOUND = {
new: WAM.cwrap('CsoundObj_new', ['number'], null),
compileCSD: WAM.cwrap('CsoundObj_compileCSD', ['number'], ['number', 'string']),
evaluateCode: WAM.cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']),
readScore: WAM.cwrap('CsoundObj_readScore', ['number'], ['number', 'string']),
reset: WAM.cwrap('CsoundObj_reset', null, ['number']),
getOutputBuffer: WAM.cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']),
getInputBuffer: WAM.cwrap('CsoundObj_getInputBuffer', ['number'], ['number']),
getControlChannel: WAM.cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']),
setControlChannel: WAM.cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']),
setStringChannel: WAM.cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']),
getKsmps: WAM.cwrap('CsoundObj_getKsmps', ['number'], ['number']),
performKsmps: WAM.cwrap('CsoundObj_performKsmps', ['number'], ['number']),
render: WAM.cwrap('CsoundObj_render', null, ['number']),
getInputChannelCount: WAM.cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']),
getOutputChannelCount: WAM.cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']),
getTableLength: WAM.cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']),
getTable: WAM.cwrap('CsoundObj_getTable', ['number'], ['number', 'number']),
getZerodBFS: WAM.cwrap('CsoundObj_getZerodBFS', ['number'], ['number']),
setMidiCallbacks: WAM.cwrap('CsoundObj_setMidiCallbacks', null, ['number']),
pushMidiMessage: WAM.cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']),
setOutputChannelCallback: WAM.cwrap('CsoundObj_setOutputChannelCallback', null, ['number', 'number']),
compileOrc: WAM.cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']),
setOption: WAM.cwrap('CsoundObj_setOption', null, ['number', 'string']),
prepareRT: WAM.cwrap('CsoundObj_prepareRT', null, ['number']),
getScoreTime: WAM.cwrap('CsoundObj_getScoreTime', null, ['number']),
setTable: WAM.cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']),
destroy: WAM.cwrap('CsoundObj_destroy', null, ['number'])
new: CSMOD.cwrap('CsoundObj_new', ['number'], null),
compileCSD: CSMOD.cwrap('CsoundObj_compileCSD', ['number'], ['number', 'string']),
evaluateCode: CSMOD.cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']),
readScore: CSMOD.cwrap('CsoundObj_readScore', ['number'], ['number', 'string']),
reset: CSMOD.cwrap('CsoundObj_reset', null, ['number']),
getOutputBuffer: CSMOD.cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']),
getInputBuffer: CSMOD.cwrap('CsoundObj_getInputBuffer', ['number'], ['number']),
getControlChannel: CSMOD.cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']),
setControlChannel: CSMOD.cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']),
setStringChannel: CSMOD.cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']),
getKsmps: CSMOD.cwrap('CsoundObj_getKsmps', ['number'], ['number']),
performKsmps: CSMOD.cwrap('CsoundObj_performKsmps', ['number'], ['number']),
render: CSMOD.cwrap('CsoundObj_render', null, ['number']),
getInputChannelCount: CSMOD.cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']),
getOutputChannelCount: CSMOD.cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']),
getTableLength: CSMOD.cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']),
getTable: CSMOD.cwrap('CsoundObj_getTable', ['number'], ['number', 'number']),
getZerodBFS: CSMOD.cwrap('CsoundObj_getZerodBFS', ['number'], ['number']),
setMidiCallbacks: CSMOD.cwrap('CsoundObj_setMidiCallbacks', null, ['number']),
pushMidiMessage: CSMOD.cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']),
setOutputChannelCallback: CSMOD.cwrap('CsoundObj_setOutputChannelCallback', null, ['number', 'number']),
compileOrc: CSMOD.cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']),
setOption: CSMOD.cwrap('CsoundObj_setOption', null, ['number', 'string']),
prepareRT: CSMOD.cwrap('CsoundObj_prepareRT', null, ['number']),
getScoreTime: CSMOD.cwrap('CsoundObj_getScoreTime', null, ['number']),
setTable: CSMOD.cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']),
destroy: CSMOD.cwrap('CsoundObj_destroy', null, ['number'])
}

resolve();
Expand Down Expand Up @@ -185,7 +185,7 @@ CsoundScriptProcessorNode = function(context, options) {
* @memberof CsoundMixin
*/
writeToFS(filePath, blobData) {
let FS = WAM["FS"];
let FS = CSMOD["FS"];
let stream = FS.open(filePath, 'w+');
let buf = new Uint8Array(blobData)
FS.write(stream, buf, 0, buf.length, 0);
Expand Down Expand Up @@ -309,7 +309,7 @@ CsoundScriptProcessorNode = function(context, options) {
requestTable(number, callback = null) {
let buffer = CSOUND.getTable(this.csound, number);
let len = CSOUND.getTableLength(this.csound, number);
let src = new Float32Array(WAM.HEAP8.buffer, buffer, len);
let src = new Float32Array(CSMOD.HEAP8.buffer, buffer, len);
this.table[number] = new Float32Array(src);
if (callback !== null)
this.tableCallback[number] = callback;
Expand Down Expand Up @@ -356,9 +356,9 @@ CsoundScriptProcessorNode = function(context, options) {
this.cnt = ksmps;

let outputPointer = CSOUND.getOutputBuffer(this.csound);
this.csoundOutputBuffer = new Float32Array(WAM.HEAP8.buffer, outputPointer, ksmps * this.nchnls);
this.csoundOutputBuffer = new Float32Array(CSMOD.HEAP8.buffer, outputPointer, ksmps * this.nchnls);
let inputPointer = CSOUND.getInputBuffer(this.csound);
this.csoundInputBuffer = new Float32Array(WAM.HEAP8.buffer, inputPointer, ksmps * this.nchnls_i);
this.csoundInputBuffer = new Float32Array(CSMOD.HEAP8.buffer, inputPointer, ksmps * this.nchnls_i);
this.zerodBFS = CSOUND.getZerodBFS(this.csound);
this.started = true;
}
Expand Down Expand Up @@ -481,9 +481,9 @@ CsoundScriptProcessorNode = function(context, options) {
}
}

let WAM = AudioWorkletGlobalScope.WAM;
WAM["print"] = (t) => spn.msgCallback(t);
WAM["printErr"] = (t) => spn.msgCallback(t);
let CSMOD = AudioWorkletGlobalScope.CSMOD;
CSMOD["print"] = (t) => spn.msgCallback(t);
CSMOD["printErr"] = (t) => spn.msgCallback(t);

return Object.assign(spn,CsoundMixin);
}
Expand Down

0 comments on commit 155c335

Please sign in to comment.