Skip to content

Software audio tap crashes on multichannel PCM when AVAudioFormat returns nil #400

Description

@dlev02

What happened?

A TestFlight crash report came in from Prism. The app was using AetherEngine 6.1.3.

The crash is fully symbolicated and lands in the software-path audio tap:

Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value
AudioTapPCMConverter.convert(_:) (AudioTapPCMConverter.swift:30)
AetherEngine.installSoftwareTapSink(controller:)
SoftwarePlaybackHost.runDemuxLoop(...)

AudioTapPCMConverter creates its input format with the channel-count-only AVAudioFormat initializer and force-unwraps the result. On macOS that initializer returns nil for interleaved Float32 input with 3–8 channels at normal sample rates, including 48 kHz/6-channel PCM. That matches the software decoder's supported multichannel output.

This is only fatal while an audio-tap consumer is active, such as soundtrack recognition or live transcription. Playback without a tap does not run this converter. The same force unwrap is still present on current main.

Steps to reproduce

  1. Create interleaved Float32 PCM with more than two channels, for example 48 kHz/6-channel.
  2. Install an audio tap while the software playback path is active.
  3. Deliver the decoded CMSampleBuffer to AudioTapPCMConverter.convert(_:).
  4. AVAudioFormat(commonFormat:sampleRate:channels:interleaved:) returns nil, and line 30 traps on the force unwrap.

The Foundation behavior can also be reproduced directly without the original media file:

let format = AVAudioFormat(
    commonFormat: .pcmFormatFloat32,
    sampleRate: 48_000,
    channels: 6,
    interleaved: true
)
// format == nil

AetherEngine version or commit SHA

6.1.3 / 343bcba (confirmed unchanged on current main)

Host app

Custom / my own integration

Platform

macOS

OS version

macOS 27.0

Device / chip

Apple Silicon Mac (ARM64; exact model not included in the TestFlight report)

Playback path

Software (dav1d) host

Source media (for playback bugs)

The original media file is not available. The crash is in the decoded interleaved Float32 PCM path and is directly reproducible with 48 kHz/6-channel PCM.

Error codes / log lines

Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value
AudioTapPCMConverter.swift:30

Anything else

A narrow fix would be to reuse AetherEngine's existing channel-layout mapping and remove the force unwrap:

var streamDescription = asbd
guard let channelLayout = AVAudioChannelLayout(
    layoutTag: audioChannelLayoutTag(for: Int32(asbd.mChannelsPerFrame))
),
let inFormat = AVAudioFormat(
    streamDescription: &streamDescription,
    channelLayout: channelLayout
) else {
    return []
}

AudioDecoder already uses the same audioChannelLayoutTag(for:) mapping when it creates these sample buffers, so this should preserve the intended 3.0/5.1/7.1 layout without changing routing or public API.

The existing AudioTapPCMConverterTests.makeSample helper already accepts a channel count, so one 5.1 conversion case should cover the regression without new test infrastructure.

I have not included the TestFlight crash file because it contains unrelated user/session metadata.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions