Public: anyone can read this; the crew can change it.
forked from trevato/cs
A sound says which side it came from: the ear has a heading, and the engine pans what it hears #217
Check · Review · Land · Live done — Landed and live in production.
`src/engine/sound.ts` grows `panOf(source, ear, yaw)` beside `attenuate`: the component of the direction to a sound along the ear's right — `right = (sin yaw, −cos yaw, 0)`, the same degrees `angleVectors` takes — divided by the distance, or by `HEAD` (64 Source units, about a stride) when that is larger. That gives −1 hard left, +1 hard right, and 0 dead ahead, dead behind, straight overhead or o…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/engine/sound.tsgrowspanOf(source, ear, yaw)besideattenuate: the component of the direction to a sound along the ear's right —right = (sin yaw, −cos yaw, 0), the same degreesangleVectorstakes — divided by the distance, or byHEAD(64 Source units, about a stride) when that is larger. That gives −1 hard left, +1 hard right, and 0 dead ahead, dead behind, straight overhead or on top of the ear, with the near-head softening falling out of the same division rather than needing a branch: a body walking through you slides to centre and out the other side instead of flipping speakers in one frame.BurstandTonegain an optionalpan. A voice that carries one ends on aStereoPannerNodeinto the destination instead of the destination itself; the value is clamped to −1..1 with NaN and infinities landing at centre before any node sees it. A voice with nopanbuilds no panner and is wired byte-for-byte as before — which is what the range does today — and a context with nocreateStereoPannerfalls back to the destination rather than throwing, so the three hand-written fakes and the oldest Safari all play the sound centred.The shooter's
shotandplaynow take the ear's heading as well as its position and hand the pan they compute to every voice of every recipe;src/client/main.tspassesears.yaw. Your own boots are passed no pan at all, and your own gun is fired from the ear that hears it, so it works out centred without a special case.Front and back are deliberately not in the answer: two speakers cannot say the difference, and the only honest way to would be a per-voice head model this game does not want.
Worth a look: the
panOftable and the no-panner path insrc/engine/sound.test.ts; the recorder tests insrc/client/audio.test.ts(a step 300 units left of a north-facing ear is −1, right is +1, ahead is 0, and every node of every named noise carries the same pan); andsrc/client/main.test.ts, where the stage helper now records the heading handed to the voice, so a frame that played from one player's eye with another's yaw would fail.src/range/stage.test-helper.tsandsrc/range/audio.test.tsgrewcreateStereoPanneron their doubles — not because the range pans, but because a double that answers less than a browser is how the thrown frame hides. The committed bundles are rebuilt and all three stay under their ceilings. No dependencies added;bun run testis 972 passing.🤖 Generated with Claude Code
Closes #209