From 0a0004ec1492672627d052f3c1b3e669603d0942 Mon Sep 17 00:00:00 2001 From: Alexander Wallin Date: Tue, 21 Aug 2018 10:34:45 +0200 Subject: [PATCH] (audio-worklets) Adds --worklet option which outputs a WASMed bundle of AudioWorkletProcessors --- compile.js | 39 +++++++++++-- emscripten/post-worklet.js | 109 +++++++++++++++++++++++++++++++++++++ emscripten/pre-worklet.js | 3 + 3 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 emscripten/post-worklet.js create mode 100644 emscripten/pre-worklet.js diff --git a/compile.js b/compile.js index 550e0a4..09ed592 100644 --- a/compile.js +++ b/compile.js @@ -21,6 +21,11 @@ const inputArgs = yargs type: 'boolean', description: 'Exports library as a CommonJS module', }) + .option('worklet', { + alias: 'w', + type: 'boolean', + description: 'Exports library as an AudioWorkletProcessor', + }) .option('debug', { type: 'boolean', description: @@ -30,10 +35,19 @@ const inputArgs = yargs .alias('help', 'h') .argv -// Filename -let outputFilename = inputArgs.module === true - ? '3dti-toolkit.module.js' - : '3dti-toolkit.js' +// Filenames +let outputFilename = '3dti-toolkit.js' +let preJsFilename = 'pre.js' +let postJsFilename = 'post-browser.js' + +if (inputArgs.module === true) { + outputFilename = '3dti-toolkit.module.js' + postJsFilename = 'post-module.js' +} else if (inputArgs.worklet === true) { + outputFilename = '3dti-toolkit.worklet.js' + preJsFilename = 'pre-worklet.js' + postJsFilename = 'post-worklet.js' +} if (inputArgs.debug === true) { outputFilename = outputFilename.replace(/\.js$/, '.debug.js') @@ -53,11 +67,22 @@ let args = [ '-s', 'ASSERTIONS=0', '-s', 'ABORTING_MALLOC=0', // '-s', 'NO_FILESYSTEM=1', - '-s', 'ALLOW_MEMORY_GROWTH=1', + '-s', `ALLOW_MEMORY_GROWTH=${inputArgs.worklet === true ? '0' : '1'}`, '--pre-js', './emscripten/pre.js', - '--post-js', `./emscripten/post-${inputArgs.module ? 'module' : 'browser'}.js`, + '--post-js', `./emscripten/${postJsFilename}`, ] +// Worklet options +if (inputArgs.worklet === true) { + args = [ + ...args, + '-s', 'WASM=1', + // '-s', 'ENVIRONMENT="worker"', + '-s', 'SINGLE_FILE=1', + '-s', 'BINARYEN_ASYNC_COMPILATION=0', + ] +} + // Code optimisation args if (inputArgs.debug === true) { args = [ @@ -88,6 +113,8 @@ globby(globPatterns) ...filePaths, ])) .then(finalArgs => { + console.log(finalArgs) + // return false return exec('emcc', finalArgs, {}) }) .then(() => console.log('Done!')) diff --git a/emscripten/post-worklet.js b/emscripten/post-worklet.js new file mode 100644 index 0000000..a0eccb2 --- /dev/null +++ b/emscripten/post-worklet.js @@ -0,0 +1,109 @@ + return Module +} + +const Toolkit = AudioToolkit() + +/* global AudioWorkletProcessor */ +/* eslint camelcase: 0 */ +/* eslint new-cap: 0 */ +/* eslint no-param-reassign: 0 */ + +function getFloatVectorFromArray(arr) { + const vector = new Toolkit.FloatVector() + for (let i = 0; i < arr.length; i++) { + vector.push_back(arr[i]) + } + return vector +} + +const SAMPLING_RATE = 44100 +const NUM_EQ_LEVELS = 3 +const INITIAL_FREQ = 125 +const NUM_EQ_BANDS = 7 +const OCTAVE_BAND_STEP = 1 +const LPF_FREQ = 20000 +const HPF_FREQ = 0 +const Q_LPF = 0.707 +const Q_BPF = 1.4142 +const Q_HPF = 0.707 +const dBs_SPL_for_0_dBs_fs = 100 + +class HearingAidProcessor extends AudioWorkletProcessor { + constructor() { + super() + + // Set up the hearing aid simulator + this.has = new Toolkit.CHearingAidSim() + this.has.Setup( + SAMPLING_RATE, + NUM_EQ_LEVELS, + INITIAL_FREQ, + NUM_EQ_BANDS, + OCTAVE_BAND_STEP, + LPF_FREQ, + HPF_FREQ, + Q_LPF, + Q_BPF, + Q_HPF + ) + this.has.GetDynamicEqualizer(Toolkit.T_ear.LEFT).EnableLevelsInterpolation() + this.has.GetDynamicEqualizer(Toolkit.T_ear.RIGHT).EnableLevelsInterpolation() + this.has.EnableHearingAidSimulation(Toolkit.T_ear.BOTH) + + // Create buffers with a buffer size of 2 * 128 (AudioWorkletProcessor + // use a fixed "render quantum", or block size, of 128 bytes). + this.inputStereoBuffer = new Toolkit.EarPairBuffers() + this.outputStereoBuffer = new Toolkit.EarPairBuffers() + this.inputStereoBuffer.Resize(128, 0) + this.outputStereoBuffer.Resize(128, 0) + + // Allow audiograms to be set over port messaging + this.port.addEventListener('message', this.handleMessage.bind(this)) + this.port.start() + + console.log('HearingAidProcessor') + } + + handleMessage(evt) { + const { data } = evt + + console.log(evt) + + if (data.key === 'leftEarAudiogram') { + this.has.SetDynamicEqualizerUsingFig6( + Toolkit.T_ear.LEFT, + getFloatVectorFromArray(data.value), + dBs_SPL_for_0_dBs_fs + ) + } + if (data.key === 'rightEarAudiogram') { + this.has.SetDynamicEqualizerUsingFig6( + Toolkit.T_ear.RIGHT, + getFloatVectorFromArray(data.value), + dBs_SPL_for_0_dBs_fs + ) + } + } + + process(inputs, outputs) { + if (this.has === null) { + return true + } + + for (let i = 0; i < 128; i++) { + this.inputStereoBuffer.Set(Toolkit.T_ear.LEFT, i, inputs[0][0][i]) + this.inputStereoBuffer.Set(Toolkit.T_ear.RIGHT, i, inputs[0][1][i]) + } + + Toolkit.HearingAidSim_Process(this.has, this.inputStereoBuffer, this.outputStereoBuffer) + + for (let i = 0; i < 128; i++) { + outputs[0][0][i] = this.outputStereoBuffer.Get(Toolkit.T_ear.LEFT, i) + outputs[0][1][i] = this.outputStereoBuffer.Get(Toolkit.T_ear.RIGHT, i) + } + + return true + } +} + +registerProcessor('HearingAidProcessor', HearingAidProcessor) diff --git a/emscripten/pre-worklet.js b/emscripten/pre-worklet.js new file mode 100644 index 0000000..86d7677 --- /dev/null +++ b/emscripten/pre-worklet.js @@ -0,0 +1,3 @@ +var AudioToolkit = function(Module) { + Module = Module || {}; + Module['ENIVIRONMENT'] = 'WORKER';