Я пытаюсь реализовать высокочастотную версию Ladder-фильтра в стиле Moog в аудиопроцессоре VST, который я разрабатываю с использованием инфраструктуры JUCE. Я основываю алгоритм на фильтре LP Ladder, который можно найти здесь:
http://www.musicdsp.org/en/latest/Filters/24-moog-vcf.html
Чтобы сделать его фильтром HP, я вычитаю выходной сигнал конечного фильтра ("outL4b") из входного, прежде чем применить его к окончательному выходному. Было указано, что он работает в нескольких местах (я не могу вспомнить, где я нашел информацию), но не создает «истинного» высокочастотного сигнала, так как сильно ослабленная версия «сухого» сигнала остается, даже когда значение отсечки фильтра составляет максимум (40 - 22050 Гц). Значение Q может составлять от 0,0 до 4,0. Все переменные устанавливаются в ноль при первоначальном создании плагина, а частота дискретизации в моей DAW установлена на 44100 Гц.
При использовании в качестве фактического LP-фильтра алгоритм работает должным образом.
Я также попытался вычесть все выходы фильтра из всех входов, что не сработало. На данный момент я в растерянности. Функция показана ниже.
void FilterSection::moogHighPass(AudioBuffer<float>& buffer, int
inputChannels, float cutoff, float q, float sampleRate)
{
float fs = sampleRate;
float fs2 = 2 * fs;
float fc = (2.0f * cutoff) / fs;
float p = fc * (1.8f - 0.8f * fc);
float k = 2.0f * sin(fc * pi * 0.5f) - 1.0f;
float t1 = (1.0f - p) * 1.386249f;
float t2 = 12.0f + t1 * t1;
float res = ((q / 4.0f) * (t2 + 6.0f * t1) / (t2 - 6.0f * t1));
const float* inputChannelDataL = buffer.getReadPointer(0);
const float* inputChannelDataR = buffer.getReadPointer(1);
float* outputChannelDataL = {};
outputChannelDataL = buffer.getWritePointer(0);
float* outputChannelDataR = {};
outputChannelDataR = buffer.getWritePointer(1);
for (int i = 0; i < buffer.getNumSamples(); i++)
{
inputLMoogb = inputChannelDataL[i];
inputRMoogb = inputChannelDataR[i];
inputLMoogb -= res * out4Lb;
inputRMoogb -= res * out4Rb;
//inputLMoogb = tanh(inputLMoogb);
//inputRMoogb = tanh(inputRMoogb);
out1Lb = (p * inputLMoogb) + (p * in1Lb) - k * out1Lb; // Pole 1
out1Rb = (p * inputRMoogb) + (p * in1Rb) - k * out1Rb;
out2Lb = (p * out1Lb) + (p * in2Lb) - k * out2Lb; // Pole 2
out2Rb = (p * out1Rb) + (p * in2Rb) - k * out2Rb;
out3Lb = (p * out2Lb) + (p * in3Lb) - k * out3Lb; // Pole 3
out3Rb = (p * out2Rb) + (p * in3Rb) - k * out3Rb;
out4Lb = (p * out3Lb) + (p * in4Lb) - k * out4Lb; // Pole 4, (1 - (g / 2))
out4Rb = (p * out3Rb) + (p * in4Rb) - k * out4Rb;
out4Lb = out4Lb - (out4Lb * out4Lb * out4Lb) * 0.166667f;
out4Rb = out4Rb - (out4Rb * out4Rb * out4Rb) * 0.166667f;
in1Lb = inputLMoogb;
in1Rb = inputRMoogb;
in2Lb = out1Lb;
in2Rb = out1Rb;
in3Lb = out2Lb;
in3Rb = out2Rb;
in4Lb = out3Lb;
in4Rb = out3Rb;
outputChannelDataL[i] = (inputLMoogb - out4Lb) / 2; //(out4L / 2) ???
outputChannelDataR[i] = (inputRMoogb - out4Rb) / 2;
//outputChannelDataL[i] = inputLMoogb + in2Lb + in3Lb + in4Lb - out1Lb - out2Lb - out3Lb - out4Lb; //(out4L / 2) ???
//outputChannelDataR[i] = inputRMoogb + in2Rb + in3Rb + in4Rb - out1Rb - out2Rb - out3Rb - out4Rb;
}
}
Я не получаю никаких ошибок, и общий результат, похоже, включает высокочастотный компонент, но ослабленная версия ввода остается. Любая помощь в решении этой проблемы будет принята с благодарностью.