Deactivating audio error on iOS device


#1

I had an iOS app that used to work fine two months ago. I made a small change unrelated change (size of a button), recompiled and now it fails to work on my test device (iPhone SE), when it used to work fine. It also works fine on the emulator. I get the following error:

**[avas] AVAudioSession.mm:1142:-[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.**

**JUCE Assertion failure in juce_ios_Audio.cpp:207**

This is the offending code:

static void setAudioSessionActive (bool enabled)
{
JUCE_NSERROR_CHECK ([[AVAudioSession sharedInstance] setActive: enabled
error: &error]);
}

The offending section of code is called (several layers deep) from this my code:

setAudioChannels (0, 2); // no inputs, two outputs
AudioDeviceManager::AudioDeviceSetup setup;
deviceManager.getAudioDeviceSetup(setup);
setup.sampleRate = 44100;
deviceManager.initialise(0, 2, nullptr, true, “”, &setup);

Any ideas of what to do?


#2

I think this call starts the audio device already, but I don’t think you need that line at all.
Can you try without the setAudioChannels()? It is done when you call deviceManager.initialise()…


#3

Can you post the stack trace when you see the error?

There was a fairly recent change the the audio session handling on the develop branch. Do you see the same behaviour if you pull the latest changes from there?


#4

Thank you for the suggestion. If I comment out the setAudioChannels(…) line, the program does not crash and seems to work. But I get no sounds at all in both the emulator and the device.


#6

Below is the stack trace. I haven’t tried the development branch but will do soon.

* thread #1, name = 'JUCE Message Thread', queue = 'com.apple.main-thread', stop reason = signal SIGTRAP
  * frame #0: 0x000000018156c890 libsystem_kernel.dylib`__kill + 8
    frame #1: 0x00000001040bd1bc VindorPlayer`juce::logNSError(e=domain: "NSOSStatusErrorDomain" - code: 560030580) at juce_ios_Audio.cpp:207
    frame #2: 0x00000001040bc150 VindorPlayer`juce::iOSAudioIODevice::Pimpl::setAudioSessionActive(enabled=false) at juce_ios_Audio.cpp:290
    frame #3: 0x00000001040bbdb0 VindorPlayer`juce::iOSAudioIODevice::Pimpl::Pimpl(this=0x000000011dd20770, ioDeviceType=0x00000001c00a79e0, ioDevice=0x00000001c022aa80) at juce_ios_Audio.cpp:258
    frame #4: 0x00000001040b7544 VindorPlayer`juce::iOSAudioIODevice::Pimpl::Pimpl(this=0x000000011dd20770, ioDeviceType=0x00000001c00a79e0, ioDevice=0x00000001c022aa80) at juce_ios_Audio.cpp:248
    frame #5: 0x00000001040b7414 VindorPlayer`juce::iOSAudioIODevice::iOSAudioIODevice(this=0x00000001c022aa80, ioDeviceType=0x00000001c00a79e0, (null)=0x000000016bdb74f0, (null)=0x000000016bdb74f8) at juce_ios_Audio.cpp:1332
    frame #6: 0x00000001040b7590 VindorPlayer`juce::iOSAudioIODevice::iOSAudioIODevice(this=0x00000001c022aa80, ioDeviceType=0x00000001c00a79e0, (null)=0x000000016bdb74f0, (null)=0x000000016bdb74f8) at juce_ios_Audio.cpp:1333
    frame #7: 0x00000001040b8b80 VindorPlayer`juce::iOSAudioIODeviceType::createDevice(this=0x00000001c00a79e0, outputDeviceName=0x000000016bdb74f0, inputDeviceName=0x000000016bdb74f8) at juce_ios_Audio.cpp:1404
    frame #8: 0x00000001040ad234 VindorPlayer`juce::AudioDeviceManager::setAudioDeviceSetup(this=0x000000011e039ea0, newSetup=0x000000016bdb7838, treatAsChosenDevice=false) at juce_AudioDeviceManager.cpp:463
    frame #9: 0x00000001040acbb0 VindorPlayer`juce::AudioDeviceManager::initialiseDefault(this=0x000000011e039ea0, preferredDefaultDeviceName=0x000000016bdb7fa0, preferredSetupOptions=0x000000016bdb7fb0) at juce_AudioDeviceManager.cpp:242
    frame #10: 0x00000001040abfa0 VindorPlayer`juce::AudioDeviceManager::initialise(this=0x000000011e039ea0, numInputChannelsNeeded=0, numOutputChannelsNeeded=2, xml=0x0000000000000000, selectDefaultDeviceOnFailure=true, preferredDefaultDeviceName=0x000000016bdb7fa0, preferredSetupOptions=0x000000016bdb7fb0) at juce_AudioDeviceManager.cpp:205
    frame #11: 0x000000010404cb68 VindorPlayer`Player::Player(this=0x000000011e038c00) at Player.cpp:636
    frame #12: 0x000000010404df10 VindorPlayer`Player::Player(this=0x000000011e038c00) at Player.cpp:500
    frame #13: 0x0000000104057ae0 VindorPlayer`splayerApplication::MainWindow::MainWindow(this=0x000000011dd08470, name=String @ 0x000000016bdb93a8) at Main.cpp:72
    frame #14: 0x00000001040579b4 VindorPlayer`splayerApplication::MainWindow::MainWindow(this=0x000000011dd08470, name=<unavailable>) at Main.cpp:70
    frame #15: 0x0000000104057678 VindorPlayer`splayerApplication::initialise(this=0x00000001c046c500, commandLine=0x000000016bdb9418) at Main.cpp:30
    frame #16: 0x0000000104318524 VindorPlayer`juce::JUCEApplicationBase::initialiseApp(this=0x00000001c046c500) at juce_ApplicationBase.cpp:297
    frame #17: 0x0000000104537c4c VindorPlayer`juce::JUCEApplication::initialiseApp(this=0x00000001c046c500) at juce_Application.cpp:93
    frame #18: 0x00000001045479b0 VindorPlayer`::-[JuceAppStartupDelegate applicationDidFinishLaunching:](self=0x00000001c003aa20, _cmd="applicationDidFinishLaunching:", application=0x000000011de04660) at juce_ios_Windowing.mm:110
    frame #19: 0x000000018b6f5e24 UIKit`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 512
    frame #20: 0x000000018b6f5914 UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 5356
    frame #21: 0x000000018b6c25e0 UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1680
    frame #22: 0x000000018bcf2b1c UIKit`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 784
    frame #23: 0x000000018b6c1dd0 UIKit`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 160
    frame #24: 0x000000018b6c1c6c UIKit`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 240
    frame #25: 0x000000018b6c0afc UIKit`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 724
    frame #26: 0x000000018c35684c UIKit`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 296
    frame #27: 0x000000018b6c01ec UIKit`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 432
    frame #28: 0x000000018c13bac8 UIKit`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 220
    frame #29: 0x000000018c289bf8 UIKit`_performActionsWithDelayForTransitionContext + 112
    frame #30: 0x000000018b6bfc0c UIKit`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 248
    frame #31: 0x000000018b6bf5a8 UIKit`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 368
    frame #32: 0x000000018b6bc5e0 UIKit`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 540
    frame #33: 0x000000018b6bc330 UIKit`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 364
    frame #34: 0x00000001842e8470 FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 364
    frame #35: 0x00000001842f0d6c FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 224
    frame #36: 0x00000001074d919c libdispatch.dylib`_dispatch_client_callout + 16
    frame #37: 0x00000001074e57cc libdispatch.dylib`_dispatch_block_invoke_direct + 232
    frame #38: 0x000000018431c878 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 36
    frame #39: 0x000000018431c51c FrontBoardServices`-[FBSSerialQueue _performNext] + 404
    frame #40: 0x000000018431cab8 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 56
    frame #41: 0x0000000181a8f404 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
    frame #42: 0x0000000181a8ec2c CoreFoundation`__CFRunLoopDoSources0 + 276
    frame #43: 0x0000000181a8c79c CoreFoundation`__CFRunLoopRun + 1204
    frame #44: 0x00000001819acda8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #45: 0x0000000183992020 GraphicsServices`GSEventRunModal + 100
    frame #46: 0x000000018b9cc758 UIKit`UIApplicationMain + 236
    frame #47: 0x0000000104547ed4 VindorPlayer`juce::juce_iOSMain(argc=1, argv=0x000000016bdbb850, customDelegatePtr=0x0000000000000000) at juce_ios_Windowing.mm:422
    frame #48: 0x0000000104317f0c VindorPlayer`juce::JUCEApplicationBase::main(argc=1, argv=0x000000016bdbb850) at juce_ApplicationBase.cpp:237
    frame #49: 0x0000000104057474 VindorPlayer`main(argc=1, argv=0x000000016bdbb850) at Main.cpp:104
    frame #50: 0x000000018143dfc0 libdyld.dylib`start + 4
(lldb) 

#7

Hmm. That’s not particularly enlightening.

  • Did this start happening without changing any JUCE code?
  • If you revert your button size change do things work as they used to?

#8

I did revert the change, with the same results. I also got the developer branch and compiled against it with the same result. In addition, I got an old iPhone 5 (iOS 10.3.3), reset it to factory settings, connected it and got the same results. It will crash if I use the original code. If I comment out the setAudioChannels line then it doesn’t crash but I get no sound.


#9

Does the JUCE DemoRunner application (or any of the JUCE-provided examples) work?


#10

In the end, if I keep the line below and removed the others everything is fine.

I’m not sure how to set the sample rate, but it defaults to what I want so that’s ok.

An unexpected side effect is that IOChannelData::IOChannelConfig::getHardwareChannelNames(...) is hard coded on the emulator to return two channels. This is different than the behavior on the iPhone. The phone returns only one channel “Speaker” when outputting through it’s built-in speaker. It returns two channels if headphones are connected. That confused me until I dug deeper into the code.