Summary
Ambisonic/positional-FOA spatialization is set up only inside the if (!sound.isPlaying) branch, so replaying an already-playing key with upmix: "ambisonic" never gets a spatial renderer and stays flat until a follow-up Update.
Details
src/audio/MediaService.ts:332-354 — the whole if (data.upmix === 'ambisonic') block sits inside if (!sound.isPlaying):
if (!sound.isPlaying) {
const [playback] = sound.play({...});
...
if (data.upmix === 'ambisonic') {
const inputChannels = this.resolveAmbisonicInputChannels(sound, data);
const target = await this.resolveAmbisonicTarget(sound, soundKey, data);
if (inputChannels === 4) { await this.configureAmbisonicPlayback(...); }
else { await this.configurePositionalFoa(...); }
}
}
If play() is called for a key whose sound is already playing, the outer guard is false and the ambisonic setup is skipped entirely, so the sound remains non-spatialized. Only a subsequent Update (:384-391) recovers it.
Fix direction
Move the upmix === 'ambisonic' setup out of the !sound.isPlaying guard, or (re)apply the renderer whenever the payload requests ambisonic regardless of current play state.
Verification
Read src/audio/MediaService.ts (play) end to end.
Summary
Ambisonic/positional-FOA spatialization is set up only inside the
if (!sound.isPlaying)branch, so replaying an already-playing key withupmix: "ambisonic"never gets a spatial renderer and stays flat until a follow-upUpdate.Details
src/audio/MediaService.ts:332-354— the wholeif (data.upmix === 'ambisonic')block sits insideif (!sound.isPlaying):If
play()is called for a key whose sound is already playing, the outer guard is false and the ambisonic setup is skipped entirely, so the sound remains non-spatialized. Only a subsequentUpdate(:384-391) recovers it.Fix direction
Move the
upmix === 'ambisonic'setup out of the!sound.isPlayingguard, or (re)apply the renderer whenever the payload requests ambisonic regardless of current play state.Verification
Read
src/audio/MediaService.ts(play) end to end.