Vst что за формула

Мощность

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Статья находится на проверке у методистов Skysmart.
Если вы заметили ошибку, сообщите об этом в онлайн-чат
(в правом нижнем углу экрана).

Определение мощности

Допустим, нам необходимо убрать урожай пшеницы с поля площадью 100 га. Это можно сделать вручную или с помощью комбайна. Очевидно, что пока человек обработает 1 га площади, комбайн успеет сделать намного больше. В данном случае разница между человеком и техникой — именно то, что называют мощностью. Отсюда вытекает первое определение.

Мощность в физике — это количество работы, которая совершается за единицу времени.

Рассмотрим другой пример: между точкой А и точкой Б расстояние 15 км, которое человек проходит за 3 часа, а автомобиль может проехать всего за 10 минут. Понятно, что одно и то же количество работы они сделают за разное время. Что показывает мощность в данном случае? Как быстро или с какой скоростью выполняется некая работа.

В электромеханике данная величина тоже связана со скоростью, а конкретно — с тем, как быстро передается ток по участку цепи. Исходя из этого, мы можем рассмотреть еще одно определение.

Мощность — это скалярная физическая величина, которая характеризует скорость передачи энергии от системы к системе или скорость преобразования, изменения, потребления энергии.

Напомним, что скалярными величинами называются те, значение которых выражается только числом (без вектора направления).

Мощность человека в зависимости от деятельности

Вид деятельности

Мощность, Вт

Бег со скоростью 9 км/ч

Плавание со скоростью 50 м/мин

Как обозначается мощность: единицы измерения

В таблице выше вы увидели обозначение в ваттах, и читая инструкции к бытовой технике, можно заметить, что среди характеристик прибора обязательно указано количество ватт. Это единица измерения механической мощности, используемая в международной системе СИ. Она обозначается буквой W или Вт.

Измерение мощности в ваттах было принято в честь шотландского ученого Джеймса Уатта — изобретателя паровой машины. Он стал одним из родоначальников английской промышленной революции.

В физике принято следующее обозначение мощности: 1 Вт = 1 Дж / 1с.

Это значит, что за 1 ватт принята мощность, необходимая для совершения работы в 1 джоуль за 1 секунду.

В каких единицах еще измеряется мощность? Ученые-астрофизики измеряют ее в эргах в секунду (эрг/сек), а в автомобилестроении до сих пор можно услышать о лошадиных силах.

Интересно, что автором этой последней единицы измерения стал все тот же шотландец Джеймс Уатт. На одной из пивоварен, где он проводил свои исследования, хозяин накачивал воду для производства с помощью лошадей. И Уатт выяснил, что 1 лошадь за секунду поднимает около 75 кг воды на высоту 1 метр. Вот так и появилось измерение в лошадиных силах. Правда, сегодня такое обозначение мощности в физике считается устаревшим.

Одна лошадиная сила — это мощность, необходимая для поднятия груза в 75 кг за 1 секунду на 1 метр. 🐴

Источник

Программирование&Музыка: Частотный фильтр Баттервота. Часть 3

Всем привет! Вы читаете третью часть статьи про создание VST-синтезатора на С#. В предыдущих частях был рассмотрен SDK и библиотеки для создания VST плагинов, рассмотрено программирование осциллятора и ADSR-огибающей для управления амплитудой сигнала.

В этой части я расскажу, как рассчитать и закодить фильтр частот, без которого не обходится ни один синтезатор. А без эквалайзера немыслима обработка звука.

Внимание — будет много матана — будем рассчитывать формулы для коэффициентов фильтра.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Скриншот VST плагина-эквалайзера Fab Filter Pro Q

Цикл статей

Оглавление

Эквалайзер

Часто при обработке звука мы хотим изменить его характер/окраску/тембр. Сделать звук более басовым, убрать верхние частоты, или наоборот, сделать звук «прозрачным», оставив лишь середину и верха. Уверен, многие люди, не работавшие с обработкой звука, знают что такое эквалайзер — они есть акустических колонках, музыкальных центрах, магнитофонах, плеерах, и т.д. Эквалайзер — это набор фильтров, каждый из которых изменяет амплитуду сигнала в его выбранной полосе частот. На бытовых колонках это, обычно, 2-3 крутилки — низкие частоты, средние и верха, с фиксированными полосами частот.

В Winamp’овском эквалайзере уже есть 10 заранее определенных полос.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Скриншот эквалайзера в плеере Winamp

В мире обработки звука существует множество плагинов-эквалайзеров, на любой вкус и цвет. Плагин Fab Filter Pro Q (скриншот в начале статьи) — это графический эквалайзер, позволяющий создавать большое число полос и редактировать их параметры.

Каждая полоса в эквалайзере — это, по сути, фильтр частот. Фильтры частот изменяют тембральные/частотные характеристики сигнала. В электронике существуют много типов и классификаций фильтров, с соответствующими характеристиками и параметрами — смотрим википедию.
Мы рассмотрим и запрограммируем самые простые фильтры: НЧ, ВЧ и полосовой фильтры.

Фильтрация через преобразование Фурье

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

Если не думать над реализацией ДПФ, то такой подход я бы назвал достаточно интуитивным и простым в программировании (опять же, если взять ДПФ из какой-нибудь либы и не кодить самому).

Минусы подхода — во-первых, ДПФ принимает на вход массив из семплов, размер которого является степенью двойки. Это значит, что выходной сигнал уже будет с задержкой. Во вторых, каждый 512-й семпл мы будем производить данный алгоритм: ДПФ, обработка частот сигнала, обратное ДФП. Это не малые вычисления. В-третьих, есть еще минусы и тонкости, которые знают адепты цифровой обработки сигналов.

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

Цифровые фильтры

Большую часть информации и вывод формул я взял из книги Digital Signal Processing: A Practical Approach — очень рекомендую, она есть в русской версии — Цифровая обработка сигналов. Практический подход, заинтересованные найдут PDF в сети.

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

Когда я начинал гуглить код фильтров, я сразу находил множество непонятного математического кода, и хотелось хоть чуть-чуть понять, откуда берутся такие рассчетные формулы. Осциллятор, огибающая, дилей — понимание и программирование работы этих составляющих лично мне кажется интуитивным, но только не фильтров. Этой статьей я хочу пробудить интерес к цифровой обработке сигналов) Буду рад, если возникнет желание разобраться в этой теме более основательно.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Аппроксимация АЧХ идеального фильтра (картинка из советского учебника, не нашел исходник)

Фильтр изменяет сигнал, «убирая» в нем выбранные частоты. Существующие фильтры не идеальны. Полоса пропускания — полоса частот, которую фильтр «не затрагивает» (на графике есть некоторая Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формулаизменения — особенность неидеального представленного фильтра). Полоса подавления — полоса нежелательных частот. В полосе перехода происходит спад частот. Естественно, фильтр ближе к «идеальному» тем, насколько меньше он искажает полосу пропускания, насколько сильно он подавляет частоты в полосе подавления и насколько узка полоса перехода. Есть разные «приближения» фильтров — фильтр Чебышёва, Баттервота, и так далее — их вы найдете в книжках и на просторах сети.

Почему фильтр Баттервота?

Все очень просто, АЧХ фильтра Баттерворта максимально гладкая на частотах полосы пропускания — имхо, важнее всего не испортить сигнал в полосе пропускания.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Логарифмическая АЧХ для фильтров Баттерворта нижних частот разных порядков (скриншот взят с Википедии)

Вывод формулы фильтра НЧ

Передаточная функция для фильтра Баттервота на s-плоскости записывается следующими формулами:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формулапри четных n и
Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формулапри нечетных n

Чтобы получить сверточные коэффициенты, нужно получить передаточную функцию на z-плоскости в виде

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Тогда свертка для фильтра будет выглядеть так:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

В формуле нужно использовать денормированные частоты, т.е. произвести замену (в полосовом фильтре будут две частоты w1 и w2, определяющие полосу пропускания):

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Если мы хотим рассчитывать НЧ-фильтр, то нужно сделать преобразование — произвести замену параметра s в передаточной функции:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Для рассчета других типов фильтров (ВЧ, полосового, режекторного) нужно делать другие замены. Они рассмотрены в книге Цифровая обработка сигналов. Практический подход в части 8.8.2 и далее в статье.

Далее, для перехода в z-плоскость делаем замену:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Для аналитических рассчетов я использовал пакет Mathematica.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

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

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Найдем коэффициенты при степенях у полученных полиномов, используя функцию CoefficientList:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Если все делать честно, то, по условию, a0 должен быть равен 1 — поделим на a0 все коэффициенты (для кодинга будем использовать предыдущие формулы без деления):

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Вывод формулы фильтра ВЧ и полосового фильтра

