Audiokit: Audiobus 'hwFormat' crash

Created on 23 Mar 2017  Â·  29Comments  Â·  Source: AudioKit/AudioKit

I'm integrating Audiobus into my AudioKit-based app, and have followed the instructions here, but when I call Audiobus.start(), the app will continue running for about a second, then I get some error output, followed by a crash:

2017-03-22 23:25:45.620918 Vulse[20369:7115604] [central] 54: ERROR: [0x16e167000] >avae> AVAudioIONodeImpl.mm:365: _GetHWFormat: required condition is false: hwFormat
framerate: 23
2017-03-22 23:26:03.917219 Vulse[20369:7115604] * Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: hwFormat'

So, I got the FilterEffects example up and running to see if the issue was just in my app. (First I had to change the input variable in viewDidLoad to a property, because it was deiniting too early and causing a crash.) But after fixing that, I unfortunately got the same error above.

Interestingly, for the second or two before the app crashes, everything seems to work properly: the app takes audio input from audiobus and I can hear it output with the reverb applied. Also (at least in my app) if I remove the Audiobus.start(), but still try to instantiate an AKStereoInput, I get a similar message: SetOutputFormat: required condition is false: format.sampleRate == hwFormat.sampleRate

Do you get the same crash when trying this yourself, with the latest AudioKit release? I'm using Audiobus 2.3.3, on an iPhone 6s running iOS 10.2.1.

All 29 comments

The apps didn't crash on the release testing, but I can check it all out again.

Audiobus 3 is about to be released, so we'll be updating and testing examples for that probably tomorrow.

Well, the AudioBus 3 SDK won't be released for a couple more days so I looked at this problem. I found one bug on the iPad and pushed that commit. Now it works on the iPad at least. But the iPad is stereo, and the iPhone6 is mono, so your bug may still persist. I don't have mono phone (7 is stereo) to test...

Reopen this issue if you still have problems with this fix.

I just now got around to checking if the issue is resolved and I'm not seeing the crash anymore! In fact AudioBus integration seems to be working quite seamlessly now. Thanks for looking into this.

Hmm, I may have spoken too soon; it looks like the crash is still happening in certain cases. I'll look into it some more and reopen the issue if necessary.

Okay, I think you were onto something when you mentioned stereo vs mono. The crash seems to only occur when I don't have headphones plugged in on startup, and it even crashes immediately if I start it up with headphones and then pull them out.

So, most likely, nothing has actually changed in Audiobus/AudioKit since I opened the issue; I just thought it was working because I had headphones plugged in.

I checked the Audiobus forums and it seems that another AudioKit user is having the exact same problem. All stereo devices / outputs work, but mono triggers the same crash: https://heroes.audiob.us/discussion/620/iphone-speaker-crash/p1

So maybe AudioKit isn't handling mono outputs correctly with respect to what Audiobus expects? However, in this link (not using AudioKit, just AVAudioEngine), they get a similar crash, but the fixes listed have nothing to do with the audio channels:
https://forums.developer.apple.com/thread/65656


So, I've been looking around in the code, and this seems like it might be relevant? Audiobus.swift:48:

var audioUnit: AudioUnit {
    return AudioKit.engine.outputNode.audioUnit!
}

This is the audio unit passed into ABFilterPort's initializer. If you look at AVAudioEngine.h for the outputNode property, there's this:

/*! @property outputNode
  @abstract
    The engine's singleton output node.
  @discussion
    Audio output is performed via an output node. The engine creates a singleton on demand when
    this property is first accessed. Connect another node to the input of the output node, or obtain
    a mixer that is connected there by default, using the "mainMixerNode" property.

    The AVAudioSesssion category and/or availability of hardware determine whether an app can
    perform output. Check the output format of output node (i.e. hardware format) for non-zero
    sample rate and channel count to see if output is enabled.
*/
open var outputNode: AVAudioOutputNode { get }

The last paragraph mentions the node's hardware format, which seems relevant to the GetHWFormat crash. Perhaps the audio unit being passed to Audiobus is ill-formed somehow? Or the AudioKit channel count isn't in sync with the AVAudioEngine's channel count?

