[Программирование, Звук] VSTi-плагин ASIO-хоста для подключения входа дополнительного ASIO-драйвера в DAW

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
15-Ноя-2020 05:30

Столкнулся я как-то с ситуацией, когда, при наличии основной звуковой карты со своим ASIO-драйвером, необходимо было в DAW подключить USB-микрофон со своим ASIO-драйвером. А DAW не поддерживает подключение двух ASIO-драйверов одновременно. Поиском наткнулся на VST-плагин "VST interfaced ASIO-Host", написанный на Delphi. К сожалению, хоть и плагин увиделся через jBridge, нормально он так и не заработал. Таким образом, пришлось писать подобный плагин самому. В итоге, за 10 дней был написан плагин ASIOInput с открытым исходным кодом. В этой статье я расскажу о некоторых особенностях его разработки и архитектуры.
Сам VST-плагин технически является .dll, которая экспортирует единственную функцию SVSTPlugin* VSTPluginMain(void*) Эту функцию вызывает DAW и получает указатель на структуру данных, в которой хранится вся информация о загруженном плагине. Чтобы плагин функционировал, нужно заполнить как минимум следующие поля.
  • InputCount и OutputCount - количество входных и выходных каналов. Количество каналов - это строго заданная величина на этапе загрузки плагина, и в дальнейшем она меняться не может. Поэтому здесь я задаю 0 входных каналов и 2 выходных канала. Если потребуется 1 реальный канал, то он будет продублирован по обоим выходам плагина.
  • PluginProperties - флаги свойств плагина. Здесь задаем 3 флага: наличие собственного интерфейса, поддержка колбэка UpdateBufferData() и то, что плагин является инструментом - в некоторых DAW для инструментов заводятся отдельные дорожки в микшере, что удобно.
  • Колбэк RequestFromHost() - эту функцию будет вызывать DAW, чтобы проинформировать плагин о некоторых событиях. Минимально реализованный в плагине набор событий следующий: инициализация и де-инициализация плагина, приостановка и возобновление работы плагина, изменение частоты семплирования, изменение размера буфера семплов, а также события для графического интерфейса плагина: показать и скрыть окно редактора, получить размер окна редактора, и событие простоя - для перерисовки элементов интерфейса окна редактора.
  • Колбэк UpdateBufferData() - DAW вызывает эту функцию, когда ему нужно получить значения очередного набора звуковых семплов. Здесь же, в параметрах, указывается, сколько именно семплов хочет получить DAW при каждом вызове этой функции.
Дочерний же ASIO драйвер является Windows COM-объектом. Доступ к нему осуществляется по GUID-ам. Список всех ASIO-драйверов (имена и GUID-ы) хранится в реестре по адресу HKEYLOCALMACHINE\SOFTWARE\ASIO. Для работы с ASIO-драйвером, после инициализации COM-объекта по GUID-у функцией CoCreateInstance(), нужно инициализировать сам ASIO-драйвер, создать буферы для семплов, и непосредственно запустить ASIO-драйвер. Причем при вызове функции создания буферов семплов, необходимо также передать указатели на колбэки обновления данных в буфере и запросов от ASIO-драйвера к хосту. Таким образом получается, что у плагина вызываются извне две функции: DAW вызывает функцию, где плагин должен заполнить данные выходных семплов от плагина в DAW - VSTPluginCallUpdateBufferData(), и дочерний ASIO-драйвер вызывает функцию, где отдает плагину очередную порцию данных семплов со входа звуковой карты - ASIOHostCallUpdateBufferDataEx(). Причем эти функции вызываются независимо друг от друга. А в случае, если размеры буферов семплов DAW и дочернего ASIO-драйвера разные, то еще и разное количество раз в секунду. Нам же необходимо передать данные от дочернего ASIO-драйвера в DAW, причем сделать это с минимальной задержкой. В случае с одинаковым размером буфера семплов я применил синхронизацию двух вызовов. Таким образом, при запросе DAW-ом семплов от плагина, вызов функции приостанавливается до ближайшего вызова из дочернего ASIO-драйвера, в котором происходит обновление буфера DAW напрямую, только после чего функция запроса DAW-ом семплов от плагина отпускается и завершается. Технически синхронизация обеспечивается ожиданием событий ОС Windows (функции CreateEvent(), SetEvent() и WaitForSingleObject()). Если же размер буферов DAW и дочернего ASIO-драйвера разный, то применяется кольцевой буфер. Колбэк дочернего ASIO-драйвера записывает данные в кольцевой буфер, а колбэк DAW-а считывает данные. Чтобы чтение не происходило во время записи, используется мютекс OC Windows. Размер кольцевого буфера выбирается как максимальный из размеров буферов DAW и дочернего ASIO-драйвера, и может настраиваться пользователем х2, х3 и х4.
Подводные камни при разработке плагина.
  • У COM-объекта ASIO-драйвера все функции возвращают 0 в случае успеха. Все, кроме функции инициализации. Она, в случае успеха, возвращает 1. Минус один вечер отладки.
  • DAW передает в плагин дескриптор родительского окна. Если после события скрытия окна редактора, не снять привязку окна редактора с этим дескриптором, то окно редактора плагина продолжает отображаться, но, в случае с DAW Cubase 9.5, поверх системного меню DAW - т.е. поверх "Файл, Правка" и т.д.
  • Если при создании буферов семплов указать ASIO-драйверу некорректное значение, то буферы создадутся с нужными ASIO-драйверу корректными размерами, но частота вызова колбэка будет рассчитана некорректно, и колбэк будет вызываться неверное количество раз в секунду. При этом функция создания буферов вернет 0. Еще минус один вечер отладки.
  • Не стоит де-инициализировать COM-объект дочернего ASIO-драйвера из колбэка самого ASIO-драйвера.
Скриншот ранней версии плагина с дополнительной отладочной информацией.
Скачать последнюю версию плагина (VST2, x86 и x64): тыц.Исходники на гитхабе: тыц.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_zvuk (Звук), #_asio, #_vst, #_daw, #_sinhronizatsija_potokov (синхронизация потоков), #_programmirovanie (
Программирование
)
, #_zvuk (
Звук
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 15:22
Часовой пояс: UTC + 5