Вывод формул для ВЧ-фильтра аналогичен НЧ-фильтру с другим преобразованием:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Для вывода формул полосового фильтра применяется преобразование:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Если производить замену, то степень полиномов в числителе и знаменателе H(z) удвоится (в замене есть s^2), значит порядок фильтра увеличится вдвое. Поэтому изначально используем функцию H(s) для n = 1:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Программирование фильтра Баттервота по полученным формулам

Фильтр будет иметь 2 параметра: тип фильтра (НЧ, ВЧ, полосовой) и частота среза w. Для полосового фильтра будем рассматривать частоту среза как частоту посередине полосы пропускания. Полосу пропускания же определим как отрезок частот [w — w/4, w + w/4] (можно придумать здесь более сложный и логичный здесь логарифмический закон, на ваше усмотрение).

Пусть мы определили коэффициенты b0, b1, b2, a1 и a2 (a0 по условию равен 1) по рассчитанным формулам. Алгоритм работы фильтра сводится к свертке, которая делается последовательно для каждого семпла:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

y(n) — это новое значение семпла, которое нужно рассчитать. x(n) — текущее значение семпла, соответственно y(n-1) и y(n-2) — предыдущие 2 рассчитанных семпла, а x(n-1) и x(n-2) — предыдущие входные значения семплов.

Нужно организовать запоминание предыдущих семплом. Не будем мудрить с циклическими буферами, сделаем просто и понятно: два массива из трех элементов. Каждый раз будем «проталкивать» новые значения в этот массив, последовательно копируя более старые значения семплов.

Получаем простой класс:

Напишем каркасный класс для фильтра (смотри архитектуру синтезатора в первой статье). Класс BiquadConvolutionTable работает с одним сигналом, т.е. с одним каналом — моно. Поэтому нам нужны две BiquadConvolutionTable — для левого и правого каналов.

Чтобы корректно применить фильтр, нужно последовательно, для всех семплов входящей последовательности применить функцию BiquadConvolutionTable.Process и заполнить результирующий массив семплов.

Рассчетом коэффициентов для BiquadConvolutionTable будет заниматься функция CalculateCoefficients.

Функция CalculateCoefficients вызывается каждый раз в цикле — зачем? В следующей статье я расскажу про модуляцию (изменение во времени) параметров, и поэтому, частота среза может меняться, а значит, нужно перерассчитывать коэффициенты. Конечно, по-трушному, нужно подписаться на изменение частоты среза и уже в обработчике рассчитывать коэффициенты. Но в этих статьях я оптимизами заниматься не буду, цель — закодить фильтр.

Осталось закодить функцию CalculateCoefficients по рассчитаным формулам для коэффициентов.
Вспомним, что нужно использовать денормированные частоты, т.е. произвести замену:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Списываем все формулы для коэффициентов b0, b1, b2, a0, a1, a2. После рассчетов нужно поделить все коэффициенты на a0, чтобы a0 стало равно 1.

Полосовой эквалайзер в библиотеке NAudio

Она содержит пространство имен NAudio.Dsp с функционалом для фильтрации, свертки, гейта, огибающей, БПФ и других интересных штук.

Рассмотрим класс Equalizer (из примеров, пространство имен NAudioWpfDemo.EqualizationDemo), позволяющий производить эквализацию сигнала. Класс реализует ISampleProvider, который в функции Read(float[] buffer, int offset, int count) обрабатывает (изменяет) массив семплов buffer.

Конструктор принимает массив структуры EqualizerBand, которые описывают «полосы» эквалайзера:

Здесь Frequency — центральная частота полосы с параметром Q (Bandwidth, добротность фильтра), c усилением Gain dB.

Если заглянуть в реализацию, то каждой полосе EqualizerBand соответствует класс BiQuadFilter который используется как полосовой (Peaking) фильтр. Все фильтры изменяют сигнал используются последовательно.

Класс EqualizerBand является реализацией фильтра Баттервота, с большим выборов типов фильтров и параметрами. Если посмотреть реализацию, можно увидеть схожие формулы и коэффициенты.

Пример использования класса Equalizer вы найдете в проекте NAudioWpfDemo в классе EqualizationDemoViewModel.

Программы для рассчета фильтров

Прародителем цифровых фильтров были фильтры аналоговые. Теория для аналоговых схем и аналоговой обработке сигналов в дальнейшем переросла в теорию цифровой обработки сигналов.

Для рассмотренного фильтра Баттервота и рассчитанных формул для коэффициентов можно собрать аналоговую схему.

Есть много программ для рассчета и построения схем, параметров элементов для них, сверточных коэффициентов различных фильтров.
Можете погуглить по «filter calculation software».

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Iowa Hills Software RF Filter Designer

В следующей статье я расскажу про эффект delay, distortion и модуляцию параметров.

Всем добра! Удачи в программировании!

Список литературы

Не забывайте смотреть списки статей и книг в предыдущих статьях.

Источник

Программирование&Музыка: понимаем и пишем VSTi синтезатор на C# WPF. Часть 1

Занимаясь музыкальным творчеством, я часто делаю аранжировки и записи на компьютере — используя кучу всяких VST плагинов и инструментов. Стыдно признаться — я никогда не понимал, как «накручивают» звуки в синтезаторах. Программирование позволило мне написать свой синтезатор, «пропустить через себя» процесс создания звука.

Я планирую несколько статей, в которых будет пошагово рассказано, как написать свой VST плагин/инструмент: программирование осциллятора, частотного фильтра, различных эффектов и модуляции параметров. Упор будет сделан на практику, объяснение программисту простым языком, как же все это работает. Теорию (суровые выводы и доказательства) обойдем стороной (естественно, будут ссылки на статьи и книги).

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

Предстоит нелегкий путь, если вы готовы — добро пожаловать под кат.

Цикл статей

Оглавление

Загадочный мир синтеза звука

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

Перебирая пресеты одного синтезатора можно встретить как «ожидаемый» звук электронного синтезатора из детства (музыка из мультика Летучий Корабль) так и имитацию ударных, звуков, шума, даже голоса! И все это делает один синтезатор, с одними и теми же ручками параметров. Это меня всегда удивляло, хотя я понимал: каждый звук — суть конкретная настройка всех ручек.

Недавно я решил наконец-таки разобраться, каким же образом создаётся (или, правильнее сказать, синтезируется) звук, как и почему нужно крутить ручки, как видоизменяется от эффектов сигнал (визуально и на слух). И конечно же, научиться (хотя бы понять основы) самому «накручивать» звук, копировать понравившиеся мне стили. Я решил последовать одной цитате:

«Скажи мне — и я забуду, покажи мне — и я запомню, дай мне сделать — и я пойму.»
Конфуций

Конечно, все подряд делать не надо (куда столько велосипедов?), но сейчас я хочу получить знания и самое главное — поделиться ими с вами.

Цель: не углубляясь в теорию, создать простой синтезатор, сделав упор на объяснение процессов с точки зрения программирования, на практике.

В синтезаторе будут:

Все составляющие я планирую рассмотреть в нескольких статьях. В данной будет рассмотрено программирование осциллятора.

Программировать будем на C#; UI можно писать либо на WPF, либо на Windows Forms, либо вообще обойтись без графической оболочки. Плюс выбора WPF — красивая графика, которую достаточно быстро кодить, минус — только на Windows. Владельцы других ОС — не расстраивайтесь, всё-таки цель — понять работу синтезатора (а не запилить красивый UI), тем более, код, который я буду демонстрировать, можно быстро перенести, скажем, на С++.

Программирование логики синтезатора начнется с главы Пишем простой осциллятор. Если вам не интересны технические стороны написания VST плагинов, вы просто хотите прочитать про, собственно, синтез (и ничего не кодить) — милости прошу сразу к этой главе.

Исходный код написанного мной синтезатора доступен на GitHub’е.

Звук в цифровом виде

По-сути, конечная наша цель — создание звука на компьютере. Обязательно прочитайте (хотя бы, бегло) статью на хабре «Теория звука» — в ней изложены базовые знания о представлении звука на компьютере, понятия и термины.

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

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

VST SDK

VST (Virtual Studio Technology) — это технология, позволяющая писать плагины для программ обработки звука. Сейчас существует большое множество плагинов, решающих различные задачи: синтезаторы, эффекты, анализаторы звука, виртуальные инструменты и так далее.

Чтобы создавать VST плагины, компания Steinberg (некоторые ее знают по программе Cubase) выпустила VST SDK, написанный на C++. Помимо технологии (или, как еще говорят, «формата плагинов») VST, есть и другие — RTAS, AAX, тысячи их. Я выбрал VST, из-за большей известности, большого количества плагинов и инструментов (хотя, большинство известных плагинов поставляется в разных форматах).

На данный момент актуальная версия VST SDK 3.6.6, хотя многие продолжают использовать версию 2.4. Исторически складывается, что сложно найти DAW без поддержки версии 2.4, и не все поддерживают версию 3.0 и выше.