I'm curious about any thoughts you might have on possible causes or things to try next. If there's a way I can run my app against the AudioKit source, instead of the compiled framework, let me know. That would be helpful so I can tweak the code in place.

(Btw: apparently I can't reopen my issue if someone else closes it, so feel free to reopen this since the issue is still occurring.)

I've seen this happen when developing on my iPhone 7… curious if it thinks the lightning cable at some point is an output… This could also all be a red herring.

Similar sounding thread on Apple dev forums: https://forums.developer.apple.com/thread/73166

I've been trying to dig into this a bit more, not much progress but I did notice the crash only seems to occur when the "System Audio Output" node is added downstream of my app in Audiobus. Up until that point, even with the input hooked up or other effects apps downstream, it works as expected. It also crashes if I add the output, then add my app.

Given what I mentioned about mono/stereo, I tried setting AKSettings.numberOfChannels to 1, but this didn't seem to affect anything.

When I get the time I'll try this again with the FilterEffects example app. Even if the behavior is the same it should help isolate the issue. @aure is there a way to build an app against the AudioKit source instead of the compiled framework? It would help to be able to step through the code, tweak things, etc.

@jconst The second half of this video shows how to use .xcodeproj file instead of the framework: https://vimeo.com/214224470

I tested again with FilterEffects and got the same behavior, including the crash when you unplug headphones. I dug around the Audiobus forums a bit more and there are a couple other threads describing the same issue:

https://heroes.audiob.us/discussion/445/ios8-avaudioengine-integration-issue-with-audiobus/p1

https://heroes.audiob.us/discussion/635/change-in-channel-processing-in-last-couple-of-weeks/p1

Seems like a lot of people are having this issue. The first link does suggest that the problem lies in using engine.outputNode.audioUnit directly (which AudioKit's Audiobus.swift does), but it looks like the workaround doesn't work for anyone either. This seems like a likely enough cause, but if there's no actual workaround I think I'll just live with the bug for now and hope that Audiobus 3 SDK fixes this.

Also, probably worth noting that I tested using just IAA (no Audiobus app) through GarageBand, and I had all the same issues. I'm still using the Audiobus SDK to publish, though, so idk if this actually narrows anything down.

Hey guys, thought I'd just chime in here. I'd be very interested to see how this works in total absence of the Audiobus SDK. It'd simply be a matter of using AudioOutputUnitPublish directly, to expose the audio unit to Inter-App Audio hosts - this would be a quick hack, but should give us an idea of whether it's crashing or not with just the IAA API alone.

I have seen this same crash frequently on an iPhone 7 while playing back mono source. Unplugging it from the computer via lightning connector did seem to reduce the frequency of crashes. The same code on a 5s runs perfectly every time.

We're going to pull AudioKit out of the loop and go Straight AVAudioPlayer Kit playback for this one instance and see if we still experience problems.

Some updates: Since the Audiobus 3 SDK is out, I updated to the Audiobus 3 app and SDK, but unfortunately this didn't solve the issue.

@michaeltyson good idea; I tried that out and am still getting the same error in the same situations. I modified Audiobus.swift to remove the Audiobus stuff and publish using AudioOutputUnitPublish directly, so it looks like this (the publish is on line 67). Then I hooked it up to GarageBand, and it works until I unplug the headphones, causing my app to crash with the hwformat error. So it looks like it's not specifically an Audiobus issue, but with IAA in general.

I also tried publishing AudioKit.engine.inputNode.audioUnit instead of the outputNode, but the crash still occurred. And, on my iPhone 6s, it doesn't make a difference whether the lighting cable to the computer is plugged into the phone.

I think I'm going to try some of the Apple sample apps next and see if they have this issue (I'm assuming they won't). Then I can try to work from there and pinpoint the difference that's causing the crashes.

Bravo @jconst, thanks for trying that! Let me know how the sample app tests go - I suspect you'll see the same issues. Either way I'll pass whatever you find on to my contact on the Core Audio team and make sure they see it

Not sure if this helps, I am a bit of a script kiddy with the audio in iOS. I can't seem to find an answer elsewhere and it looks like it could be recent. I hope I am not intruding on your project but this was the only worthwhile discussion on the issue I could find. I thought since my project is so simple it might help reduce some possibilities.

I have a prototype/just-for-fun app I have been working on that simply plays a file or speaks an utterance. Has worked flawlessly until today when I happen to have bluetooth headphones on connected when I started the app in simulator.

Use Case 1:

I put headphones on for the first time via bluetooth. Ran app in iPhone 5s simulator. Headphones were connected before I built and ran the project. The audio (I was also playing music from iTunes) seemed to go to a lower-quality and I thought there was an issue with iTunes, then I got the following messages in my output that I had never seen before:

2017-05-29 11:09:52.001738-0400 Charles[70453:2089239] [aqme] 1158: AQDefaultDevice: Abandoning I/O cycle because reconfig pending (1).
2017-05-29 11:09:54.048749-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:09:56.096854-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:09:58.144935-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:00.192980-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:02.241081-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:04.289179-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:06.337309-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:08.385381-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:10.433457-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:12.481531-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:14.529619-0400 Charles[70453:2089239] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0
2017-05-29 11:10:15.529760-0400 Charles[70453:2089120] [aqme] 318: Audio device 0x3a: error 0 fetching sample rate, or sample rate is 0. Defaulting to 44100.
2017-05-29 11:10:15.535880-0400 Charles[70453:2089120] [aqme] 2162: EXCEPTION thrown (2003332927): -
2017-05-29 11:10:17.580703-0400 Charles[70453:2097388] [aqme] 318: Audio device 0x3a: error 0 fetching sample rate, or sample rate is 0. Defaulting to 44100.
2017-05-29 11:10:17.581942-0400 Charles[70453:2097388] [aqme] 318: Audio device 0x3a: error 0 fetching sample rate, or sample rate is 0. Defaulting to 44100.
2017-05-29 11:10:17.584072-0400 Charles[70453:2111193] [aqme] 318: Audio device 0x3a: error 0 fetching sample rate, or sample rate is 0. Defaulting to 44100.
2017-05-29 11:10:17.585783-0400 Charles[70453:2111193] [aqme] 318: Audio device 0x3a: error 0 fetching sample rate, or sample rate is 0. Defaulting to 44100.

when I disconnected the bluetooth headphones, I got this and the app crashed:

2017-05-29 11:10:17.588395-0400 Charles[70453:2089106] [central] 54:   ERROR:    >avae> AVAudioIONodeImpl.mm:365: _GetHWFormat: required condition is false: hwFormat
2017-05-29 11:10:17.597 Charles[70453:2089106] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: hwFormat'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010c9a2b0b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010bff2141 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010c9a6cf2 +[NSException raise:format:arguments:] + 98
    3   AVFAudio                            0x000000010f931a9e _Z19AVAE_RaiseExceptionP8NSStringz + 158
    4   AVFAudio                            0x000000010f930fcf _ZN13AVAudioIOUnit12_GetHWFormatEjPj + 441
    5   AVFAudio                            0x000000010f930c7f ___ZN13AVAudioIOUnit22IOUnitPropertyListenerEPvP28OpaqueAudioComponentInstancejjj_block_invoke_2 + 169
    6   libdispatch.dylib                   0x000000011244a4a6 _dispatch_call_block_and_release + 12
    7   libdispatch.dylib                   0x000000011247305c _dispatch_client_callout + 8
    8   libdispatch.dylib                   0x000000011245194f _dispatch_queue_serial_drain + 221
    9   libdispatch.dylib                   0x0000000112452669 _dispatch_queue_invoke + 1084
    10  libdispatch.dylib                   0x0000000112454ec4 _dispatch_root_queue_drain + 634
    11  libdispatch.dylib                   0x0000000112454bef _dispatch_worker_thread3 + 123
    12  libsystem_pthread.dylib             0x000000011280a5a2 _pthread_wqthread + 1299
    13  libsystem_pthread.dylib             0x000000011280a07d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Use Case 2:

I started the app in simulator the same way (but no iTunes playing in background). This time I connected the bluetooth headphones after the app was running. I immediately got this output:

2017-05-29 11:30:03.225128-0400 Charles[70808:2160962] [aqme] 1158: AQDefaultDevice: Abandoning I/O cycle because reconfig pending (1).

For the minute or so I ran the app, I kept getting this message over and over:
2017-05-29 11:30:05.273250-0400 Charles[70808:2160962] [aqme] 254: AQDefaultDevice (32): skipping input stream 0 0 0x0

Then, just like last time, when I turned off the bluetooth headphones, I got the following along with a crash:

2017-05-29 11:32:59.451312-0400 Charles[70808:2160810] [central] 54:   ERROR:    >avae> AVAudioIONodeImpl.mm:365: _GetHWFormat: required condition is false: hwFormat
2017-05-29 11:32:59.455 Charles[70808:2160810] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: hwFormat'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000107b3fb0b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010718f141 objc_exception_throw + 48
    2   CoreFoundation                      0x0000000107b43cf2 +[NSException raise:format:arguments:] + 98
    3   AVFAudio                            0x000000010aacea9e _Z19AVAE_RaiseExceptionP8NSStringz + 158
    4   AVFAudio                            0x000000010aacdfcf _ZN13AVAudioIOUnit12_GetHWFormatEjPj + 441
    5   AVFAudio                            0x000000010aacdc7f ___ZN13AVAudioIOUnit22IOUnitPropertyListenerEPvP28OpaqueAudioComponentInstancejjj_block_invoke_2 + 169
    6   libdispatch.dylib                   0x000000010d6754a6 _dispatch_call_block_and_release + 12
    7   libdispatch.dylib                   0x000000010d69e05c _dispatch_client_callout + 8
    8   libdispatch.dylib                   0x000000010d67c94f _dispatch_queue_serial_drain + 221
    9   libdispatch.dylib                   0x000000010d67d669 _dispatch_queue_invoke + 1084
    10  libdispatch.dylib                   0x000000010d67fec4 _dispatch_root_queue_drain + 634
    11  libdispatch.dylib                   0x000000010d67fbef _dispatch_worker_thread3 + 123
    12  libsystem_pthread.dylib             0x000000010da355a2 _pthread_wqthread + 1299
    13  libsystem_pthread.dylib             0x000000010da3507d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Project

Here is a link to my repo:

Prototype with simple AV

Here is a link to the commit where this happened:
Commit where I first saw this error (and first used headphones with this project)

If you don't want to bother with the repo, I have pasted the few spots where I used AV things:

// MARK: AV Variables
    let synth = AVSpeechSynthesizer()
    var textUtterance = AVSpeechUtterance(string: "")
    var audioPlayer: AVAudioPlayer!
    var audioEngine: AVAudioEngine!
    var audioPlayerNode: AVAudioPlayerNode!
    var changePitchEffect: AVAudioUnitTimePitch!

...

//audio
        audioEngine = AVAudioEngine()
        audioPlayer = AVAudioPlayer()
        //setup node
        audioPlayerNode = AVAudioPlayerNode()
        audioEngine.attach(audioPlayerNode)
        changePitchEffect = AVAudioUnitTimePitch()
        audioEngine.attach(changePitchEffect)

        audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)
        audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)

