Skip to content

Recover AudioStream when system audio output device changes#274

Open
MaxHeimbrock wants to merge 2 commits intomainfrom
max/audiostream-replay-on-device-change
Open

Recover AudioStream when system audio output device changes#274
MaxHeimbrock wants to merge 2 commits intomainfrom
max/audiostream-replay-on-device-change

Conversation

@MaxHeimbrock
Copy link
Copy Markdown
Contributor

@MaxHeimbrock MaxHeimbrock commented May 7, 2026

Summary

  • Fixes AudioStream going silent on macOS / Android after the system audio output device changes (e.g. unplugging headphones), where the only previous workaround was disconnecting and re-subscribing the participant.
  • Subscribes to AudioSettings.OnAudioConfigurationChanged and, in the handler, destroys the existing AudioProbe + AddComponents a fresh one and Stop()/Play()s the AudioSource. The ring buffer is cleared and re-primed so we don't drain stale frames buffered during the device-change blackout.

Why re-Play() alone isn't enough

Unity tears down its native audio engine on device changes (macOS / AAudio). AudioSources are stopped, but more importantly the OnAudioFilterRead registration of AudioProbe lives on the DSP graph and is detached during the rebuild. Unity only re-registers filter components added after the rebuild — so we have to recreate the AudioProbe to get the filter slot back. iOS doesn't hit this because route changes there don't rebuild the engine.

Test plan

  • macOS Editor: unplug/plug headphones during a call — audio resumes on the new device without disconnecting the participant.
  • Android: same flow, with both wired and Bluetooth route changes.
  • iOS: regression check — route changes still work as before (no behavior change expected).
  • EditMode tests pass (MediaStreamLifetimeTests updated for the new unsubscribe).

🤖 Generated with Claude Code

MaxHeimbrock and others added 2 commits May 7, 2026 10:32
Unity stops every AudioSource during the audio engine reset that follows a
system output device change (per AudioSettings.OnAudioConfigurationChanged
docs). Without re-playing the source, OnAudioFilterRead stops firing and
the AudioStream goes silent until recreated. Subscribe to the event,
re-Play() the source, and clear the ring buffer so we don't drain stale
frames accumulated during the device-change blackout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Calling _audioSource.Play() alone isn't enough to recover after Unity
tears down the audio engine: the OnAudioFilterRead node from the
existing AudioProbe stays detached from the rebuilt audio graph and
no callbacks fire. Destroy the old probe, AddComponent a fresh one,
and Stop()/Play() the source so Unity re-registers the filter node.
Also drop the deviceWasChanged gate (programmatic Reset() needs the
same recovery) and switch to a visible Debug.Log so the event firing
can be confirmed in the Console.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MaxHeimbrock MaxHeimbrock force-pushed the max/audiostream-replay-on-device-change branch from 17e73ed to 9e4af91 Compare May 7, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant