Skip to content

Commit

Permalink
Optimize asset loading & caching
Browse files Browse the repository at this point in the history
only fetch each resource from the network once,
and only compile each wasm module once
  • Loading branch information
Smona committed Jun 30, 2021
1 parent ad0162f commit 8c6ff65
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "faust-loader",
"version": "1.1.1",
"version": "1.2.0",
"main": "dist/faustLoader.js",
"types": "dist/faustLoader.d.ts",
"scripts": {
Expand Down
59 changes: 39 additions & 20 deletions src/loadProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,39 @@ function heap2Str(buf: Uint8Array) {
return str;
}

const loadedProcessors: string[] = [];
const processorModules: Record<string, Promise<void>> = {};
async function loadProcessorModule(context: IAudioContext, url: string) {
if (!context.audioWorklet) {
console.error(
"Error loading FaustAudioProcessorNode: standardized-audio-context AudioWorklet isn't supported in this environment."
);
return null;
}

const existing = processorModules[url];

if (existing) {
return existing;
}

processorModules[url] = context.audioWorklet.addModule(url);
return processorModules[url];
}

const wasmModules: Record<string, Promise<WebAssembly.Module>> = {};
async function getWasmModule(url: string) {
const existing = wasmModules[url];

if (existing) {
return existing;
}

wasmModules[url] = fetch(url)
.then((response) => response.arrayBuffer())
.then((dspBuffer) => WebAssembly.compile(dspBuffer));
return wasmModules[url];
}

const importObject = {
env: {
memoryBase: 0,
Expand Down Expand Up @@ -81,32 +113,19 @@ export default async function loadProcessor(
baseURL: string
) {
const cleanedBaseURL = baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
// Load DSP wasm
const dspFile = await fetch(`${cleanedBaseURL}${name}.wasm`);
const dspBuffer = await dspFile.arrayBuffer();
const dspModule = await WebAssembly.compile(dspBuffer);

const [dspModule] = await Promise.all([
getWasmModule(`${cleanedBaseURL}${name}.wasm`),
loadProcessorModule(context, `${cleanedBaseURL}${name}-processor.js`),
]);

const dspInstance = await WebAssembly.instantiate(dspModule, importObject);

const HEAPU8 = new Uint8Array(dspInstance.exports.memory.buffer);
const json = heap2Str(HEAPU8);
const json_object = JSON.parse(json);
const processorOptions = { wasm_module: dspModule, json: json };

if (!context.audioWorklet) {
console.error(
"Error loading FaustAudioProcessorNode: standardized-audio-context AudioWorklet isn't supported in this environment."
);
return null;
}

// Load processor script, if necessary
if (!loadedProcessors.includes(name)) {
await context.audioWorklet.addModule(
`${cleanedBaseURL}${name}-processor.js`
);
loadedProcessors.push(name);
}

const nodeOptions = {
numberOfInputs: parseInt(json_object.inputs) > 0 ? 1 : 0,
numberOfOutputs: parseInt(json_object.outputs) > 0 ? 1 : 0,
Expand Down
9 changes: 6 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { AudioContext } from "standardized-audio-context";
import createCompressor from "./Compressor.dsp";

const ctx = new AudioContext();
createCompressor(ctx).then((node) => {
console.log(node);
console.log(node.getParams());
Promise.all([
createCompressor(ctx),
createCompressor(ctx),
createCompressor(ctx),
]).then((nodes) => {
console.log(nodes);
});

0 comments on commit 8c6ff65

Please sign in to comment.