У меня есть приложение, в котором есть набор из примерно 50 звуков, длина которых варьируется от примерно 300 мс до примерно 4 секунд. Различные комбинации звуков должны воспроизводиться в точное время (до 10 из них могут быть вызваны одновременно). Некоторые звуки необходимо повторять с интервалом в 100 мс.
Я реализовал это как двумерный массив AVAudioPlayers, каждый из которых загружается звуком при запуске приложения. Для каждого звука есть несколько проигрывателей, чтобы приспособить быстро повторяющиеся звуки. Плееры для определенного звука повторно используются в строгой ротации. Когда планируется новый звук, самый старый проигрыватель для этого звука останавливается, а его текущее время устанавливается равным 0, поэтому звук будет повторяться с самого начала в следующий раз, когда он будет запланирован с помощью player.play(atTime:). Есть поток, который планирует новые наборы звуков примерно за 300 мс до их воспроизведения.
Все это работает довольно хорошо, вплоть до момента, который зависит от устройства. В конце концов, по мере того, как звуки воспроизводятся быстрее и/или планируется большее количество одновременных звуков, некоторые звуки отказываются воспроизводиться.
Я подумываю о переходе на AVAudioEngine и AVAudioPlayerNodes, используя узел микшера. Кто-нибудь знает, может ли этот подход обрабатывать больше одновременных звуков? Я предполагаю, что оба подхода преобразуются в довольно похожий набор функций CoreAudio, но на самом деле я не писал код для проверки этой гипотезы — прежде чем я это сделаю, я надеюсь, что кто-то еще исследовал эту проблему до меня. Раньше я был глубоко в CoreAudio, и я надеюсь, что вместо этого смогу использовать эти удобные высокоуровневые функции!
Кроме того, кто-нибудь знает способ вызвать закрытие, когда звук инициируется? Задокументированная функциональность позволяет закрытие обратного вызова, но единственный способ, которым я смог инициировать события при запуске звуков, — это создать очередь обслуживания высокого качества для DispatchQueue. К сожалению, в зависимости от загрузки системы, события в очереди могут выполняться во время, отличающееся от запланированного примерно на 50 мс, что не так точно, как хотелось бы.