AVAudioEngine randomly stops after app going background and return to foreground

Hey guys,

I have a problem with AVAudioEngine stopping for unknown reason in a following situation:

* All work is done on its own pthread thread with max priority.

* In the thread's main function I call `update` in a loop, which schedules AVAudioPCMBuffer-s in a following way:

[player_ scheduleBuffer:buffer completionHandler:^()
{
  for (auto &bufferStruct : buffers_)
  {
    if (bufferStruct.buffer == buffer)
    {
      bufferStruct.available = true;
      return;
    }
  }
}];

where `player_` is of type `AVAudioPlayerNode`.


The buffers I schedule are filled manually with float32 pcm data. Frame length of a buffer is sufficient to play for 1 / 25.0 of a second. Total number of buffers is 5, so when all buffers were scheduled, the code waits for them to become available in a following way:

for (auto &bufferStruct : buffers_)
{
  if (bufferStruct.position + bufferStruct.buffer.frameLength < playerTime && bufferStruct.available)
  {
    if (UpdateBuffer(bufferStruct.buffer))
    {
      ScheduleBuffer(bufferStruct);
    }
  }
}

where `playerTime` is obtained through `AVAudioPlayerNode::playerTimeForNodeTime` and `AVAudioPlayerNode::lastRenderTime`.


This scheme works perfectly fine as long as needed until the app does not go background and then returns to foreground.

When the app goes background I stop scheduling AVAudioPCMBuffer-s to the AVAudioPlayerNode and start doing it again when the app goes foreground.

But at some point after the app went foreground the AVAudioEngine may stop playing, i.e. its `isRunning` returns `NO` (it may stop playing after first background switch or after tenth, I don't see any pattern in it).

`isRunning` starts to return `NO` after some time after the app is returned foreground, so I am able to hear few sounds from the device, and few buffers are scheduled for playing.

And in this situation I am not able to do anything to make it play again:

* I tried restarting it by calling `startAndReturnError`:

NSError *error = nil;
[engine_ startAndReturnError:&error];

if (![player_ isPlaying])
{
  [player_ play];
}

There are no errors returned by startAndReturnError but when scheduling new buffers to the player a completion handler passed into [player_ scheduleBuffer: completionHandler:...] never gets called.


* I tried to recreate buffers and player completely too, it did not work.

* I tried to recreate AVAudioEngine:


[engine_ stop];
[engine_ release];


and it causes a crash in `Thread 70 Queue : engine (serial)`:

#0 0x000000019e08b528 in objc_msgSend ()
#1 0x000000019f7f1894 in +[NSConcreteNotification newTempNotificationWithName:object:userInfo:] ()
#2 0x000000019f7f17d8 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#3 0x00000001a4d2f6ec in ___ZN17AVAudioEngineImpl26IOUnitConfigurationChangedEv_block_invoke_2 ()


I am subscribed to AVAudioSessionInterruptionNotification, AVAudioSessionMediaServicesWereResetNotification, AVAudioSessionRouteChangeNotification, AVAudioEngineConfigurationChangeNotification and none of them are called.



The device I am using is iPhone SE, 12.3.1.



Suggestions anyone?

AVAudioEngine randomly stops after app going background and return to foreground
 
 
Q