Как написать VST-плагин

Как написать VST-плагинМногие музыканты занимаются доводкой своих инструментов, собирают педальки, преампы и прочие аналоговые приборы. Это дает уверенность в том, что происходит после извлечения нот, как именно формируется звук, да и вообще является частью творческого процесса. Так получилось, что сам занимаюсь и музыкой, и цифровой обработкой сигналов (то, что называется модной аббревиатурой DSP), поэтому реализую свои звуковые замыслы не с паяльником в руках, а за ноутбуком.

Думаю, все, кто имеет хоть малейшее представление о современных аудио-редакторах знает, что такое VST. Поскольку формат очень распространен, и поддерживается подавляющим большинством редакторов, писать будем именно VST-плагин.

Постараюсь изложить все так, чтобы базового курса программирования и прямых рук было достаточно, чтобы все получилось.

Эта статья даст основу: подготовим необходимые инструменты для работы, реализуем один из самых простых эффектов — хард-клип овердрайв (или проще, цифровой дисторшн) и запустим его в редакторе.

Ставим и настраиваем все необходимое

Сначала скачаем необходимые программы:

  • Нам, конечно, понадобится DAW (редактор) с поддержкой vst, в котором мы будем обкатывать наш плагин. В целом, не так важно какой именно будем использовать, но в статье буду использовать Reaper, т. к. его можно скачать и опробовать в течение двух месяцев бесплатно: http://www. cockos. com/reaper/download. php
  • Нам понадобится SDK (это набор библиотек для разработки), который скачиваем отсюда: http://www. steinberg. net/en/company/developer. html — понадобится регистрация, но денег не просят. Качайте VST Audio Plug-Ins SDK второй версии, т. к. третью поддерживают далеко не все хосты (аудио-редакторы), в том числе и Reaper с тройкой не работает.
  • И последние: среда разработки. Будем использовать Microsoft Visual Studio Express 2013 для Windows Desktop (нужна именно desktop версия — не перепутайте!), который также бесплатен, нужна только регистрация: http://www. microsoft. com/visualstudio/rus/downloads

Устанавливаем Reaper и Visual Studio, распаковываем архив с SDK.

Запускаем Visual Studio. Чтобы не маяться с настройками проекта для начала используем пример из SDK.

Если мы не хотим затирать пример можно перед этим скопировать директорию “again” из “vstsdk2.4public. sdksamplesvst2.x” в ту же директорию, назвав ее, например, “overdrive”.

Открываем проект из нашего скачанного и распакованного SDK: “vstsdk2.4public. sdksamplesvst2.xagainwinagain. vcproj” или, соответственно “vstsdk2.4public. sdksamplesvst2.xoverdrivewinagain. vcproj”

Естественно, соглашаемся со всеми вопросами.

Для проверки нажмем “F7”. В выводе должно появиться что-то вроде:

«… again. dll

Сборка: успешно:1, с ошибками:0…»

Используем плагин

Открываем Reaper, создаем проект и добавляем дорожку. Для тестов в дорожку можно добавить звук какого-нибудь инструмента, например отсюда: http://www. freemusicloops. co. uk/free-guitar-loops/page/3

Теперь добавим директорию с нашим плагином в Reaper: идем Options > Preferences > VST и в VST plug-in paths выбираем нужную директорию (у меня “D:vstvstsdk2.4public. sdksamplesvst2.xoverdrivewinDebug”) и жмем re-scan.

Теперь в списке VST-эффектов появился “VST: Gain (x86) (Steinberg Media Technologies)”. Это только что скомпилированный (по F7) плагин. Добавляем эффект к дорожке, проверяем, что работает ползунок “Gain” в его настройках, сохраняем и закрываем проект (закрываем, чтобы он не блокировал dll-файл плагина на запись).

Я также добавил в проект JS: Analysis/gfxscope, по которому потом будем смотреть форму сигнала.

Пишем самый простой плагин

Общий план

Самая нудная часть позади, перейдем к интересному.

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

Как это работает

Сначала общая суть:

На вход программа будет получать отрывок фиксированной длинны (в несколько миллисекунд), и возвращать отрывок после преобразования. Поскольку отрывки эти очень короткие, обработка может происходить в реальном времени (с незначительной задержкой). Т. е. при наличии ASIO-карточки вполне можно играть через него.

Алгоритм

Для хардклипа нам нужно 1) усилить сигнал 2) срезать его выше некоторого значения.

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

Пишем код

Наш главный файл again. cpp находим в «обозревателе решений»: again/Source Files/again. cpp

Открываем его. Нам нужнен метод (функция) AGain:processDoubleReplacing, который находится в самом низу файла. Сначала разберем что в нем есть сейчас:

  • Аргумент inputs — входные данные, outputs — выходные данные, sampleFrames — длина входа и выхода в семплах (то есть, размер массивов).
  • Дальше, для тех кто знаком с указателями — все должно быть понятно, для остальных звездочки — это «магия». Главное что нужно знать: (*in1) и (*in2) — это семпл из левого и правого каналов соответственно, в (*out1) и (*out2) нам нужно записать что получилось после преобразования.
  • Сейчас, в примере, преобразование заключается в умножении входного сигнала на коэффициент dGain (т. е. просто меняется громкость сигнала.), который привязан к ползунку в графическом интерфейсе.

Выше есть метод AGain:processReplacing с тем же алгоритмом, но работает метод с float, а не double — она будет выполнятся в режиме одинарной точности (32-bit), но в Reaper по умолчанию установлена двойная (64-bit). В готовом плагине, конечно, нужно иметь обе функции.

Я обещал «базовый курс программирования», поэтому переписал метод в следующем виде (результат его работы ровно тот же):

Дисторшн будет отличаться тем, что сигнал должен обрезаться на отметке 1.

Нам нужна функция std:min, которая возвращает меньшее из переданных в нее значений. Подключаем в начале файла соответствующую библиотеку (после #include “again. h”):

#include

И теперь преобразование выглядит так:

Здесь умножаем на 30 для того, чтобы входной сигнал усиливался — иначе не будет перегруза. Клиппинг получается за счет того, что мы берем минимальное значение из 1.0 и полученного после умножения числа, соответственно больше 1.0 на выходе не получается.

Если мы попробуем скомпилировать (нажать F7; если вдруг ругается на то что не может записать dll — значит не закрыт проект в редакторе) и проверить в Reaper, то увидим что эффект работает, клиппинг есть.

Теперь нам нужно, чтобы клиппинг работал с двух сторон. Соответственно, нужно и ограничеть с двух сторон: минимальное значение в 1 уже есть, теперь добавим максимальное в -1:

И получаем:

Возможно, более понятный вариант программы через if-else :

И, тот же алгоритм в AGain:processReplacing для режима 32-bit:

That’s all Falks!

Что дальше?

Саму программу можно и нужно привести в порядок, я описал лишь минимально необходимый набор действий, чтобы получить плагин со своим алгоритмом. Так что, небольшой todo list:

  • Переименовать название (again) проекта, файлов и классов
  • Добавить собственное название в AGain:getProductString и AGain:getVendorString
  • Стоит поработать над GUI и контролами, например кроме pre-gain можно добавить и post-gain (без клиппинга), добавить возможность установки соотношения wet-dry.

Но последний пункт — тема для отдельной статьи, а если наводить красоту — то и цикла статей. Сами же алгоритмы обработки — все время появляются, развиваются и множатся.