Сколько звуков можно воспроизводить одновременно на iOS - AVAudioPlayer против AVAudioEngine и AVAudioPlayerNode - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть приложение, в котором есть набор из примерно 50 звуков, длина которых варьируется от примерно 300 мс до примерно 4 секунд. Различные комбинации звуков должны воспроизводиться в определенное время (до 10 из них могут быть запущены одновременно). Некоторые звуки необходимо повторять с интервалами до 100 мс.

Я реализовал это как двумерный массив AVAudioPlayers, каждый из которых загружается со звуками при запуске приложения. Есть несколько проигрывателей для каждого звука, чтобы приспособить быстро повторяющиеся звуки. Плееры для определенного звука повторно используются в строгом порядке. Когда запланирован новый звук, самый старый проигрыватель для этого звука останавливается, и его текущее время устанавливается на 0, поэтому звук будет повторяться с самого начала, в следующий раз, когда он запланирован с помощью player.play (atTime :). Есть нить, которая планирует новые наборы звуков за 300 мс до их воспроизведения.

Все это работает довольно хорошо, вплоть до точки, которая зависит от устройства. В конце концов, поскольку звуки воспроизводятся быстрее и / или запланировано больше одновременных звуков, некоторые звуки откажутся воспроизводить.

Я планирую переключиться на AVAudioEngine и AVAudioPlayerNodes, используя узел микшера. Кто-нибудь знает, может ли такой подход обрабатывать больше одновременных звуков? Я предполагаю, что оба подхода переводят в довольно похожий набор функций CoreAudio, но я на самом деле не написал код для проверки этой гипотезы - прежде чем я это сделаю, я надеюсь, что кто-то еще мог исследовать эту проблему до меня. Я был глубоко знаком с CoreAudio и надеюсь, что смогу вместо этого использовать эти удобные высокоуровневые функции!

Кроме того, кто-нибудь знает, как вызвать закрытие при запуске звука? Документированная функциональность допускает закрытие обратного вызова, но единственный способ, которым я смог инициировать события при запуске звуков, - это создать высококачественную очередь обслуживания для DispatchQueue. К сожалению, в зависимости от загрузки системы события в очереди могут выполняться в моменты времени, отличающиеся от запланированных, примерно до 50 мс, что не так точно, как хотелось бы.

1 Ответ

0 голосов
/ 02 мая 2020

Использование AVAudioEngine с AVAudioPlayersNodes обеспечивает гораздо лучшую производительность, хотя и за счет небольшой сложности кода. Я смог легко увеличить скорость воспроизведения в пять раз, с лучшим контролем буфера.

Основным недостатком перехода на этот подход было то, что документация Apple менее звездна. Несколько дополнений к документации Apple сделали бы эту задачу намного проще:

Узлы микшера задокументированы как способные преобразовывать частоты дискретизации и количество каналов, поэтому я попытался настроить audioEngine.mainMixerNode для преобразования монобуферов в Настройки выходного узла. Настройка вывода узла основного микшера в формат узла вывода, по-видимому, была принята, но вызвала непрозрачные ошибки во время выполнения, которые жаловались на несоответствие числа каналов.

Похоже, что основной узел микшера на самом деле не является полностью функциональным узлом микшера. Чтобы заставить это работать, мне пришлось вставить другой узел микшера, который выполнил преобразование канала, и подключить его к основному узлу микшера. Если бы документация Apple действительно упоминала об этом, это избавило бы меня от многих экспериментов.

Кроме того, простое планирование буфера ничего не вызывает для воспроизведения. Вам нужно вызвать play () на узле игрока, прежде чем что-либо произойдет. Документация Apple здесь сбивает с толку - она ​​говорит, что вызов play () без аргументов приведет к немедленному воспроизведению, а это не то, что я хотел. Потребовались некоторые эксперименты, чтобы определить, что play () просто указывает узлу игрока на пробуждение, и что запланированные буферы будут фактически воспроизводиться в запланированное время, а не сразу.

Было бы чрезвычайно полезно, если бы Apple предоставила не только автоматически сгенерированную документацию по классам. Немного сгенерированной человеком документации спасло бы меня от огромного количества разочаровывающих экспериментов.

Хорошо написанный Крисом Адамсоном "Learning Core Audio" был очень полезен, когда я работал с Core Audio - это позор, что новые функции AVAudioEngine также не документированы.

...