Skip to content

Commit

Permalink
parallelize webchuck load time (2x faster)
Browse files Browse the repository at this point in the history
  • Loading branch information
terryzfeng committed Nov 10, 2024
1 parent 52afa5e commit 37959ef
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 19 deletions.
10 changes: 6 additions & 4 deletions dist/Chuck.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,19 @@ export default class Chuck extends window.AudioWorkletNode {
* @returns WebChucK ChucK instance
*/
static async init(filenamesToPreload, audioContext, numOutChannels = 2, whereIsChuck = "https://chuck.stanford.edu/webchuck/src/") {
const wasm = await loadWasm(whereIsChuck);
let defaultAudioContext = false;
// If an audioContext is not given, create a default one
// If audioContext is undefined, create new AudioContext
if (audioContext === undefined) {
audioContext = new AudioContext();
defaultAudioContext = true;
}
await audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js");
// Add Chugins to filenamesToPreload
filenamesToPreload = filenamesToPreload.concat(Chuck.chuginsToLoad);
const preloadedFiles = await preloadFiles(filenamesToPreload);
const [wasm, _, preloadedFiles] = await Promise.all([
loadWasm(whereIsChuck),
audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js"),
preloadFiles(filenamesToPreload),
]);
const chuck = new Chuck(preloadedFiles, audioContext, wasm, numOutChannels);
// Remember the chugins that were loaded
chuck.chugins = Chuck.chuginsToLoad.map((chugin) => chugin.virtualFilename.split("/").pop());
Expand Down
2 changes: 1 addition & 1 deletion dist/accel/Accel.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default class Accel {
handleMotion(event) {
this.accelActive();
if (this._accelActive) {
if (event.acceleration != null) {
if (event.acceleration !== null) {
this.theChuck.setFloat("_accelX", event.acceleration.x ? event.acceleration.x : 0.0);
this.theChuck.setFloat("_accelY", event.acceleration.y ? event.acceleration.y : 0.0);
this.theChuck.setFloat("_accelZ", event.acceleration.z ? event.acceleration.z : 0.0);
Expand Down
2 changes: 1 addition & 1 deletion dist/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export async function preloadFiles(filenamesToPreload) {
return await Promise.all(promises);
}
export async function loadWasm(whereIsChuck) {
return await new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
asyncLoadFile(whereIsChuck + "webchuck.wasm", resolve, reject);
});
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"test": "npm run build && bash ./test.sh",
"clean": "rm -rf dist/ && rm -rf docs/ && rm -rf src/wc-bundle.js",
"doc": "typedoc --out docs src/index.ts",
"format": "prettier --write src/**/*.ts",
"format": "prettier --write src/*.ts src/**/*.ts",
"prepare": "npm run build",
"postversion": "git push && git push --tags"
},
Expand Down
9 changes: 5 additions & 4 deletions src/Chuck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,21 @@ export default class Chuck extends window.AudioWorkletNode {
numOutChannels: number = 2,
whereIsChuck: string = "https://chuck.stanford.edu/webchuck/src/", // default Chuck src location
): Promise<Chuck> {
const wasm = await loadWasm(whereIsChuck);

let defaultAudioContext: boolean = false;
// If an audioContext is not given, create a default one
if (audioContext === undefined) {
audioContext = new AudioContext();
defaultAudioContext = true;
}
await audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js");

// Add Chugins to filenamesToPreload
filenamesToPreload = filenamesToPreload.concat(Chuck.chuginsToLoad);

const preloadedFiles = await preloadFiles(filenamesToPreload);
const [wasm, _, preloadedFiles] = await Promise.all([
loadWasm(whereIsChuck),
audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js"),
preloadFiles(filenamesToPreload),
]);

const chuck = new Chuck(preloadedFiles, audioContext, wasm, numOutChannels);

Expand Down
2 changes: 1 addition & 1 deletion src/gyro/Gyro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default class Gyro {
* This adds a `Gyro` and `GyroMsg` class to the ChucK Virtual Machine (VM).
* Gyrscope event (DeviceOrientationEvent) listeners are added if `enableGyro`
* is true (default).
*
*
* @example
* ```ts
* theChuck = await Chuck.init([]);
Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export async function preloadFiles(filenamesToPreload: Filename[]): Promise<File
}

export async function loadWasm(whereIsChuck: string): Promise<ArrayBuffer> {
return await new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
asyncLoadFile(whereIsChuck + "webchuck.wasm", resolve, reject);
});
}
Expand Down
14 changes: 8 additions & 6 deletions src/wc-bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async function preloadFiles(filenamesToPreload) {
return await Promise.all(promises);
}
async function loadWasm(whereIsChuck) {
return await new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
asyncLoadFile(whereIsChuck + "webchuck.wasm", resolve, reject);
});
}
Expand Down Expand Up @@ -284,17 +284,19 @@ class Chuck extends window.AudioWorkletNode {
* @returns WebChucK ChucK instance
*/
static async init(filenamesToPreload, audioContext, numOutChannels = 2, whereIsChuck = "https://chuck.stanford.edu/webchuck/src/") {
const wasm = await loadWasm(whereIsChuck);
let defaultAudioContext = false;
// If an audioContext is not given, create a default one
// If audioContext is undefined, create new AudioContext
if (audioContext === undefined) {
audioContext = new AudioContext();
defaultAudioContext = true;
}
await audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js");
// Add Chugins to filenamesToPreload
filenamesToPreload = filenamesToPreload.concat(Chuck.chuginsToLoad);
const preloadedFiles = await preloadFiles(filenamesToPreload);
const [wasm, _, preloadedFiles] = await Promise.all([
loadWasm(whereIsChuck),
audioContext.audioWorklet.addModule(whereIsChuck + "webchuck.js"),
preloadFiles(filenamesToPreload),
]);
const chuck = new Chuck(preloadedFiles, audioContext, wasm, numOutChannels);
// Remember the chugins that were loaded
chuck.chugins = Chuck.chuginsToLoad.map((chugin) => chugin.virtualFilename.split("/").pop());
Expand Down Expand Up @@ -1961,7 +1963,7 @@ class Accel {
handleMotion(event) {
this.accelActive();
if (this._accelActive) {
if (event.acceleration != null) {
if (event.acceleration !== null) {
this.theChuck.setFloat("_accelX", event.acceleration.x ? event.acceleration.x : 0.0);
this.theChuck.setFloat("_accelY", event.acceleration.y ? event.acceleration.y : 0.0);
this.theChuck.setFloat("_accelZ", event.acceleration.z ? event.acceleration.z : 0.0);
Expand Down
44 changes: 44 additions & 0 deletions test/speed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebChucK Load Test</title>
</head>

<body>
<h1>WebChucK Load Speed Test</h1>
<p id="load-time">loading...</p>
<button id="action" disabled>Start and Play</button>

<script type="module">

const start = performance.now();
import { Chuck } from '../src/wc-bundle.js';
const theChuck = await Chuck.init([]);
const end = performance.now();
// print in milliseconds
const time = (end - start).toFixed(2);
document.getElementById('load-time').textContent = `load time: ${time} ms`;



document.getElementById('action').disabled = false;

document.getElementById('action').addEventListener('click', async () => {
// Initialize default ChucK object
if (theChuck.context.state === "suspended") {
await theChuck.context.resume();
}
// Run ChucK code
theChuck.runCode(`
SinOsc sin => dac;
440 => sin.freq;
1::second => now;
`);
});
</script>
</body>

</html>

0 comments on commit 37959ef

Please sign in to comment.