У меня проблема с остановкой AVAudioEngine
по неизвестной причине в следующей ситуации:
- Вся работа выполняется в собственном потоке pthread с максимальным приоритетом.
- В основную функцию потока я вызываю
update
в al oop, которая планирует AVAudioPCMBuffer
-s следующим образом:
[player_ scheduleBuffer:buffer completionHandler:^()
{
for (auto &bufferStruct : buffers_)
{
if (bufferStruct.buffer == buffer)
{
bufferStruct.available = true;
return;
}
}
}];
, где player_
имеет тип AVAudioPlayerNode
.
Запланированные мной буферы заполняются вручную данными float32 pcm. Длина кадра буфера достаточна для воспроизведения 1 / 25,0 секунды. Общее количество буферов равно 5, поэтому, когда все буферы были запланированы, код ожидает, пока они станут доступны следующим образом:
for (auto &bufferStruct : buffers_)
{
if (bufferStruct.position + bufferStruct.buffer.frameLength < playerTime && bufferStruct.available)
{
if (UpdateBuffer(bufferStruct.buffer))
{
ScheduleBuffer(bufferStruct);
}
}
}
, где playerTime
получается через AVAudioPlayerNode::playerTimeForNodeTime
и AVAudioPlayerNode::lastRenderTime
.
Эта схема отлично работает до тех пор, пока go приложение не перестанет работать в фоновом режиме, а затем вернется на передний план. Когда приложение переходит в фоновый режим, я прекращаю планирование AVAudioPCMBuffer
-s для AVAudioPlayerNode
и начинаю делать это снова, когда приложение переходит на передний план. Но в какой-то момент после того, как приложение перешло на передний план, AVAudioEngine
может перестать воспроизводиться, то есть его isRunning
возвращает NO
(оно может перестать играть после первого переключения фона или после десятого, я не вижу в нем никакого шаблона). isRunning
начинает возвращать NO
через некоторое время после того, как приложение возвращается на передний план, поэтому я могу слышать несколько звуков от устройства, и несколько буферов запланированы для воспроизведения.
И в этой ситуации я Я не могу ничего сделать, чтобы заставить его снова воспроизвести:
- Я попытался перезапустить его, позвонив
startAndReturnError
:
NSError *error = nil;
[engine_ startAndReturnError:&error];
if (![player_ isPlaying])
{
[player_ play];
}
Нет ошибок, возвращаемых startAndReturnError
но при планировании новых буферов для игрока обработчик завершения, переданный в [player_ scheduleBuffer: completionHandler:...]
, никогда не вызывается.
- Я попытался полностью воссоздать буферы и проигрыватель, но это не сработало.
- Я пытался воссоздать AVAudioEngine:
[engine_ stop];
[engine_ release];
, и это вызывает ошибку sh в 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 ()
Я подписан на AVAudioSessionInterruptionNotification, AVAudioSessionMediaServicesWereResetNotification, AVAudioSessionRouteChangeNotification, AVAudioEngineConfigurationChangeNotification
и ни один из них не вызывается.
Я использую устройство iPhone SE, 12.3.1.
Есть какие-нибудь предложения?