...

try audioPlayer = AVAudioPlayer(contentsOf: url)
                audioPlayer.enableRate = true

                resetAudioEngineAndPlayer()

//                try audioPlayer = AVAudioPlayer(contentsOf: url)
                let audioFile = try AVAudioFile(forReading: url)

                changePitchEffect.pitch = currentPhrase.slots![currentButtons.index(of: sendingButton!)!].tone

                audioPlayerNode.scheduleFile(audioFile, at: nil, completionHandler: nil)

                try audioEngine.start()
                audioPlayerNode.play()

...

func resetAudioEngineAndPlayer() {
        audioEngine.stop()
        audioPlayerNode.stop()
    }

@jconst Did you get a chance to try the Apple sample apps?

Yes, sorry, I should have updated this a while ago. The sample apps did not have this issue, because the IAA sample app (apps? can't remember) used Audio Units directly – It looks like the problem is simply caused by trying to use AVAudioEngine and Inter-App Audio together in any way on a mono device. I rewrote my app's core processing code to use Audio Units directly instead of AVAudioEngine and haven't had this issue since. (I've found that it's still safe to use AVAudioSession for simple things like setCategory(), overrideOutputAudioPort(), setPreferredSampleRate(), etc.)

This, of course, is slightly scary news because it looks like the remaining solutions are: replace a big chunk of AudioKit with much uglier code, hope Apple fixes the bug, or find some other workaround, which might not exist.

Again, I could be wrong, but what I do know is that replacing AudioKit with a Remote IO Audio Unit with a custom render callback solved the problem. To make a change this big took about a week for my app, though, so it's not a very satisfying solution.

@jconst Has the bug been filed with Apple? I've got an example project to reproduce it: https://github.com/wtholliday/AudioEngine.

You know, I was sure I had seen an openradar link in one of the threads I was looking at but now I can't find it, so maybe it hasn't been filed.

@jconst Ah, ok. I'm preparing a DTS (and possibly a radar). My earlier DTS was rejected because my example project was using AudioBus. I've tried to use IAA directly, but I'm out of my element. Could you take a look at my example project (https://github.com/wtholliday/AudioEngine)?

If you can log a radar, I'll email my contacts on the Core Audio team and give them a heads-up directly

@wtholliday I haven't had time to test out your project, so I'm not sure what exact issues you're running into, but have you tried using the modified version of Audiobus.swift I linked a few posts ago? The comments should be cleaned out of course but it reproduced the error without having any dependencies on AudioKit or Audiobus.

I'm going to close this issue, but you can all free to continue to discuss stuff here and post results. I just don't know what actions I can take. If there's something I can do, just say so and reopen the issue, no problem. thanks.

@michaeltyson I filed a bug, which was duped to 34838819. Could you bug them about that one?

Sorry about the delay, @wtholliday - yep, I've made contact.

Good news - apparently this should be fixed in the latest iOS 11.1 beta (b5, I presume)

This issue only appears to be happening when I use quickTime player VideoScreen Recording . So clearly there is a bug somewhere apples needs to test and resolve. I have a silly work around. AlexKissiJr

This issue will happen when bluetooth device is connected before AKMicrophone inited, it related to the device sample rate is lower then 44100, also will happen when your are video chat with others, the sample rate is also lower then 44100. both you can't change the device sample rate to 44100, Also the fixed is change AKMicrophone's method:getFormatForDevice to use AudioKit.engine.inputNode.inputFormat(forBus: 0).sampleRate, but i don't know why getFormatForDevice try use AudioKit.deviceSampleRate.

private func getFormatForDevice() -> AVAudioFormat? {
let audioFormat: AVAudioFormat?
#if os(iOS) && !targetEnvironment(simulator)
let currentFormat = AudioKit.engine.inputNode.inputFormat(forBus: 0)
let desiredFS = AudioKit.deviceSampleRate
if let layout = currentFormat.channelLayout {
audioFormat = AVAudioFormat(commonFormat: currentFormat.commonFormat,
sampleRate: desiredFS,
interleaved: currentFormat.isInterleaved,
channelLayout: layout)
} else {
audioFormat = AVAudioFormat(standardFormatWithSampleRate: desiredFS, channels: 2)
}
#else
let desiredFS = AKSettings.sampleRate
audioFormat = AVAudioFormat(standardFormatWithSampleRate: desiredFS, channels: 2)
#endif
return audioFormat
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mlostekk picture mlostekk  Â·  4Comments

adamjsutcliffe picture adamjsutcliffe  Â·  10Comments

NadirBertolasi picture NadirBertolasi  Â·  10Comments

jamesharvey2 picture jamesharvey2  Â·  3Comments

crashingbooth picture crashingbooth  Â·  4Comments