Все посты серии:
Часть 1. Введение и настройка
Часть 2. Изучение кода
Часть 3. VST и AU
Часть 4. Цифровой дисторшн
Часть 5. Пресеты и GUI
Часть 6. Синтез сигналов
Часть 7. Получение MIDI сообщений
Часть 8. Виртуальная клавиатура
Часть 9. Огибающие
Часть 10. Доработка GUI
Часть 11. Фильтр
Часть 12. Низкочастотный осциллятор
Низкочастотный осциллятор (Low Frequency Oscillator, LFO) — это важная составляющая любого классического синтезатора, и мы добавим ее в свой плагин. Как понятно из названия, это просто осциллятор. Мы используем написанный нами ранее класс Oscillator
и зададим ему низкую частоту.
Начнем с Synthesis.h. Добавьте в private
:
Oscillator mLFO;
double lfoFilterModAmount;
lfoFilterModAmount
обозначает, как сильно LFO будет влиять на фильтр. Этот параметр надо инициализировать в конструкторе в Synthesis.cpp:
lfoFilterModAmount(0.1)
Почему именно 0.1
? Тут мы просто хотим показать принципиальную легкость создания LFO. Мы добавим отдельные ручки управления этому осциллятору позже, на этапе редизайна. В конец конструктора допишите:
mLFO.setMode(OSCILLATOR_MODE_TRIANGLE);
mLFO.setFrequency(6.0);
mLFO.setMuted(false);
Тут просто выбирается треугольная волна, частота 6 Гц, и снимается флаг isMuted
. Если добавлять для LFO элементы управления в интерфейс, то первые две функции должны вызываться из OnParamChange
. А флаг isMuted
зависит от того, равно ли нулю значение параметра lfoFilterModAmount
.
Так как это осциллятор, мы должны сообщать ему об изменениях частоты семплирования в Synthesis::Reset
:
mLFO.setSampleRate(GetSampleRate());
Теперь давайте установим в ProcessDoubleReplacing
некоторые значения LFO. Замените цикл for
на следующий:
for (int i = 0; i < nFrames; ++i) {
mMIDIReceiver.advance();
int velocity = mMIDIReceiver.getLastVelocity();
double lfoFilterModulation = mLFO.nextSample() * lfoFilterModAmount;
mOscillator.setFrequency(mMIDIReceiver.getLastFrequency());
mFilter.setCutoffMod((mFilterEnvelopeGenerator.nextSample() * filterEnvelopeAmount) + lfoFilterModulation);
leftOutput[i] = rightOutput[i] = mFilter.process(mOscillator.nextSample() * mEnvelopeGenerator.nextSample() * velocity / 127.0);
}
Значение lfoFilterModulation
меняется от -1
до +1
. Для аргумента функции setCutoffMod
мы складываем контролируемую огибающей частоту среза и величину lfoFilterModulation
, то есть срез теперь изменяется под воздействием двух параметров.
Вот, собственно, и все! Протестируйте — звук должен быть слегка пульсирующим, это особенно заметно, если выбрать форму волны, отличную от синуса.
Код проекта на данной стадии можно скачать отсюда.
В следующий раз займемся редизайном, чтобы плагин выглядел приятнее:
Оригинал статьи:
martin-finke.de/blog/articles/audio-plugins-014-lfo/
Автор: 1eqinfinity