DEVICE SELECTION & RENDER FORMATS

Unreal Engine 5

Unreal grants runtime audio device switching to Windows and Linux only; the Mac backend shipped with TODO stubs, no enumeration, and a single stream on the system default, so changing outputs meant restarting the game. Even Lyra's own platform config leaves macOS off the SupportsChangingAudioOutputDevice trait.

I implemented the Mac device layer end to end: Core Audio enumeration with stable UID identity, direct HAL device targeting, live device swap through the first Mac implementation of FAudioMixerPlatformSwappable, a render-format cap for user-selectable output formats, and a watcher that applies both without a restart. Swaps measure 19 to 63 ms, including full 5.1 to stereo format changes mid-session.

Unreal Engine Source 5.8 (fork) · C++ / Core Audio HAL · Companion branch to the multichannel pull request, in review with Epic

Every Output, Stable Identity

The backend queries the HAL for every output-capable device and identifies each by its driver UID, so a selection survives renames, unplugs, and reboots. au.Mac.ListOutputDevices prints a live indexed list with the current system default resolved at index zero; the list re-queries on every call, so devices appearing and disappearing, and default changes made in macOS, show up immediately.

Cmd: au.Mac.ListOutputDevices
  [0] System default (Universal Audio Thunderbolt)
  [1] LG ULTRAWIDE (2 channels)
  [2] C32F39M (2 channels)
  [3] Odyssey G5 (2 channels)
  [4] DualSense Wireless Controller (4 channels)
  [5] MacBook Pro Speakers (2 channels)
  [6] Microsoft Teams Audio (2 channels)
  [7] Pro Tools Audio Bridge 16 (16 channels)
  [8] Pro Tools Audio Bridge 2-A (2 channels)
  [9] Pro Tools Audio Bridge 2-B (2 channels)
 [10] Pro Tools Audio Bridge 32 (32 channels)
 [11] Pro Tools Audio Bridge 64 (64 channels)
 [12] Pro Tools Audio Bridge 6 (6 channels)
 [13] Pro Tools Aggregate I/O (2 channels)
 [14] Universal Audio Thunderbolt (88 channels)
 [15] ZoomAudioDevice (2 channels)

19 to 63 ms, Mid-Session

The swap path tears down the audio unit graph, retargets the HAL device, rebuilds the stream at the new device's declared layout, and re-initializes the output buffers to the new channel math before playback resumes, all without dropping mixer state. Format changes ride the same path: an 88-output Apollo rendering 5.1 hands off to the MacBook's stereo speakers and back, measured between 19 and 63 ms per swap. Sounds continue where they left off on the new device.

Cmd: au.Mac.OutputDevice 12
Attempt to swap audio render device to new device: '12', because: 'Mac audio output settings changed'
Output device: Pro Tools Audio Bridge 6 (Pro Tools Audio Bridge 6_UID)
Device preferred channel layout, 6 descriptions: [0]=Left(1) [1]=Right(2) [2]=Center(3) [3]=LFEScreen(4) [4]=LeftSurround(5) [5]=RightSurround(6)
Channel map: FrontLeft = 0, FrontRight = 1, FrontCenter = 2, LowFrequency = 3, BackLeft = 4, BackRight = 5
Rendering 6 channels (device has 6 outputs)
Device swap complete: 'Pro Tools Audio Bridge 6' (37.49 ms)
FAudioMixerPlatformSwappable::ResumePlaybackOnNewDevice - resuming audio on new device

Stereo, 5.1, 7.1 On Demand

au.Mac.MaxOutputChannels caps the parsed channel list before the render decision, so a cap of two lands in the engine's original stereo path byte for byte, and six or eight render discrete surround on capable hardware. This is the engine hook behind the player-facing Audio Output preset: 3D Headphones, Stereo, or 5.1 Home Theater, switching live from the settings menu. The format watcher forces a same-device swap when the cap changes, so the new render format applies in the same tens of milliseconds as a device change.

Console to Settings Menu

A hardware-update watcher polls the device and format CVars and requests swaps live. au.Mac.OutputDevice accepts a listed index, a device name, or a UID, where '0' or default returns to the system default. A same-device swap doubles as a configuration reload, picking up Audio MIDI Setup speaker changes in about 25 ms with no restart. In case of a channel mismatch, the layout diagnostic logging rounds out the toolset. Every device initialization prints what the device reports (channel descriptions, a layout tag, or nothing) and the final channel map built from it, so any machine's routing explains itself in the log.

The full stack surfaces in RedCell's options screen as a device list and output preset the player can switch: Audio Settings & Mix Architecture.