Unity 6.3
0 онлайн 38 гостей 3 в системе
Вход

Генераторы

Генератор — это пользовательский источник звука, который производит звук и вводит его непосредственно в сцену, обычно через AudioSource. Генераторы являются ключевыми точками расширения сценария аудиоконвейера и позволяют синтезировать или передавать поток аудио в реальном времени.

Генератор можно подключить к AudioSource двумя способами: рабочий процесс на основе ассетов и рабочий процесс на основе компонентов.

Оба рабочих процесса основаны на внедрении IAudioGenerator интерфейс, который выступает фабрикой для создания экземпляров вашего генератора.

Рабочий процесс, основанный на ассетах

Создайте ScriptableObject, который реализует IAudioGenerator.

using UnityEngine;

[CreateAssetMenu(fileName = "MyAssetBasedGenerator", menuName = "Audio/Generators/My Asset-Based Generator", order = 1)]
public class MyAssetBasedGenerator : ScriptableObject, IAudioGenerator
{
    public bool isFinite => ...;
    public bool isRealtime => ...;
    public DiscreteTime? length => ...;

    public GeneratorInstance CreateInstance(
        ControlContext context,
        AudioFormat? nestedConfiguration,
        ProcessorInstance.CreationParameters creationParameters)
    {
        return context.AllocateGenerator(new MyRealtime(...), new MyControl(...));
    }
}

После создания ассета вы можете назначить его AudioSource, перетаскивая его в поле Generator в Inspector.

Рабочий процесс на основе компонентов

Чтобы использовать рабочий процесс на основе компонентов, определите MonoBehaviour, который реализует IAudioGenerator, а затем добавьте его в GameObject в вашей сцене. В Inspector для AudioSourceназначите этот компонент в поле Генератор.

using UnityEngine;

public class MyComponentBasedGenerator : MonoBehaviour, IAudioGenerator
{
    public bool isFinite => ...;
    public bool isRealtime => ...;
    public DiscreteTime? length => ...;

    public GeneratorInstance CreateInstance(
        ControlContext context,
        AudioFormat? nestedConfiguration,
        ProcessorInstance.CreationParameters creationParameters)
    {
        return context.AllocateGenerator(new MyRealtime(...), new MyControl(...));
    }
}

IAudioGenerator interface

IAudioGenerator включает в себя следующее:

  • Возможности: Свойства, такие как GeneratorInstance.ICapabilities, которые описывают, как генератор ведет себя заранее.
  • Фабричный метод: Метод CreateInstance, который аудиосистема вызывает для создания GeneratorInstance.

Ниже приводится список возможностей:

  • Конечный: Если true, то генератор в конечном итоге прекратит работу. Общая длина не должна быть известна заранее.
  • Реальное время: значение true означает, что генератор должен работать в реальном времени с размером буфера и частотой дискретизации системы. Например, это потоки, управляемые оборудованием, графы, которые нельзя выполнять с опережением, или всё, что имеет внутреннюю временную шкалу, синхронизированную с системными часами dsp. Если не уверены, задайте false.
  • Длина: Если генератор конечен и вы знаете его общую длину, сообщите об этом здесь. Хотя это необязательно, обнаружение этого свойства полезно для инструментов редактора и планирования.

Вы должны раскрыть соответствующие возможности в вашем GeneratorInstance.IRealtime несоответствие между уровнем IAudioGenerator и IRealtime может привести к неожиданному поведению и предупреждениям в Консоли.

Настройка генератора

Конфигурация генератора происходит изначально во время создания, и дополнительно, когда система изменяет конфигурацию. Это обычно происходит в ответ на действия пользователя, такие как изменение устройства аудио выхода в системных настройках OS или при подключении пары наушников. Это двухступенчатая переговорка между хостом (владельцем генератора) и генератором:

  1. Хост предлагает предпочтительный AudioFormat для генератора (частота дискретизации, расположение динамиков, размер буфера).
  2. Генератор сообщает Setup, который он будет фактически использовать.

Некоторые генераторы (e.g. при синтезе аудио) могут адаптироваться к многим форматам, в то время как другие (e.g. при воспроизведении аудио файлов) могут поддерживать только нативный формат файла. Если генератор выбирает другой формат, чем предложенный хостом, то ответственность за преобразование между форматами при необходимости лежит на хосте.

При создании дочерних генераторов с помощью ControlContext.AllocateGeneratorродитель может предоставить дополнительный AudioFormat в качестве предложения для дочери. Дети должны следовать предложению, когда это возможно, чтобы минимизировать преобразования.

Обработка генератора

Генераторы всегда обрабатываются в цикле смешивания. Описание циклов смешивания см. в подразделе циклы смешивания в разделе Концепции скриптовых процессоров.

Вложенные генераторы

Генераторы могут быть организованы в иерархические деревья. В каждом дереве корневой генератор находится на вершине и отвечает за вызов Configure, Updateи Process на своих непосредственных дочерних генераторах. Каждый дочерний, в свою очередь, пересылает эти вызовы своим собственным дочерним. Эта схема позволяет создавать сложные структуры, такие как микшеры, контейнеры смешивания и случайные секвенсеры.

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

Передовая практика

Рассмотрим следующее:

  • Держите Process безопасными для реального времени. Избегайте выделений памяти, блокировок, блокирующего ввода-вывода, журналирования и выбрасывания исключений в аудиопотоке. Используйте буферы на стеке или из пула и состояние на основе структур — это даёт предсказуемую производительность.
  • Никогда не вызовайте UnityEngine APIs из Process. С помощью каналов синхронизируйте состояние между управляющей частью и частью реального времени и избегайте многопоточного взаимодействия, способного дать недетерминированный результат.
  • Пишите код на структурах, компилируемый через Burst. Для повышения производительности используйте простые типы-значения и плотные циклы. Задействуйте Unity.Mathematics и организовать данные для оптимальной Burst автовекторизации.
  • Убедитесь, что значения isFinite, isRealtimeи length в реализации IAudioGenerator совпадают со значениями в GeneratorInstance.IRealtime.
  • Используйте формат хоста, когда это возможно. Принятие предложенного хостом AudioFormat минимизирует дополнительное ресэмплирование или смешивание каналов.
  • Предоставление точного свойства length позволяет улучшить предварительный просмотр формы волны, планирование и индикаторы прогресса в Редакторе.
  • Когда конечный генератор достигает конца, возвращайте молчание и сигнал завершения, чтобы хосты могли выделить или перейти.
  • Проверка внешних входов. Зажим параметров вне диапазона до действительных диапазонов и обработка несоответствий в количестве каналов для предотвращения ошибок.

Дополнительные ресурсы: