Выводы корня
Корневой выход позволяет реализовать пользовательские аудиосистемы или генераторы звука, а также интегрировать стороннее программное обеспечение (FMOD, Wise), которое записывает непосредственно на главный выход, полностью обходя встроенный микшер Unity.
Настройка корневого вывода
Для настройки корневых выводов из кода выполните следующие действия:
- Реализация интерфейсов: Предоставление реализаций
RootOutputInstance.IRealtimeиRootOutputInstance.IControl. - Выделение корневого выхода: Вызов
ControlContext.AllocateRootOutput, передавая ваши реализации реального времени и управления. - Уничтожить после завершения: Когда вывод root больше не требуется, вызвать
ControlContext.Destroyдля его освобождения.
Когда вы используете ControlContext.AllocateRootOutput со встроенным контекстом управления, он соединяет новый корневой выход с главным аудиовыходом Unity и использует часть реального времени вашего экземпляра для генерации аудио.
Этапы обработки корневого выхода
Реализации RootOutputInstance.IRealtime обрабатывают аудио в три этапа:
- Ранняя обработка: Выполняет работу, которая должна быть завершена перед последующими стадиями и перед использованием любых ресурсов, управляемых корневым выходом. Например, аппаратный ввод может пробовать свои данные здесь один раз, чтобы последующие стадии читали стабильный снимок.
- Обработка: Расписание основной части работы. Эта стадия выполняется параллельно с другими корневыми выводами. Если вы используете задания, вы отвечаете за управление зависимостями и обеспечение их завершения в порядке. При использовании других процессоров (например, генераторов) либо расписывайте ваши задания с предоставленной зависимостью входа, либо завершайте эту работу в первую очередь.
- Конечная обработка: Смешивание окончательных результатов в основной аудиовыход.
В конце ранней обработки каждый корневой выход может возвращать необязательный JobHandle. Перед началом стадии обработки Unity объединяет все возвращенные обработчики в одну зависимость и передает эту зависимость каждому корневому выходу во время обработки. Если вы планируете задания на стадии обработки, используйте эту зависимость, чтобы убедиться, что любая работа, начатая в ранней обработке, будет завершена первым.
Потоки и ограничения реального времени
Для каждого вызова корневого выхода, стадии ранней обработки, обработки и окончательной обработки выполняются последовательно на одном потоке. В зависимости от контекста управления, этот поток может быть потоком аудио (для встроенного контекста) или потоком рабочего задания (для контекстов ручного управления).
На всех трех этапах применяются следующие ограничения реального времени:
- Нет выделений памяти, ни управляемых, ни собственных.
- Нет системных вызовов (таких как доступ к файлам, работа в сети, запись на диск/консоль или спящий режим).
- Нет блокировок или блокирующих операций, таких как mutexes, ожидания событий/семафоров или блокировки доступа к файлам.
Передовая практика
- Следите за тем, чтобы стадии обработки оставались безопасными для реального времени. Избегайте выделений памяти, блокировок, блокирующего ввода-вывода, журналирования и выбрасывания исключений в аудиопотоке. Предпочитайте буферы на стеке или из пула и состояние на основе структур.
- Не вызывать
UnityEngineAPIs изProcess. Используйте потокобезопасные и безблокировочные подходы для синхронизации общего состояния. - Пишите код на структурах, компилируемый через Burst, с простыми типами-значениями и плотными циклами. Выбирайте
Unity.Mathematicsи разместить данные для Burst автовекторизации. - Возвращает допустимый
JobHandleс ранней стадии, если вы планируете работу там. - Сцепьте ваши задания на стадии обработки с комбинированной зависимостью, чтобы аудиоконвейер не останавливался в ожидании их завершения.