[claude] 3D audio positioning — sounds come from their source (#239) #352

Merged
Timmy merged 1 commits from claude/issue-239 into main 2026-03-24 05:25:10 +00:00
Member

Fixes #239

What changed

  • updateAudioListener() — called every animation frame to sync the Web Audio API listener position and orientation with the Three.js camera. This is the core of spatial audio: as the camera moves or orbits, the left/right/distance cues update in real time.

  • createPanner(x, y, z) — helper that creates an HRTF PannerNode at a world-space coordinate. Uses inverse rolloff so distant sources fade naturally.

  • Portal humsstartPortalHums() attaches a quiet positional sine hum to each portal at its world position. The Morrowind portal (right), Bannerlord portal (left), and Workshop portal (behind) each have a distinct sub-bass pitch. They pan as the listener orbits. Safe to call multiple times; triggers from both startAmbient() and loadPortals() whichever fires second.

  • Positional sparkle plucks — Previously sparkles went directly to masterGain (mono-everywhere). Now each pluck spawns at a random 3D point floating above the platform, so sparkles drift in from different directions and heights. Panners are self-cleaning via osc.addEventListener("ended", ...).

  • stopAmbient() cleanup — disconnects and clears positionedPanners, resets portalHumsStarted so a fresh restart is clean.

Fixes #239 ## What changed - **`updateAudioListener()`** — called every animation frame to sync the Web Audio API `listener` position and orientation with the Three.js camera. This is the core of spatial audio: as the camera moves or orbits, the left/right/distance cues update in real time. - **`createPanner(x, y, z)`** — helper that creates an HRTF `PannerNode` at a world-space coordinate. Uses inverse rolloff so distant sources fade naturally. - **Portal hums** — `startPortalHums()` attaches a quiet positional sine hum to each portal at its world position. The Morrowind portal (right), Bannerlord portal (left), and Workshop portal (behind) each have a distinct sub-bass pitch. They pan as the listener orbits. Safe to call multiple times; triggers from both `startAmbient()` and `loadPortals()` whichever fires second. - **Positional sparkle plucks** — Previously sparkles went directly to `masterGain` (mono-everywhere). Now each pluck spawns at a random 3D point floating above the platform, so sparkles drift in from different directions and heights. Panners are self-cleaning via `osc.addEventListener("ended", ...)`. - **`stopAmbient()` cleanup** — disconnects and clears `positionedPanners`, resets `portalHumsStarted` so a fresh restart is clean.
claude added 1 commit 2026-03-24 05:15:12 +00:00
feat: 3D audio positioning — sounds come from the direction of their source
Some checks failed
CI / validate (pull_request) Failing after 15s
CI / auto-merge (pull_request) Has been skipped
0715d93d08
- Add updateAudioListener() called each frame to sync the Web Audio API
  listener position/orientation with the Three.js camera
- Add createPanner() helper for HRTF-positioned sound sources
- Sparkle plucks now spawn at random 3D positions floating above the
  platform so they drift in from all directions
- Add startPortalHums(): each portal emits a quiet positional hum at its
  world coordinate (x, y, z) so portals can be heard panning as the
  listener orbits; hums start when both audio and portal data are ready
- stopAmbient() disconnects and clears all positionedPanners and resets
  portalHumsStarted so restart is clean

Fixes #239

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Timmy merged commit 68aca2c23d into main 2026-03-24 05:25:10 +00:00
Sign in to join this conversation.