I'm trying to setup a tap on my audioEngine's inputNode
for Speech Recognition. The following code works fine in the simulator, but not when I run it on my iPhone X
running iOS 13.1.2.
Here is the relevant code:
if (audioEngine == nil || (!audioEngine!.isRunning)) {
print("Setting up audioEngine")
if audioEngine == nil {
audioEngine = AVAudioEngine.init()
}
if(audioEngine!.inputNode.inputFormat(forBus: 0).channelCount == 0){
print("Not enough available inputs!")
}
let recognitionFormat = audioEngine!.inputNode.inputFormat(forBus: 0)
audioEngine!.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recognitionFormat) {
(buffer: AVAudioPCMBuffer, when: AVAudioTime) in
self.recognitionRequest?.append(buffer)
}
audioEngine?.prepare()
try audioEngine?.start()
}
I got no errors running in the simulator and Speech Recognition works fine. However, I got the following when running on my code:
Setting up audioEngine
[aurioc] AURemoteIO.cpp:1086:Initialize: failed: -10851 (enable 1, outf< 2 ch, 0 Hz, Float32, non-inter> inf< 2 ch, 0 Hz, Float32, non-inter>)
[aurioc] AURemoteIO.cpp:1086:Initialize: failed: -10851 (enable 1, outf< 2 ch, 0 Hz, Float32, non-inter> inf< 2 ch, 0 Hz, Float32, non-inter>)
Not enough available inputs!
If I don't return after channelCount == 0
, the app will crash with:
[avae] AVAEInternal.h:76 required condition is false: [AVAEGraphNode.mm:823:CreateRecordingTap: (IsFormatSampleRateAndChannelCountValid(format))]
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: IsFormatSampleRateAndChannelCountValid(format)'
My Audio Session is setup like this:
try audioSession.setCategory(.playAndRecord, options: [.defaultToSpeaker])
try audioSession.setActive(true)
And a check of the available inputs yields:
LIST OF INPUTS: [<AVAudioSessionPortDescription: 0x280eac6b0, type = MicrophoneBuiltIn; name = iPhone Microphone; UID = Built-In Microphone; selectedDataSource = Bottom>]
I'm stumped. Any help?
I figured out the problem. The problem has to do with Flutter (which this app is using, but I didn't think was relevant.) It turns out that it is relevant. Apparently the FlutterAppDelegate@application
method is not run on the main queue, which is where I was starting my AudioSession
. When I started my AudioSession
like this, my problem went away:
DispatchQueue.main.async {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playAndRecord, mode: .spokenAudio, options: .defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("Failed to setup audio session")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With