VST SDK можно скачать с официального сайта.
В дальнейшем мы будем работать с библиотекой VST.NET, которая является оберткой для VST 2.4.

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

Сейчас я кратко изложу принципы VST SDK 2.4, для общего понимания работы плагина и его взаимодействия с DAW.

Дальнейшие функции, перечисления и структуры вы можете найти в скачанном VST SDK в исходниках из папки «VST3 SDK\pluginterfaces\vst2.x».

Библиотека должна экспортировать функцию со следующей сигнатурой:

Функция принимает указатель на коллбэк, чтобы плагин мог получать необходимую ему информацию от хоста.

Все делается на достаточно «низком» уровне — чтобы хост понял, что от него хотят, нужно передавать номер команды через параметр opcode. Перечисление всех опкодов хардкорные C-кодеры могут найти в перечислении AudioMasterOpcodesX. Остальные параметры используются аналогичным образом.

VSTPluginMain должна вернуть указатель на структуру AEffect, которая, по-сути, и является нашим плагином: она содержит информацию о плагине и указатели на функции, которые будет вызывать хост.

Основные поля структуры AEffect:

Информация о плагине. Название, версия, число параметров, число программ и пресетов (читай далее), тип плагина и прочее.

Фунции для запроса и установки значений параметров.

Функции смены пресетов/программ.

Фунция обработки массива семплов

float** — это массив каналов, каждый канал содержит одинаковое количество семплов (количество семплов в массиве зависит от звукового драйвера и его настроек). В основном встречаются плагины, обрабатывающие моно и стерео.

Супер-функция, подобна audioMasterCallback.

Вызывается хостом, по параметру opcode определяется необходимое действие (список AEffectOpcodes). Используется, чтобы узнать дополнительную информацию о параметрах, сообщать плагину об изменениях в хосте (изменение частоты дискредитации), для взаимодействия с UI плагина.

При работе с плагином было бы очень удобно, чтобы юзер мог сохранить все настроенные ручки и переключатели. А еще круче, чтобы была их автоматизация! Например, вы можете захотеть сделать знаменитый эффект rise up — тогда вам нужно менять параметр cutoff (частота среза) эквалайзера во времени.

Чтобы хост управлял параметрами вашего плагина, в AEffect есть соответствующие функции: хост может запросить общее количество параметров, узнать или установить значение конкретного параметра, узнать название параметра, его описание, получить отображаемое значение.

Хосту все равно, какая логика у параметров в плагине. Задача хоста — сохранять, загружать, автоматизировать параметры. Хосту очень удобно воспринимать параметр, как float-число от 0 до 1 — а уж плагин пусть как хочет, так его и толкует (так и сделали большинство DAW, неофициально).

Пресеты (в терминах VST SDK — programs/программы) это коллекция конкретных значений всех параметров плагина. Хост может менять/переключать/выбирать номера пресетов, узнавать их названия, аналогично с параметрами. Банки — коллекция пресетов. Банки логически существуют только в DAW, в VST SDK есть только пресеты и программы.

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

WDL-OL и JUCE

Чем плоха разработка на голом VST SDK?

На сцену выходит WDL-OL. Это C++ библиотека для создания кроссплатформенных плагинов. Поддерживаются форматы VST, VST3, Audiounit, RTAS, AAX. Удобство библиотеки состоит в том, что (при правильной настройке проекта) вы пишете один код, а при компилировании получаете свой плагин в разных форматах.

WDL-OL решает, по крайней мере, первые три пункта минусов разработки на VST SDK. Все, что вам нужно — корректно настроить проект (первая статья из блога), и отнаследоваться от класса IPlug.

Теперь с чистой совестью можно реализовать функцию ProcessDoubleReplacing, которая, по сути и является «ядром» плагина. Все заботы взял на себя класс IPlug. Если его изучать, можно быстро понять, что (в формате VST) он является оберткой структуры AEffect. Коллбэки от хоста и функции для хоста превратились в удобные виртуальные функции, с понятными названиями и адекватными списками параметров.

Помимо WDL-OL я так же узнал про библиотеку JUCE. JUCE похожа на WDL-OL, решает все заявленные минусы разработки на VST SDK. Помимо всего прочего, она уже имеет в своем составе и UI-редактор, и кучу классов для работы с аудио данными. Я лично ее не использовал, поэтому советую прочитать о ней, хотя бы, на вики.

