Skip to main content
Code samples

Audio Session Troubleshooting

Real-Time Pipeline Is Silentโ€‹

Symptoms: engine.start() succeeds but no audio comes through the tap.

Checklist:

  1. Microphone permission โ€” confirm AVAudioSession.recordPermission == .granted

  2. Audio session activated โ€” call AVAudioSession.sharedInstance().setActive(true) before engine.start()

  3. Correct format in installTap โ€” the format passed to installTap must match the AVAudioInputNode's output format:

    let inputFormat = engine.inputNode.outputFormat(forBus: 0)
    // If inputFormat.sampleRate != 48000, use AVAudioMixerNode to resample
  4. installTap before start โ€” installTap must be called before engine.start()

AVAudioSession Activation Failedโ€‹

let session = AVAudioSession.sharedInstance()
try session.setCategory(.playAndRecord, options: [.mixWithOthers, .allowBluetooth])
try session.setActive(false, options: .notifyOthersOnDeactivation)
try session.setActive(true)

Engine Stops After Phone Callโ€‹

NotificationCenter.default.addObserver(
forName: AVAudioSession.interruptionNotification,
object: nil, queue: .main
) { [weak engine] notification in
guard let info = notification.userInfo,
let t = info[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSession.InterruptionType(rawValue: t) else { return }
switch type {
case .ended:
try? engine?.start()
default: break
}
}

Sample Rate Mismatch Warningโ€‹

Always query the actual input format:

let hwFormat = engine.inputNode.outputFormat(forBus: 0)

guard let targetFormat = AVAudioFormat(
commonFormat: .pcmFormatFloat32, sampleRate: 48_000, channels: 1, interleaved: false
) else { return }

mixer.installTap(onBus: 0, bufferSize: 480, format: targetFormat) { buffer, _ in
// buffer is now guaranteed 48kHz Float32 mono
}