Найти тему
Rust.rs

Создание плагина Vst3 и Clap с помощью NIH-plug. Часть 2.

Оглавление

Статью можно найти здесь. Часть 1.

В первой части, мы создали базовый плагин, который имеет два параметра gain, bypass и настроили его для компиляции плагинов vst3 и clap.

Примеры можно найти на github:
Часть 1 в ветке gain,
Часть 2 в ветке synth.

Синтезатор

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

В методе process(), мы использовали буфер чтобы изменять в нем значения, тем самым мы создали эффект gain (усиление). Разница том, что мы принимали входные данные (const DEFAULT_INPUT_CHANNELS), чтобы использовать свою волну мы будем подменять значение.

Пример 1 и 2 одинаковый, но во втором мы сможем подменить входные данные.

-2

Ещё нам понадобится получить частоту дискретизации будущего сигнала.

-3
-4

Базовая волна.


Теперь, нам нужно создать функцию
sine() -> f32 которая будет генерировать значение нашей синусоиды. При каждой итерации наша функция должна выдавать новое значение от -1.0 до 1.0. Идея состоит в том чтобы взять окружность, и разделить на фрагменты. Где полный оборот вернет 0.0 (TAU).sin() = 0, а фрагмент вернет часть от оборота (например: f = 1/4 -> 1.0, f = 3/4 -> -1.0 ).

Мы получили формулу (TAU * f).sin().
-5

Далее уже можно подумать о частоте дискретизации, частоте волны...

Частота Найквиста - в цифровой обработке сигналов. Наивысшая частота полезного сигнала, равная половине частоты дискретизации.
-6

Далее я наткнулся на проблему. Для index я использовал time_buffer, это индекс семпла в буфере, как оказалось. С каждым новым буфером, сигнал начинался с начала.

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

-7

Изменение Кода

-8

Уже можно подставить наш осциллятор и получить синусоиду, но пока она будет звучать бесконечно.

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

Сложение волн

Полифонический синтезатор должен уметь создавать аккорды, т.е. сложение волны. Для каждой ноты он будет создавать осциллятор с частотой ноты.(например: А(ля) = 440Гц). Нам нужно получать от каждой волны семпл, сложить и это всё.

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

-9

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

-10

Midi-событие.

Наш плагин должен принимать `const MIDI_INPUT: MidiConfig = MidiConfig::Basic;`, далее в методе process, приходит context в виде миди событий, которые нужно будет обработать.

Я создал новую структуру Midi, которая принимает context в метод midi_input.context - это итератор. Получаю новое midi-сообщение и в цикле while, реагируем на него, и далее затеняю следующим midi-событием, и повторяем.

Как мы будем реагировать? Создаем HashMap, и будем записывать когда нота нажата, когда мы отпустим ноту мы удалим запись. Ключ будет нота, а значение всё событие, таким образом мы сможем получить любую информацию с события.

-11

Чтобы получить все активные ноты мы пройдемся по всем ключам в HashMap. Мы получим ноту и велосити, а так же нужно реализовать по счёт голосов.

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

-12

Далее... вспомним сложение волн. Анонимная функция создана таким образом, чтобы мы знали индекс волны и её ноту, и громкость ноты. Тем самым когда мы создаем голос (это копия осциллятора в векторе) мы знаем его индекс, и по индексу мы сможем использовать осциллятор, предать частоту с которой должна играть нота и предать в mix.

-13
-14

Итог

После компиляции мы получили полифонический синтезатор который генерирует синусоидальную волну.