Если вы хотите писать серьезный плагин, тут я бы уже всерьез задумался над использованием библиотек WDL-OL или JUCE. Всю рутину они сделают за вас, а у вас же остается вся мощь языка C++ для реализации эффективных алгоритмов и кроссплатформенность — что не маловажно в мире большого количества DAW.

Чем же мне не угодили WDL-OL и JUCE?

Страничка библиотеки — vstnet.codeplex.com, там есть исходники, бинарники, документация. Как я понял, библиотека находится в стадии почти доделал и забил заморозки (не реализованы некоторые редко используемые функции, пару лет нет изменений репозитория).

Библиотека состоит из трех ключевых сборок:

Работает все это следующим образом

При загрузке вашей либы необходимо, чтобы в ней был класс, реализующий интерфейс IVstPluginCommandStub:

VstPluginInfo содержит базовую о плагине — версия, уникальный ID плагина, число параметров и программ, число обрабатываемых каналов. PluginConfiguration нужна для вызывающей либы-обертки Jacobi.Vst.Interop.

В свою очередь, IVstPluginCommandStub реализует интерфейс IVstPluginCommands24, который содержит методы, вызываемые хостом: обработка массива (буфера) семплов, работа с параметрами, программами (пресетами), MIDI-сообщениями и так далее.

Jacobi.Vst.Framework содержит готовый удобный класс StdPluginCommandStub, реализующий IVstPluginCommandStub. Все что нужно сделать — отнаследоваться от StdPluginCommandStub и реализовать метод CreatePluginInstance(), который будет возвращать объект (instance) вашего класса-плагина, реализующего IVstPlugin.

Опять же, есть готовый удобный класс VstPluginWithInterfaceManagerBase:

Если смотреть исходный код библиотеки, можно увидеть интерфейсы, описывающие компоненты плагина, для работы с аудио, параметрами, MIDI и т.д. :

Класс VstPluginWithInterfaceManagerBase содержит виртуальные методы, возвращающие эти интерфейсы:

Эти методы и нужно перегружать, чтобы реализовывать свою логику в кастомных классах-компонентах. Например, вы хотите обрабатывать семплы, тогда вам нужно написать класс, реализующий IVstPluginAudioProcessor, и вернуть его в методе CreateAudioProcessor.

Используя различные готовые классы-компоненты можно сосредоточиться на программировании логики плагина. Хотя, вам никто не мешает реализовывать все самому, как хочется, основываясь только на интерфейсах из Jacobi.Vst.Core.

Для тех, кто уже кодит — предлагаю вам пример просто плагина, который понижает громкость на 6 дБ (для этого нужно умножить семпл на 0.5, почему — читай в статье про звук).

При программировании синта я столкнулся с некоторыми проблемами при использовании классов из Jacobi.Vst.Framework. Основная проблема заключалась в использовании параметров и их автоматизации.

Во первых, мне не понравилась реализация событий изменения значения; во вторых, обнаружились баги при тестировании плагина в FL Studio и Cubase. FL Studio воспринимает все параметры как float-числа от 0 до 1, даже не используя специальную функцию из VST SDK с опкодом effGetParameterProperties (функция вызывается у плагина чтобы получить дополнительную информацию о параметре). В WDL-OL реализация закомментирована с пометкой:

could implement effGetParameterProperties to group parameters, but can’t find a host that supports it

Хотя, конечно же, в Cubase эта функция вызывается (Cubase — продукт компании Steinberg, которая и выпустила VST SDK).

В начале я внес правки саму библиотеку, написал автору, чтобы он дал разрешение выложить исходники в репозиторий, либо сам создал репозиторий на GitHub’е. Но внятного ответа я так и не получил, поэтому решил сделать надстройку над либой — Syntage.Framework.dll.

Помимо этого, в надстройке реализованы удобные классы для работы с UI, если вы хотите использовать WPF.

Самое время скачать исходный код моего синтезатора и скомпилировать его.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Правила использования моей надстройки просты: вместо StdPluginCommandStub юзаем SyntagePluginCommandStub, а свой плагин наследуем от SyntagePlugin.

WPF UI

В VST плагине не обязательно должен быть графический интерфейс. Я видел много плагинов без UI (одни из них — mda). Большинство DAW (по крайней мере, Cubase и FL Studio) предоставят вам возможность управлять параметрами из сгенерированного ими UI.

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Автосгенерированный UI для моего синтезатора в FL Studio

Чтобы ваш плагин был с UI, во-первых, у вас должен быть класс, реализующий IVstPluginEditor; во-вторых, нужно вернуть его инстанс в перегруженной функции CreateEditor вашего класса плагина (наследник SyntagePlugin).

