AVAudioEngine

RSS for tag

Use a group of connected audio node objects to generate and process audio signals and perform audio input and output.

Posts under AVAudioEngine tag

200 Posts

Post

Replies

Boosts

Views

Activity

AVPlayer Reverse Audio Scrubbing?
Hey all, here seeking some perspective. I have an audio player app on macOS built on top of AVPlayer, I want to add the ability to scrub the audio, and hear the audio frames based on the playhead's position whether going forwards or backwards. When going backwards, the audio frame should be played in reverse as well. The audio tracks live online and are streamed. I tried playing with AVPlayer.rate, but the time pitch algos built in (.spectral, .varispeed, .timeDomain) all only guarantee up to 32x rate decoding accuracy. So technically, if the user scrubs fast enough, the audio rendered would not necessarily match the playhead's position. My current solution that works is to cache the raw audio bytes and play the appropriate frame when the user starts scrubbing. I decode the audio data manually using AudioToolbox's AudioFileOpenWithCallbacks into an AVAudioPCMBuffer, then pass it into AVAudioEngine+AVAudioPlayerNode combo. The problem with that is that means I need to cache this audio data myself (remember this is a stream), and since I don't have access to AVPlayer's own cache I need to also download it myself... which means two downloads for the same track which is less than ideal. This lead me to take it a step further and hijack AVPlayer's download process by implementing AVAssetResourceLoaderDelegate, that way AVPlayer and my audio scrubbing cache are both fed from the same source. Now... I feel like I went down a bit of a rabbit hole here. At the end of the day I simply want accurate audio scrubbing in both directions, while keeping in mind I want the audio snippets to play in reverse when the user goes backwards. Is there really no way to do this that's more "vanilla"? Am I missing something obvious? Genuinely open to any and all suggestions. Thanks.
0
0
161
1w
AVAudioEngine input tap intermittently delivers all-zero buffers — valid format, no error thrown
We have a long-form audio recording app built on AVAudioEngine. We install a tap on inputNode, accumulate the PCM buffers, and encode them to AAC in ~60-second chunks. Setup is essentially: let session = AVAudioSession.sharedInstance() try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth, .allowBluetoothA2DP]) try session.setActive(true) let engine = AVAudioEngine() let input = engine.inputNode let format = input.inputFormat(forBus: 0) // valid, e.g. 48 kHz, 1 ch input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in // In the failure case, buffer.floatChannelData is entirely 0.0 // (accumulate + encode to AAC) } engine.prepare() try engine.start() Intermittently — and so far only reported from the field, never reproduced in normal testing — a recording comes out completely silent. When we decode the resulting AAC and inspect the raw PCM, every sample is exactly 0.0. The signature is very specific: The engine is running and the tap keeps firing for the full duration (normal number of buffers / full-length chunks). inputFormat is valid (sampleRate ≠ 0, e.g. 48 kHz). No error is thrown anywhere — setCategory, setActive, start(), and the tap callback all succeed. The PCM is literally all zeros (not low-level noise / room tone — exact 0.0). Two separate silent recordings decode to byte-identical AAC, confirming pure digital silence rather than corruption. So as far as our error handling, format checks, and tap-liveness are concerned, everything looks healthy — yet the microphone is delivering pure silence. One way we can reproduce it: recording while the iPhone is being driven via macOS iPhone Mirroring (the iPhone stays locked, the mic is effectively unavailable from the device, but our session still activates with a valid format and the tap fires zero-filled buffers for the whole recording — with no error at any point). What we've ruled out: microphone permission is granted; it's not truncation or short capture (full-length, full frame count); it's not our encoding step (the input buffers themselves are zero); it's not a quiet/obstructed mic (that would be low noise, not exact 0.0). We also found two existing threads describing what looks like the same symptom: https://developer.apple.com/forums/thread/834950 https://developer.apple.com/forums/thread/808072 Both of those are PushToTalk apps where the system activates the audio session, and an Apple engineer notes it may be related to a CallKit issue (r.157725305). For context on our side: we do use CallKit, but only CXCallObserver — purely to detect whether a phone call comes in while a recording is in progress, so we can pause and resume around it. We do not use CXProvider or PushToTalk, and we activate our own AVAudioSession ourselves with setActive(true). I'm trying to understand whether there are other scenarios or device states that could leave a running AVAudioEngine tap returning all-zero buffers like this, and whether this is the same underlying CallKit issue (r.157725305) from those threads . And since nothing throws an error, any guidance on how to detect this at runtime and recover from it would be really helpful.
0
0
155
2w
AVAudioEngine input tap intermittently delivers all-zero buffers — valid format, no error thrown
We have a long-form audio recording app built on AVAudioEngine. We install a tap on inputNode, accumulate the PCM buffers, and encode them to AAC in ~60-second chunks. Setup is essentially: let session = AVAudioSession.sharedInstance() try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth, .allowBluetoothA2DP]) try session.setActive(true) let engine = AVAudioEngine() let input = engine.inputNode let format = input.inputFormat(forBus: 0) // valid, e.g. 48 kHz, 1 ch input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in // In the failure case, buffer.floatChannelData is entirely 0.0 // (accumulate + encode to AAC) } engine.prepare() try engine.start() Intermittently — and so far only reported from the field, never reproduced in normal testing — a recording comes out completely silent. When we decode the resulting AAC and inspect the raw PCM, every sample is exactly 0.0. The signature is very specific: The engine is running and the tap keeps firing for the full duration (normal number of buffers / full-length chunks). inputFormat is valid (sampleRate ≠ 0, e.g. 48 kHz). No error is thrown anywhere — setCategory, setActive, start(), and the tap callback all succeed. The PCM is literally all zeros (not low-level noise / room tone — exact 0.0). Two separate silent recordings decode to byte-identical AAC, confirming pure digital silence rather than corruption. So as far as our error handling, format checks, and tap-liveness are concerned, everything looks healthy — yet the microphone is delivering pure silence. One way we can reproduce it: recording while the iPhone is being driven via macOS iPhone Mirroring (the iPhone stays locked, the mic is effectively unavailable from the device, but our session still activates with a valid format and the tap fires zero-filled buffers for the whole recording — with no error at any point). What we've ruled out: microphone permission is granted; it's not truncation or short capture (full-length, full frame count); it's not our encoding step (the input buffers themselves are zero); it's not a quiet/obstructed mic (that would be low noise, not exact 0.0). Questions: What other device states or scenarios can cause a running AVAudioEngine input tap to deliver all-zero buffers with a valid format and no error? (e.g. another process/system feature holding the mic, Continuity Camera/Mic, CallKit/PushToTalk session ownership, etc.) Since this surfaces with no error and a valid format, what is the recommended way to detect it at runtime? Is monitoring the input level / PCM energy the only signal, or is there a supported API to know the input isn't actually live? What's the recommended recovery once detected — is a full session deactivate/reactivate re-handshake sufficient, or is recreating the engine required?
1
0
163
2w
visionOS nearby SharePlay blocks local microphone capture
I created a minimal sample project that reproduces a microphone issue with nearby SharePlay / Window Sharing on Apple Vision Pro. Sample project: https://github.com/JerryNee/mic-demo Screen recording: https://youtu.be/aMj_A_leJWU Issue I first implemented SharePlay through FaceTime and found that local microphone capture was unavailable. That seemed understandable because FaceTime itself uses the microphone. I then moved the app to a nearby SharePlay / Window Sharing session specifically to avoid a FaceTime call, but local microphone capture still fails. Local microphone capture works before starting nearby SharePlay. After starting a nearby SharePlay / Window Sharing session with GroupActivities, the same app fails at: try audioEngine.start() This does not require a FaceTime call. It happens with an in-room nearby SharePlay / Window Sharing session. The screen recording also goes silent when the Share Window UI appears. I checked the MP4 audio track with ffmpeg silencedetect; audio becomes silent at about 00:00:22.60, matching the moment nearby sharing starts: silence_start: 22.600612 silence_end: 55.051927 | silence_duration: 32.451315 Environment Two nearby Apple Vision Pro devices Xcode device list: visionOS 27.0 and visionOS 26.5 Xcode 27.0, build 27A5194q Frameworks: GroupActivities, AVFoundation, Speech Entitlement: com.apple.developer.group-session Microphone and speech recognition permissions granted Steps Run the sample on Apple Vision Pro. Tap Start Listening and speak. Transcription works. Tap Stop Listening. Tap Start Nearby Session. Share with another nearby Apple Vision Pro. Tap Start Listening again while the nearby session is active. audioEngine.start() fails. Ending the nearby session makes microphone capture work again. Minimal microphone code let recognizer = SFSpeechRecognizer() let audioEngine = AVAudioEngine() let request = SFSpeechAudioBufferRecognitionRequest() request.shouldReportPartialResults = true let session = AVAudioSession.sharedInstance() try session.setCategory(.record, mode: .measurement, options: [.duckOthers]) try session.setActive(true) let input = audioEngine.inputNode let format = input.outputFormat(forBus: 0) input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in request.append(buffer) } audioEngine.prepare() try audioEngine.start() Minimal nearby SharePlay code struct MicDemoActivity: Codable, GroupActivity, Transferable { static let activityIdentifier = "com.example.mic-demo.nearby-mic-repro" static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .micDemoActivity) } var metadata: GroupActivityMetadata { var metadata = GroupActivityMetadata() metadata.type = .generic metadata.title = "Mic Demo Nearby Session" return metadata } } for await session in MicDemoActivity.sessions() { session.join() } _ = try await MicDemoActivity().activate() Questions Is local microphone capture expected to be unavailable during a nearby SharePlay / Window Sharing session? Is screen recording audio expected to become silent during nearby sharing? What is the recommended way to support nearby shared UI/state while still allowing local voice input?
1
0
178
4w
Push Notification sounds with AVAudioSession, AVAudioEngine
I am using AVAudioSession, AVAudioEngine and SpeechAnalyzer to listen to commands, also when the phone is locked. In the same time, I can receive PushNotifications with pre-defined sound. However, the pre-defined sound is not played when the AVAudioEngine is running and the phone is locked. In the code below, I have made many experiments, all of them are "Receive Push Notification while the phone is locked", and I have the following results: If audioEngine has started - I only see the alert, but no sound. If I comment out audioEngine.start, all works as expected and I hear the apns sound on the speaker. If I change the AVAudioSession category to 'record' I don't receive the push message at all! I wonder if anyone has seen it. Here is my code: private func doStartListening() async { print("SpeechService: doStartListening called") guard !audioEngine.isRunning else { print("SpeechService: Audio engine already running") return } do { try configureAudioSession() let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0) audioEngine.inputNode.removeTap(onBus: 0) guard let locale = await SpeechTranscriber.supportedLocale(equivalentTo: Locale(identifier: "en-US")) else { print("English is not supported on this device") return } let transcriber = SpeechTranscriber(locale: locale, preset: .transcription) if let installationRequest = try await AssetInventory.assetInstallationRequest(supporting: [transcriber]) { try await installationRequest.downloadAndInstall() } let (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self) let audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(compatibleWith: [transcriber]) let analyzer = SpeechAnalyzer(modules: [transcriber]) // Initialize the modern SpeechAnalyzer self.analyzer = analyzer task = Task { print("SpeechService: Starting analyzer results loop") do { for try await result in transcriber.results { if Task.isCancelled { break } self.handleAnalyzerResult(result) } } catch { print("SpeechService: Analyzer error: \(error.localizedDescription)") let nsError = error as NSError if nsError.domain == "kAFAssistantErrorDomain" && nsError.code == 203 { self.addLog(NSLocalizedString("error_siri_disabled", comment: "")) Task { await self.stopListening() } } else if self.isListening { self.restartRecognition() } } } audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self]buffer, _ in guard let audioFormat else { return } do { let converted = try self!.converter.convertBuffer(buffer, to: audioFormat) inputBuilder.yield(AnalyzerInput(buffer: converted)) } catch { print("Exception when converting audio") } } audioEngine.prepare() try audioEngine.start() print("SpeechService: Audio engine started") try await analyzer.start(inputSequence: inputSequence) isListening = true addLog(NSLocalizedString("waiting_wakeup", comment: "")) } catch { print("SpeechService: Error starting listening: \(error.localizedDescription)") addLog("Error starting listening: \(error.localizedDescription)") lastError = error.localizedDescription isListening = false } } private func configureAudioSession() throws { let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .defaultToSpeaker]) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) }
0
0
646
Jun ’26
SIGILL crash in AudioToolbox/caulk during AudioQueue creation on macOS 26.4.1 (Apple Silicon + Rosetta)
Product: macOS Version: macOS 26.4.1 (25E253) Area: Audio / AVFoundation / AudioToolbox Summary: We are observing a reproducible crash during audio playback initialization in our macOS application on Apple Silicon systems running macOS 26.4.1. The crash occurs inside Apple audio frameworks while creating an AudioQueue through AVAudioPlayer/NSSound APIs. Environment: Application: Avaya Workplace 3.41.0 Hardware: Apple Silicon (Mac14,7) OS: macOS 26.4.1 Application architecture: x86_64 running under Rosetta Frameworks involved: AppKit (NSSound) AVFAudio AudioToolbox caulk Crash Type: SIGILL (ILL_ILLOPC) Observed Stack: -[NSSound play] AVAudioPlayer play AudioQueueNewOutput AudioConverterNewWithOptions caulk::alloc::consolidating_free_map::maybe_create_free_node Details: The crash occurs while attempting to start ringtone/notification playback from the application. The failure happens during AudioQueue initialization before actual playback begins. The crashing thread consistently shows: caulk AudioToolboxCore AudioToolbox AVFAudio AppKit Application audio helper We also observed similar AudioQueue initialization stacks on multiple threads, which may indicate concurrent audio queue initialization. Questions: Is there any known regression in AudioToolbox/AVFAudio/caulk on macOS 26.4.1 affecting x86_64 applications running under Rosetta? Are there known limitations or unsupported scenarios involving AudioQueue creation from Rosetta-translated applications? Are there recommended alternatives or mitigations for NSSound/AVAudioPlayer usage on macOS 26? Reproduction: Launch application on Apple Silicon Mac Trigger ringtone/notification playback Application intermittently crashes during AudioQueue initialization Additional Notes: Crash is intermittent but reproducible in customer environments. The application currently uses NSSound/AVAudioPlayer for ringtone playback. We are also investigating whether concurrent sound initialization may contribute to the issue.
1
0
276
May ’26
AVAudioSession gets interrupted when closing a window
I have a visionOS app that plays audio using AVAudioEngine and presents both a window and an immersive space. If I close the window, the audio session gets interrupted and attempting to restart the session and audio engine has no effect. I need to dismiss the app, then reopen it, which reopens the main window, in order for audio to start playing again. This is in all visionOS 2 betas. Note that I have background audio enabled for my app.
4
1
1.8k
May ’26
AVAudioEngineConfigurationChangeNotification received while engine is running
The documentation for AVAudioEngineConfigurationChangeNotification states When the audio engine’s I/O unit observes a change to the audio input or output hardware’s channel count or sample rate, the audio engine stops, uninitializes itself, and issues this notification. A user of my framework has reported a crash during notification processing on iOS 26.4 when the main mixer node is disconnected from the output node in order to reestablish the connection with a different format. The failing precondition is com.apple.coreaudio.avfaudio: required condition is false: !IsRunning(). The report was observed on iPhone 16 / iOS 26.4.2, ARM64, TestFlight build. The backtrace contains: [Last Exception Backtrace] 3 AVFAudio AVAudioEngineGraph::_DisconnectInput AVAudioEngineGraph.mm:2728 4 AVFAudio -[AVAudioEngine disconnectNodeInput:bus:] AVAudioEngine.mm:155 5 SFB sfb::AudioPlayer::handleAudioEngineConfigurationChange AudioPlayer.mm:2247 [Thread 18 Crashed] 9 SFB sfb::AudioPlayer::handleAudioEngineConfigurationChange AudioPlayer.mm:2212 … 14 AVFAudio IOUnitConfigurationChanged Has the behavior for AVAudioEngineConfigurationChangeNotification changed in iOS 26.4? It's simple enough to call [engine_ stop] in the notification handler but the documentation states this shouldn't be necessary. I've not observed a similar crash on previous iOS versions.
0
1
427
May ’26
AVAudioEngine startAndReturnError is now failing
I have a keyboard in my iOS Morse Code app that has always been able to play audio via AVAudioEngine. Recently it has been failing to produce audio. I see that startAndReturnError: is now failing with this error: Error Domain=com.apple.coreaudio.avfaudio Code=268435459 "(null)" UserInfo={failed call=err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)} What's going on? Have keyboards lost the ability to play audio? Here's how I set things up: _engine = [AVAudioEngine new]; _prefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedAppGroupID]; AVAudioMixerNode* mainMixerNode = _engine.mainMixerNode; AVAudioOutputNode* outputNode = _engine.outputNode; AVAudioFormat* format = [outputNode inputFormatForBus:0]; AVAudioFormat* inputFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:44100 channels:1 interleaved:NO]; self.srcNode = [[AVAudioSourceNode alloc] initWithRenderBlock:^OSStatus(BOOL* _Nonnull isSilence, const AudioTimeStamp* _Nonnull timestamp, AVAudioFrameCount frameCount, AudioBufferList* _Nonnull outputData) { // This block builds the data, but is never called, so it is not the culprit. }]; [_engine attachNode:self.srcNode]; [_engine connect:self.srcNode to:mainMixerNode format:inputFormat]; [_engine connect:mainMixerNode to:_engine.outputNode format:nil]; [_engine prepare];
0
0
395
Apr ’26
Mixing ScreenCaptureKit audio with microphone audio
Hi, I'm new to AVAudioEngine(and macOS programming in general). I'm trying to mix microphone audio with ScreenCaptureKit audio using AVAudioEngine without playing it back. I've created a AVAudioPlayerNode and scheduling buffers in my SCStream handler: playerNode.scheduleBuffer(samples) and have connected the playerNode to the mainMixerNode. audioEngine.connect(audioEngine.inputNode, to: audioEngine.mainMixerNode, format: micFormat) audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: format) The problem is that mainMixerNode plays the audio to the speaker creating a feedback loop. How can I prevent the mixer output from being played back. Also: Is this the best way of mixing microphone input with some other input? I ran into AVAudioEngine's manual rendering mode, which seems like the way to go for mixing audio without playing it back. However, I couldn't figure out how to connect microphone input to the AVAudioEngine in manual rendering mode?
1
0
1.3k
Mar ’26
Video Audio + Speech To Text
Hello, I am wondering if it is possible to have audio from my AirPods be sent to my speech to text service and at the same time have the built in mic audio input be sent to recording a video? I ask because I want my users to be able to say "CAPTURE" and I start recording a video (with audio from the built in mic) and then when the user says "STOP" I stop the recording.
2
0
1.8k
Mar ’26
AVAudioEngine fails to start during FaceTime call (error 2003329396)
Is it possible to perform speech-to-text using AVAudioEngine to capture microphone input while being on a FaceTime call at the same time? I tried implementing this, but whenever I attempt to start the  AVAudioEngine  while a FaceTime call is active, I get the following error: “The operation couldn’t be completed. (OSStatus error 2003329396)” I assume this might be due to microphone resource restrictions during FaceTime, but I’d like to confirm whether this limitation is at the system level or if there’s any possible workaround or entitlement that allows concurrent microphone access. Has anyone encountered this issue or found a solution?
2
1
1.5k
Mar ’26
WatchOS: Can a background metronome app coexist with both Runna workout and Spotify playback?
I’m building a standalone Apple Watch metronome app for running. My goal is for these 3 apps to work at the same time: Runna owns the workout session Spotify plays music my app plays a metronome click in the background So far this is what I've found: Using HKWorkout​Session in my metronome app works well with Spotify, but conflicts with Runna and other workout apps, so I removed that. Using watchOS background audio with longFormAudio allows my app run in the background, and it can coexist with Runna. However, it seems to conflict with Spotify playback, and one app tends to stop the other. Is there any supported watchOS audio/background configuration that allows all 3 at once? More specifically this is what I need: another app owns HKWorkout​Session Spotify keeps playing my app keeps generating metronome clicks in the background Or is this simply not supported by current watchOS session/background rules? My metronome uses AVAudio​Engine / AVAudio​Player​Node with generated click audio. Thank you!
4
0
1.5k
Mar ’26
Unexpected Ambisonics format
When trying to load an ambisonics file using this project: https://github.com/robertncoomber/NativeiOSAmbisonicPlayback/ I get "Unexpected Ambisonics format". Interestingly, loading a 3rd order ambisonics file works fine: let ambisonicLayoutTag = kAudioChannelLayoutTag_HOA_ACN_SN3D | 16 let AmbisonicLayout = AVAudioChannelLayout(layoutTag: ambisonicLayoutTag) let StereoLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_Stereo) So it's purely related to the kAudioChannelLayoutTag_Ambisonic_B_Format
0
0
114
Mar ’26
AVAudioEngine obtains channel audio data
Currently, I have successfully used ChannelMap to map hardware input channels and obtained audio data from the hardware device's MIC and OTG inputs. Additionally, I have used ChannelMap to map output channels to freely feed data for playback to each output channel. However, I now have a problem. I have a hardware device that only has output channels (no input channels), and the system has set this hardware device as the default playback device. In this case, how can I obtain the audio data being played to the output channels for modification?
0
0
418
Dec ’25
How to safely switch between mic configurations on iOS?
I have an iPadOS M-processor application with two different running configurations. In config1, the shared AVAudioSession is configured for .videoChat mode using the built-in microphone. The input/output nodes of the AVAudioEngine are configured with voice processing enabled. The built-in mic is formatted for 1 channel at 48KHz. In config2, the shared AVAudioSession is configured for .measurement mode using an external USB microphone. The input/output nodes of the AVAudioEngine are configured with voice processing disabled. The external mic is formatted for 2 channels at 44.1KHz I've written a configuration manager designed to safely switch between these two configurations. It works by stopping AVAudioEngine and detaching all but the input and output nodes, updating the shared audio session for the desired mic and sample-rates, and setting the appropriate state for voice processing to either true or false as required by the configuration. Finally the new audio graph is constructed by attaching appropriate nodes, connecting them, and re-starting AVAudioEngine I'm experiencing what I believe is a race-condition between switching voice processing on or off and then trying to re-build and start the new audio graph. Even though notifications, which are dumped to the console indicate that my requested input and sample-rate settings are in place, I crash when trying to start the audio engine because the sample-rate is wrong. Investigating further it looks like the switch from remote I/O to voice-processing I/O or vice-versa has not yet actually completed. I introduced a 100ms second delay and that seems to help but is obviously not a reliable way to build software that must work consistently. How can I make sure that what are apparently asynchronous configuration changes to the shared audio session and the input/output nodes have completed before I go on? I tried using route change notifications from the shared AVAudioSession but these lie. They say my preferred mic input and sample-rate setting is in place but when I dump the AVAudioEngine graph to the debugger console, I still see the wrong sample rate assigned to the input/output nodes. Also these are the wrong AU nodes. That is, VPIO is still in place when RIO should be, or vice-versa. How can I make the switch reliable without arbitrary time delays? Is my configuration manager approach appropriate (question for Apple engineers)?
1
0
576
Nov ’25
Not able to write AAC audio with 96 kHz sample rate using AVAudioRecorder or Extended audio file services
Not able to record audio in AAC format with 96 kHz sample rate using AVAudioRecorder or Extended Audio File services with 96 kHz input audio from input device. The audio recording settings used are let settings: [String: Any] = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: sampleRate AVNumberOfChannelsKey: 1 AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] When tried using AVAudioEngine using AVAudioFile, AVAudioFile(forWriting: fileURL, // file extension .m4a settings: fileSettings, commonFormat: AVAudioCommonFormat.pcmFormatFloat32, interleaved: interleaved) else { return } got error CodecConverterFactory.cpp:977 unable to select compatible encoder sample rate AudioConverter.cpp:1017 Failed to create a new in process converter -> from 1 ch, 96000 Hz, Float32 to 1 ch, 96000 Hz, aac (0x00000000) 0 bits/channel, 0 bytes/packet, 0 frames/packet, 0 bytes/frame, with status 1718449215
1
0
1.2k
Nov ’25
AVPlayer Reverse Audio Scrubbing?
Hey all, here seeking some perspective. I have an audio player app on macOS built on top of AVPlayer, I want to add the ability to scrub the audio, and hear the audio frames based on the playhead's position whether going forwards or backwards. When going backwards, the audio frame should be played in reverse as well. The audio tracks live online and are streamed. I tried playing with AVPlayer.rate, but the time pitch algos built in (.spectral, .varispeed, .timeDomain) all only guarantee up to 32x rate decoding accuracy. So technically, if the user scrubs fast enough, the audio rendered would not necessarily match the playhead's position. My current solution that works is to cache the raw audio bytes and play the appropriate frame when the user starts scrubbing. I decode the audio data manually using AudioToolbox's AudioFileOpenWithCallbacks into an AVAudioPCMBuffer, then pass it into AVAudioEngine+AVAudioPlayerNode combo. The problem with that is that means I need to cache this audio data myself (remember this is a stream), and since I don't have access to AVPlayer's own cache I need to also download it myself... which means two downloads for the same track which is less than ideal. This lead me to take it a step further and hijack AVPlayer's download process by implementing AVAssetResourceLoaderDelegate, that way AVPlayer and my audio scrubbing cache are both fed from the same source. Now... I feel like I went down a bit of a rabbit hole here. At the end of the day I simply want accurate audio scrubbing in both directions, while keeping in mind I want the audio snippets to play in reverse when the user goes backwards. Is there really no way to do this that's more "vanilla"? Am I missing something obvious? Genuinely open to any and all suggestions. Thanks.
Replies
0
Boosts
0
Views
161
Activity
1w
AVAudioEngine input tap intermittently delivers all-zero buffers — valid format, no error thrown
We have a long-form audio recording app built on AVAudioEngine. We install a tap on inputNode, accumulate the PCM buffers, and encode them to AAC in ~60-second chunks. Setup is essentially: let session = AVAudioSession.sharedInstance() try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth, .allowBluetoothA2DP]) try session.setActive(true) let engine = AVAudioEngine() let input = engine.inputNode let format = input.inputFormat(forBus: 0) // valid, e.g. 48 kHz, 1 ch input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in // In the failure case, buffer.floatChannelData is entirely 0.0 // (accumulate + encode to AAC) } engine.prepare() try engine.start() Intermittently — and so far only reported from the field, never reproduced in normal testing — a recording comes out completely silent. When we decode the resulting AAC and inspect the raw PCM, every sample is exactly 0.0. The signature is very specific: The engine is running and the tap keeps firing for the full duration (normal number of buffers / full-length chunks). inputFormat is valid (sampleRate ≠ 0, e.g. 48 kHz). No error is thrown anywhere — setCategory, setActive, start(), and the tap callback all succeed. The PCM is literally all zeros (not low-level noise / room tone — exact 0.0). Two separate silent recordings decode to byte-identical AAC, confirming pure digital silence rather than corruption. So as far as our error handling, format checks, and tap-liveness are concerned, everything looks healthy — yet the microphone is delivering pure silence. One way we can reproduce it: recording while the iPhone is being driven via macOS iPhone Mirroring (the iPhone stays locked, the mic is effectively unavailable from the device, but our session still activates with a valid format and the tap fires zero-filled buffers for the whole recording — with no error at any point). What we've ruled out: microphone permission is granted; it's not truncation or short capture (full-length, full frame count); it's not our encoding step (the input buffers themselves are zero); it's not a quiet/obstructed mic (that would be low noise, not exact 0.0). We also found two existing threads describing what looks like the same symptom: https://developer.apple.com/forums/thread/834950 https://developer.apple.com/forums/thread/808072 Both of those are PushToTalk apps where the system activates the audio session, and an Apple engineer notes it may be related to a CallKit issue (r.157725305). For context on our side: we do use CallKit, but only CXCallObserver — purely to detect whether a phone call comes in while a recording is in progress, so we can pause and resume around it. We do not use CXProvider or PushToTalk, and we activate our own AVAudioSession ourselves with setActive(true). I'm trying to understand whether there are other scenarios or device states that could leave a running AVAudioEngine tap returning all-zero buffers like this, and whether this is the same underlying CallKit issue (r.157725305) from those threads . And since nothing throws an error, any guidance on how to detect this at runtime and recover from it would be really helpful.
Replies
0
Boosts
0
Views
155
Activity
2w
AVAudioEngine input tap intermittently delivers all-zero buffers — valid format, no error thrown
We have a long-form audio recording app built on AVAudioEngine. We install a tap on inputNode, accumulate the PCM buffers, and encode them to AAC in ~60-second chunks. Setup is essentially: let session = AVAudioSession.sharedInstance() try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth, .allowBluetoothA2DP]) try session.setActive(true) let engine = AVAudioEngine() let input = engine.inputNode let format = input.inputFormat(forBus: 0) // valid, e.g. 48 kHz, 1 ch input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in // In the failure case, buffer.floatChannelData is entirely 0.0 // (accumulate + encode to AAC) } engine.prepare() try engine.start() Intermittently — and so far only reported from the field, never reproduced in normal testing — a recording comes out completely silent. When we decode the resulting AAC and inspect the raw PCM, every sample is exactly 0.0. The signature is very specific: The engine is running and the tap keeps firing for the full duration (normal number of buffers / full-length chunks). inputFormat is valid (sampleRate ≠ 0, e.g. 48 kHz). No error is thrown anywhere — setCategory, setActive, start(), and the tap callback all succeed. The PCM is literally all zeros (not low-level noise / room tone — exact 0.0). Two separate silent recordings decode to byte-identical AAC, confirming pure digital silence rather than corruption. So as far as our error handling, format checks, and tap-liveness are concerned, everything looks healthy — yet the microphone is delivering pure silence. One way we can reproduce it: recording while the iPhone is being driven via macOS iPhone Mirroring (the iPhone stays locked, the mic is effectively unavailable from the device, but our session still activates with a valid format and the tap fires zero-filled buffers for the whole recording — with no error at any point). What we've ruled out: microphone permission is granted; it's not truncation or short capture (full-length, full frame count); it's not our encoding step (the input buffers themselves are zero); it's not a quiet/obstructed mic (that would be low noise, not exact 0.0). Questions: What other device states or scenarios can cause a running AVAudioEngine input tap to deliver all-zero buffers with a valid format and no error? (e.g. another process/system feature holding the mic, Continuity Camera/Mic, CallKit/PushToTalk session ownership, etc.) Since this surfaces with no error and a valid format, what is the recommended way to detect it at runtime? Is monitoring the input level / PCM energy the only signal, or is there a supported API to know the input isn't actually live? What's the recommended recovery once detected — is a full session deactivate/reactivate re-handshake sufficient, or is recreating the engine required?
Replies
1
Boosts
0
Views
163
Activity
2w
visionOS nearby SharePlay blocks local microphone capture
I created a minimal sample project that reproduces a microphone issue with nearby SharePlay / Window Sharing on Apple Vision Pro. Sample project: https://github.com/JerryNee/mic-demo Screen recording: https://youtu.be/aMj_A_leJWU Issue I first implemented SharePlay through FaceTime and found that local microphone capture was unavailable. That seemed understandable because FaceTime itself uses the microphone. I then moved the app to a nearby SharePlay / Window Sharing session specifically to avoid a FaceTime call, but local microphone capture still fails. Local microphone capture works before starting nearby SharePlay. After starting a nearby SharePlay / Window Sharing session with GroupActivities, the same app fails at: try audioEngine.start() This does not require a FaceTime call. It happens with an in-room nearby SharePlay / Window Sharing session. The screen recording also goes silent when the Share Window UI appears. I checked the MP4 audio track with ffmpeg silencedetect; audio becomes silent at about 00:00:22.60, matching the moment nearby sharing starts: silence_start: 22.600612 silence_end: 55.051927 | silence_duration: 32.451315 Environment Two nearby Apple Vision Pro devices Xcode device list: visionOS 27.0 and visionOS 26.5 Xcode 27.0, build 27A5194q Frameworks: GroupActivities, AVFoundation, Speech Entitlement: com.apple.developer.group-session Microphone and speech recognition permissions granted Steps Run the sample on Apple Vision Pro. Tap Start Listening and speak. Transcription works. Tap Stop Listening. Tap Start Nearby Session. Share with another nearby Apple Vision Pro. Tap Start Listening again while the nearby session is active. audioEngine.start() fails. Ending the nearby session makes microphone capture work again. Minimal microphone code let recognizer = SFSpeechRecognizer() let audioEngine = AVAudioEngine() let request = SFSpeechAudioBufferRecognitionRequest() request.shouldReportPartialResults = true let session = AVAudioSession.sharedInstance() try session.setCategory(.record, mode: .measurement, options: [.duckOthers]) try session.setActive(true) let input = audioEngine.inputNode let format = input.outputFormat(forBus: 0) input.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in request.append(buffer) } audioEngine.prepare() try audioEngine.start() Minimal nearby SharePlay code struct MicDemoActivity: Codable, GroupActivity, Transferable { static let activityIdentifier = "com.example.mic-demo.nearby-mic-repro" static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .micDemoActivity) } var metadata: GroupActivityMetadata { var metadata = GroupActivityMetadata() metadata.type = .generic metadata.title = "Mic Demo Nearby Session" return metadata } } for await session in MicDemoActivity.sessions() { session.join() } _ = try await MicDemoActivity().activate() Questions Is local microphone capture expected to be unavailable during a nearby SharePlay / Window Sharing session? Is screen recording audio expected to become silent during nearby sharing? What is the recommended way to support nearby shared UI/state while still allowing local voice input?
Replies
1
Boosts
0
Views
178
Activity
4w
Using separate BluetoothHFP devices for input and output
I want to connect a BluetoothHFP microphone to MFi hearing aids. Whenever I make the microphone the input it steals the output and whenever I make the MFi the output it steals the input. Is it possible to do this using AVAudioSession? Is it possible to redefine the MFi hearing aids as a speaker and use Live Listen?
Replies
0
Boosts
0
Views
293
Activity
Jun ’26
Push Notification sounds with AVAudioSession, AVAudioEngine
I am using AVAudioSession, AVAudioEngine and SpeechAnalyzer to listen to commands, also when the phone is locked. In the same time, I can receive PushNotifications with pre-defined sound. However, the pre-defined sound is not played when the AVAudioEngine is running and the phone is locked. In the code below, I have made many experiments, all of them are "Receive Push Notification while the phone is locked", and I have the following results: If audioEngine has started - I only see the alert, but no sound. If I comment out audioEngine.start, all works as expected and I hear the apns sound on the speaker. If I change the AVAudioSession category to 'record' I don't receive the push message at all! I wonder if anyone has seen it. Here is my code: private func doStartListening() async { print("SpeechService: doStartListening called") guard !audioEngine.isRunning else { print("SpeechService: Audio engine already running") return } do { try configureAudioSession() let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0) audioEngine.inputNode.removeTap(onBus: 0) guard let locale = await SpeechTranscriber.supportedLocale(equivalentTo: Locale(identifier: "en-US")) else { print("English is not supported on this device") return } let transcriber = SpeechTranscriber(locale: locale, preset: .transcription) if let installationRequest = try await AssetInventory.assetInstallationRequest(supporting: [transcriber]) { try await installationRequest.downloadAndInstall() } let (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self) let audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(compatibleWith: [transcriber]) let analyzer = SpeechAnalyzer(modules: [transcriber]) // Initialize the modern SpeechAnalyzer self.analyzer = analyzer task = Task { print("SpeechService: Starting analyzer results loop") do { for try await result in transcriber.results { if Task.isCancelled { break } self.handleAnalyzerResult(result) } } catch { print("SpeechService: Analyzer error: \(error.localizedDescription)") let nsError = error as NSError if nsError.domain == "kAFAssistantErrorDomain" && nsError.code == 203 { self.addLog(NSLocalizedString("error_siri_disabled", comment: "")) Task { await self.stopListening() } } else if self.isListening { self.restartRecognition() } } } audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self]buffer, _ in guard let audioFormat else { return } do { let converted = try self!.converter.convertBuffer(buffer, to: audioFormat) inputBuilder.yield(AnalyzerInput(buffer: converted)) } catch { print("Exception when converting audio") } } audioEngine.prepare() try audioEngine.start() print("SpeechService: Audio engine started") try await analyzer.start(inputSequence: inputSequence) isListening = true addLog(NSLocalizedString("waiting_wakeup", comment: "")) } catch { print("SpeechService: Error starting listening: \(error.localizedDescription)") addLog("Error starting listening: \(error.localizedDescription)") lastError = error.localizedDescription isListening = false } } private func configureAudioSession() throws { let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .defaultToSpeaker]) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) }
Replies
0
Boosts
0
Views
646
Activity
Jun ’26
SIGILL crash in AudioToolbox/caulk during AudioQueue creation on macOS 26.4.1 (Apple Silicon + Rosetta)
Product: macOS Version: macOS 26.4.1 (25E253) Area: Audio / AVFoundation / AudioToolbox Summary: We are observing a reproducible crash during audio playback initialization in our macOS application on Apple Silicon systems running macOS 26.4.1. The crash occurs inside Apple audio frameworks while creating an AudioQueue through AVAudioPlayer/NSSound APIs. Environment: Application: Avaya Workplace 3.41.0 Hardware: Apple Silicon (Mac14,7) OS: macOS 26.4.1 Application architecture: x86_64 running under Rosetta Frameworks involved: AppKit (NSSound) AVFAudio AudioToolbox caulk Crash Type: SIGILL (ILL_ILLOPC) Observed Stack: -[NSSound play] AVAudioPlayer play AudioQueueNewOutput AudioConverterNewWithOptions caulk::alloc::consolidating_free_map::maybe_create_free_node Details: The crash occurs while attempting to start ringtone/notification playback from the application. The failure happens during AudioQueue initialization before actual playback begins. The crashing thread consistently shows: caulk AudioToolboxCore AudioToolbox AVFAudio AppKit Application audio helper We also observed similar AudioQueue initialization stacks on multiple threads, which may indicate concurrent audio queue initialization. Questions: Is there any known regression in AudioToolbox/AVFAudio/caulk on macOS 26.4.1 affecting x86_64 applications running under Rosetta? Are there known limitations or unsupported scenarios involving AudioQueue creation from Rosetta-translated applications? Are there recommended alternatives or mitigations for NSSound/AVAudioPlayer usage on macOS 26? Reproduction: Launch application on Apple Silicon Mac Trigger ringtone/notification playback Application intermittently crashes during AudioQueue initialization Additional Notes: Crash is intermittent but reproducible in customer environments. The application currently uses NSSound/AVAudioPlayer for ringtone playback. We are also investigating whether concurrent sound initialization may contribute to the issue.
Replies
1
Boosts
0
Views
276
Activity
May ’26
AVAudioSession gets interrupted when closing a window
I have a visionOS app that plays audio using AVAudioEngine and presents both a window and an immersive space. If I close the window, the audio session gets interrupted and attempting to restart the session and audio engine has no effect. I need to dismiss the app, then reopen it, which reopens the main window, in order for audio to start playing again. This is in all visionOS 2 betas. Note that I have background audio enabled for my app.
Replies
4
Boosts
1
Views
1.8k
Activity
May ’26
AVAudioEngineConfigurationChangeNotification received while engine is running
The documentation for AVAudioEngineConfigurationChangeNotification states When the audio engine’s I/O unit observes a change to the audio input or output hardware’s channel count or sample rate, the audio engine stops, uninitializes itself, and issues this notification. A user of my framework has reported a crash during notification processing on iOS 26.4 when the main mixer node is disconnected from the output node in order to reestablish the connection with a different format. The failing precondition is com.apple.coreaudio.avfaudio: required condition is false: !IsRunning(). The report was observed on iPhone 16 / iOS 26.4.2, ARM64, TestFlight build. The backtrace contains: [Last Exception Backtrace] 3 AVFAudio AVAudioEngineGraph::_DisconnectInput AVAudioEngineGraph.mm:2728 4 AVFAudio -[AVAudioEngine disconnectNodeInput:bus:] AVAudioEngine.mm:155 5 SFB sfb::AudioPlayer::handleAudioEngineConfigurationChange AudioPlayer.mm:2247 [Thread 18 Crashed] 9 SFB sfb::AudioPlayer::handleAudioEngineConfigurationChange AudioPlayer.mm:2212 … 14 AVFAudio IOUnitConfigurationChanged Has the behavior for AVAudioEngineConfigurationChangeNotification changed in iOS 26.4? It's simple enough to call [engine_ stop] in the notification handler but the documentation states this shouldn't be necessary. I've not observed a similar crash on previous iOS versions.
Replies
0
Boosts
1
Views
427
Activity
May ’26
AVAudioEngine startAndReturnError is now failing
I have a keyboard in my iOS Morse Code app that has always been able to play audio via AVAudioEngine. Recently it has been failing to produce audio. I see that startAndReturnError: is now failing with this error: Error Domain=com.apple.coreaudio.avfaudio Code=268435459 "(null)" UserInfo={failed call=err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)} What's going on? Have keyboards lost the ability to play audio? Here's how I set things up: _engine = [AVAudioEngine new]; _prefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedAppGroupID]; AVAudioMixerNode* mainMixerNode = _engine.mainMixerNode; AVAudioOutputNode* outputNode = _engine.outputNode; AVAudioFormat* format = [outputNode inputFormatForBus:0]; AVAudioFormat* inputFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:44100 channels:1 interleaved:NO]; self.srcNode = [[AVAudioSourceNode alloc] initWithRenderBlock:^OSStatus(BOOL* _Nonnull isSilence, const AudioTimeStamp* _Nonnull timestamp, AVAudioFrameCount frameCount, AudioBufferList* _Nonnull outputData) { // This block builds the data, but is never called, so it is not the culprit. }]; [_engine attachNode:self.srcNode]; [_engine connect:self.srcNode to:mainMixerNode format:inputFormat]; [_engine connect:mainMixerNode to:_engine.outputNode format:nil]; [_engine prepare];
Replies
0
Boosts
0
Views
395
Activity
Apr ’26
Mixing ScreenCaptureKit audio with microphone audio
Hi, I'm new to AVAudioEngine(and macOS programming in general). I'm trying to mix microphone audio with ScreenCaptureKit audio using AVAudioEngine without playing it back. I've created a AVAudioPlayerNode and scheduling buffers in my SCStream handler: playerNode.scheduleBuffer(samples) and have connected the playerNode to the mainMixerNode. audioEngine.connect(audioEngine.inputNode, to: audioEngine.mainMixerNode, format: micFormat) audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: format) The problem is that mainMixerNode plays the audio to the speaker creating a feedback loop. How can I prevent the mixer output from being played back. Also: Is this the best way of mixing microphone input with some other input? I ran into AVAudioEngine's manual rendering mode, which seems like the way to go for mixing audio without playing it back. However, I couldn't figure out how to connect microphone input to the AVAudioEngine in manual rendering mode?
Replies
1
Boosts
0
Views
1.3k
Activity
Mar ’26
Video Audio + Speech To Text
Hello, I am wondering if it is possible to have audio from my AirPods be sent to my speech to text service and at the same time have the built in mic audio input be sent to recording a video? I ask because I want my users to be able to say "CAPTURE" and I start recording a video (with audio from the built in mic) and then when the user says "STOP" I stop the recording.
Replies
2
Boosts
0
Views
1.8k
Activity
Mar ’26
AVAudioEngine fails to start during FaceTime call (error 2003329396)
Is it possible to perform speech-to-text using AVAudioEngine to capture microphone input while being on a FaceTime call at the same time? I tried implementing this, but whenever I attempt to start the  AVAudioEngine  while a FaceTime call is active, I get the following error: “The operation couldn’t be completed. (OSStatus error 2003329396)” I assume this might be due to microphone resource restrictions during FaceTime, but I’d like to confirm whether this limitation is at the system level or if there’s any possible workaround or entitlement that allows concurrent microphone access. Has anyone encountered this issue or found a solution?
Replies
2
Boosts
1
Views
1.5k
Activity
Mar ’26
WatchOS: Can a background metronome app coexist with both Runna workout and Spotify playback?
I’m building a standalone Apple Watch metronome app for running. My goal is for these 3 apps to work at the same time: Runna owns the workout session Spotify plays music my app plays a metronome click in the background So far this is what I've found: Using HKWorkout​Session in my metronome app works well with Spotify, but conflicts with Runna and other workout apps, so I removed that. Using watchOS background audio with longFormAudio allows my app run in the background, and it can coexist with Runna. However, it seems to conflict with Spotify playback, and one app tends to stop the other. Is there any supported watchOS audio/background configuration that allows all 3 at once? More specifically this is what I need: another app owns HKWorkout​Session Spotify keeps playing my app keeps generating metronome clicks in the background Or is this simply not supported by current watchOS session/background rules? My metronome uses AVAudio​Engine / AVAudio​Player​Node with generated click audio. Thank you!
Replies
4
Boosts
0
Views
1.5k
Activity
Mar ’26
Unexpected Ambisonics format
When trying to load an ambisonics file using this project: https://github.com/robertncoomber/NativeiOSAmbisonicPlayback/ I get "Unexpected Ambisonics format". Interestingly, loading a 3rd order ambisonics file works fine: let ambisonicLayoutTag = kAudioChannelLayoutTag_HOA_ACN_SN3D | 16 let AmbisonicLayout = AVAudioChannelLayout(layoutTag: ambisonicLayoutTag) let StereoLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_Stereo) So it's purely related to the kAudioChannelLayoutTag_Ambisonic_B_Format
Replies
0
Boosts
0
Views
114
Activity
Mar ’26
Audio System Trace: Zero Time Stamp
In Instruments, I'm seeing "Zero Time Stamp" events in the "Audio Server" lane. What does that mean?
Replies
1
Boosts
0
Views
288
Activity
Mar ’26
Can I trigger AudioRecordingIntent from a bluetooth device
I have a BLE device which my app connects to and can detect button presses. On a button press, I want my app to start recording using the AudioRecordingIntent. But my app doesn't work and throws a background error. Is there any reliable way I can get the app to start recording audio in the background?
Replies
2
Boosts
0
Views
428
Activity
Feb ’26
AVAudioEngine obtains channel audio data
Currently, I have successfully used ChannelMap to map hardware input channels and obtained audio data from the hardware device's MIC and OTG inputs. Additionally, I have used ChannelMap to map output channels to freely feed data for playback to each output channel. However, I now have a problem. I have a hardware device that only has output channels (no input channels), and the system has set this hardware device as the default playback device. In this case, how can I obtain the audio data being played to the output channels for modification?
Replies
0
Boosts
0
Views
418
Activity
Dec ’25
How to safely switch between mic configurations on iOS?
I have an iPadOS M-processor application with two different running configurations. In config1, the shared AVAudioSession is configured for .videoChat mode using the built-in microphone. The input/output nodes of the AVAudioEngine are configured with voice processing enabled. The built-in mic is formatted for 1 channel at 48KHz. In config2, the shared AVAudioSession is configured for .measurement mode using an external USB microphone. The input/output nodes of the AVAudioEngine are configured with voice processing disabled. The external mic is formatted for 2 channels at 44.1KHz I've written a configuration manager designed to safely switch between these two configurations. It works by stopping AVAudioEngine and detaching all but the input and output nodes, updating the shared audio session for the desired mic and sample-rates, and setting the appropriate state for voice processing to either true or false as required by the configuration. Finally the new audio graph is constructed by attaching appropriate nodes, connecting them, and re-starting AVAudioEngine I'm experiencing what I believe is a race-condition between switching voice processing on or off and then trying to re-build and start the new audio graph. Even though notifications, which are dumped to the console indicate that my requested input and sample-rate settings are in place, I crash when trying to start the audio engine because the sample-rate is wrong. Investigating further it looks like the switch from remote I/O to voice-processing I/O or vice-versa has not yet actually completed. I introduced a 100ms second delay and that seems to help but is obviously not a reliable way to build software that must work consistently. How can I make sure that what are apparently asynchronous configuration changes to the shared audio session and the input/output nodes have completed before I go on? I tried using route change notifications from the shared AVAudioSession but these lie. They say my preferred mic input and sample-rate setting is in place but when I dump the AVAudioEngine graph to the debugger console, I still see the wrong sample rate assigned to the input/output nodes. Also these are the wrong AU nodes. That is, VPIO is still in place when RIO should be, or vice-versa. How can I make the switch reliable without arbitrary time delays? Is my configuration manager approach appropriate (question for Apple engineers)?
Replies
1
Boosts
0
Views
576
Activity
Nov ’25
Not able to write AAC audio with 96 kHz sample rate using AVAudioRecorder or Extended audio file services
Not able to record audio in AAC format with 96 kHz sample rate using AVAudioRecorder or Extended Audio File services with 96 kHz input audio from input device. The audio recording settings used are let settings: [String: Any] = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: sampleRate AVNumberOfChannelsKey: 1 AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] When tried using AVAudioEngine using AVAudioFile, AVAudioFile(forWriting: fileURL, // file extension .m4a settings: fileSettings, commonFormat: AVAudioCommonFormat.pcmFormatFloat32, interleaved: interleaved) else { return } got error CodecConverterFactory.cpp:977 unable to select compatible encoder sample rate AudioConverter.cpp:1017 Failed to create a new in process converter -> from 1 ch, 96000 Hz, Float32 to 1 ch, 96000 Hz, aac (0x00000000) 0 bits/channel, 0 bytes/packet, 0 frames/packet, 0 bytes/frame, with status 1718449215
Replies
1
Boosts
0
Views
1.2k
Activity
Nov ’25