webaudio

sandbox

What this shows

Three flat-shaded spheres carry positional sound sources over a grid; click to start the audio, then walk with WASD and drag to look while each sphere glows with its sound's loudness.

Side by side with the three.js r186 original: webaudio_sandbox.html

Differences from three.js

  • Both sides start with the scene already rendered and build the audio graph on the first click on their own canvas, instead of waiting for the upstream START button; cleanup stops every source and closes that side's AudioContext.
  • The upstream music tracks 358232 and 376737 are CC BY-NC-SA and are not copied, so both sides substitute generated audio: a sawtooth pulsing twice a second on the first sphere and a fast square beat on the second, built from OscillatorNode and GainNode.
  • The CC0 Project_Utopia ambience is also replaced by a generated slow triangle swell, because the asset was not copied into this repository; it plays as a node source instead of a looping media element.
  • The generated sources start at once and never end, where the two upstream songs play through once.
  • EASEL has no Phong material, so the spheres use flat-shaded LambertMaterial without specular.
  • EASEL's AudioAnalyzer takes an AudioContext and options, so the port creates one per sphere with fftSize 32 and attaches it to that sound's output, where three.js passes the sound to AudioAnalyser.
  • EASEL FogExp2 evaluates fog per vertex from a lookup table, so the fog fades across each face instead of per pixel.
EASEL (Canvas2D)
This example needs a canvas-capable browser.

Loading scene…

three.js r186 (WebGL)
This example needs a canvas-capable browser.

Loading scene…

Loading scene…

Key API excerpt

import * as EASEL from "@xsyetopz/easel";


canvas.addEventListener("click", () => {
  const context = new AudioContext();
  EASEL.setAudioContext(context);

  const listener = new EASEL.AudioListener();
  camera.add(listener);

  const sound = new EASEL.PositionalAudio(listener);
  const oscillator = context.createOscillator();
  oscillator.start(0);
  sound.setNodeSource(oscillator);
  sound.refDistance = 20;
  sound.volume = 0.5;
  mesh.add(sound);

  analyser = new EASEL.AudioAnalyzer(context, { fftSize: 32 }).attach(sound.output);
});

material.emissive.b = analyser.averageFrequency / 256;

controls.update(timer.update(timestamp).delta);
renderer.prepare(scene, camera);
renderer.render(scene, camera);