В своем синтезаторе Syntage я написал пару контролов — слайдер, крутилка (knob), клавиатура пианино — если вы хотите, можете их скопировать и использовать.

UI-поток (thread)

Я тестировал синтезатор в FL Studio и Cubase 5 и уверен, что, в других DAW будет тоже самое: UI плагина обрабатывается отдельным потоком. А это значит, что логики аудио и UI обрабатывается в независимых потоках. Это влечет все проблемы, или, последствия такого подхода: доступ к данным из разных потоков, критические данные, доступ к UI из другого потока.

Для облегчения решения проблем я написал класс UIThread, который, по сути, является очередью команд. Если вы в какой-то момент хотите что-то сообщить/поменять/сделать в UI, а текущий код работает не в UI-потоке, то вы можете поставить на выполнение в очередь необходимую функцию:

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

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

Обзор архитектуры синтезатора Syntage

При написании синтезатора активно использовалось ООП; предлагаю вам познакомиться с получившейся архитектурой и использовать мой код. Вы можете сделать все по-своему, но в этих статьях придется терпеть мое видение)

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Класс PluginCommandStub нужен только чтобы создать и вернуть объект класса PluginController. PluginController предоставляет информацию о плагине, так же создает и владеет следующими компонентами:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Чтобы обрабатывать аудиоданные есть интерфейсы IAudioChannel и IAudioStream. IAudioChannel предоставляет прямой доступ к массиву/буферу семплов (double[] Samples). IAudioStream содержит массив каналов.

Представленные интерфейсы содержат удобные методы обработки всех семплов и каналов «скопом»: микширование каналов и потоков, применение метода к каждому семплу в отдельности и так далее.

Для интерфейсов IAudioChannel и IAudioStream написаны реализации AudioChannel и AudioStream. Здесь важно запомнить следующую вещь: нельзя хранить ссылки на AudioStream и AudioChannel, если они являются внешними данными в функции. Суть в том, что размеры буферов могут меняться по ходу работы плагина, буферы постоянно переиспользуются — не выгодно постоянно перевыделять и копировать память. Если вам необходимо сохранить буфер для дальнейшего использования (уж не знаю, зачем) — копируйте его в свой буфер.

IAudioStreamProvider является владельцем аудиопотоков, можно попросить создать поток функцией CreateAudioStream и вернуть поток для его удаления функцией ReleaseAudioStream.

В каждый момент времени длина (длина массива семплов) всех аудиопотоков и каналов одинакова, технически она определяется хостом. В коде ее можно получить либо у самого IAudioChannel или IAudioStream (свойство Length), так же у «хозяина» IAudioStreamProvider (свойство CurrentStreamLenght).

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Класс AudioProcessor является «ядром» синтезатора — в нем-то и происходит синтез звука. Класс является наследником SyntageAudioProcessor, который, в свою очередь, реализует следующие интерфейсы:

Синтез звука проходит длинную цепочку обработки: создание простой волны в осцилляторах, микширование звука с разных осцилляторов, последовательная обработка в эффектах. Логика создания и обработки звука была разделена на классы-компоненты для AudioProcessor. Каждый компонент является наследником класса SyntageAudioProcessorComponentWithParameters — содержит ссылку на AudioProcessor и возможность создавать параметры.

В синтезаторе представлены следующие компоненты:

Все этапы создания звука вы можете найти в функции Routing.Process и на следующей схеме:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

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

Далее будет рассмотрено программирование логики класса Oscillator, а в следующих статьях будут рассмотрены другие классы-компоненты.

Настраиваем проект для создания плагина/инструмента

Предлагаю вам использовать следующий скрипт (его нужно прописать в Project → Properties → Build Events → Post-build event command line, выполнение скрипта поставьте на On successful build):

Отладка кода

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Пишем простой осциллятор

Я надеюсь, что вы прочитали главу «Обзор архитектуры синтезатора Syntage» — я буду объяснять все в терминах своей архитектуры.

Самый простой звук — это чистый тон (синусоидальный сигнал, синус) определенной частоты. В природе вы вряд ли сможете услышать чистый тон. В жизни же можно услышать чистые тона в какой-нибудь электронике (и то, уверенности мало). Фурье сказал, что любой звук можно представить как одновременное звучание тонов разной частоты и громкости. Окраска звука характеризуется тембром — грубо говоря, описанием соотношения тонов в этом звуке (спектром).

Мы пойдем схожим путем — будем генерировать простой сигнал, а затем воздействовать на него и менять с помощью эффектов.

Какие выбрать «простые» сигналы? Очевидно, сигналы, спектр которых известен и хорошо изучен, которые легко обрабатывать. Возьмем четыре знаменитые типа сигналов:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Периоды четырех типов сигналов: синус, треугольник, импульс/квадрат, пила.

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

Синус имеет глухое и тихое звучание, остальные же — «острое» и громкое. Это связано с тем, что, в отличие от синуса, другие сигналы содержат большое количество других тонов (гармоник) в спектре.

Наш генерируемый сигнал будет характеризоваться двумя параметрами: типом волны и частотой.
На графике изображены периоды нужных нам волн. Заметьте, что все волны представлены в интервале от 0 до 1. Это очень удобно, так как позволяет одинаково запрограммировать расчет значений. Такой подход позволяет задать произвольную форму сигнала, я даже видел синтезаторы, где можно вручную его нарисовать.

По представленным картинкам напишем вспомогательный класс WaveGenerator, с методом GetTableSample, который будет возвращать значение амплитуды сигнала в зависимости от типа волны и времени (время должно быть в пределах от 0 до 1).

Добавим так же в тип волны белый шум — он полезен в синтезе нестандартных звуков. Белый шум характеризуется тем, что спектральные составляющие равномерно распределены по всему диапазону частот. Функция NextDouble стандартного класса Random имеет равномерное распределение — таким образом, мы можем считать, что каждый сгенерированный семпл относится к некоторой гармонике. Соответственно, мы будем выбирать гармоники равномерно, получая белый шум. Нужно лишь сделать отображение результата функции из интервала [0,1] в интервал минимального и максимального значения амплитуды [-1,1].

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

Пока что у нашего осциллятора будет два параметра:

Оформим все вышесказанное:

Осталось написать функцию GenerateToneToStream.

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

Оба параметра могут меняться во время работы плагина, поэтому не советую каким-либо образом их кешировать. Каждый вызов функции Generate() на вход плагину подается буфер конечной длины (длина определяется хостом, по времени она достаточно короткая) — звук генерируется «порциями». Мы должны запоминать, сколько времени прошло с момента начала генерирования волны, чтобы звук был «непрерывным». Пока что звук будем генерировать с момента старта плагина. Синхронизировать звук с нажатием клавиши будем в следующей статье.

Семплы генерируются в цикле от 0 до [длина текущего буфера].

Частота дискретизации — число семплов в секунду. Время, которое проходит от начала одного семпла до другого равно timeDelta = 1/SampleRate. При частоте дискретизации 44100 Гц это очень маленькое время — 0.00002267573 секунды.

Теперь мы можем знать, сколько времени в секундах прошло с момента старта до текущего семпла — заведем переменную _time и будем прибавлять к ней timeDelta каждую итерацию цикла.

Чтобы воспользоваться функцией WaveGenerator.GetTableSample нужно знать относительное время от 0 до 1, где 1 — период волны. Зная нужную частоты волны, мы знаем и ее период — значение, обратное частоте.

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

Пример: мы генерируем синус со знаменитой частотой 440 Гц. Из частоты находим период синуса: 1/440 = 0.00227272727 секунды.
Частота дискретизации 44100 Гц.
Рассчитаем 44150-й семпл, если на нулевом семпле время равнялось нулю.
На 44150-м семпле прошло 44150/44100 = 1.00113378685 секунд.
Смотрим, сколько это в периодах — 1.00113378685/0.00227272727 = 440.498866743.
Отбрасываем целую часть — 0.498866743. Именно это значение и нужно передать в функцию WaveGenerator.GetTableSample.

Если записать все символьно, получим:

Vst что за формула. Смотреть фото Vst что за формула. Смотреть картинку Vst что за формула. Картинка про Vst что за формула. Фото Vst что за формула

Оформим выкладки в виде отдельной функции WaveGenerator.GenerateNextSample и запишем итоговую функцию GenerateToneToStream.

Обычно, в параметры осциллятора добавляют следующие:

Данные параметры есть в реализованном мною синтезаторе — вы можете самостоятельно их реализовать.

Осталось реализовать классы AudioProcessor (будет создавать осциллятор и вызывать у него метод Generate) и PluginController (создает AudioProcessor).
Посмотрите реализацию данных классов в моем коде Syntage. На текущем этапе AudioProcessor нужен, чтобы:

В следующей статье я расскажу как написать ADSR-огибающую.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *