DSP - фильтрация частот с использованием DFT - PullRequest
4 голосов
/ 20 мая 2010

Я пытаюсь реализовать 8-полосный эквалайзер на основе DFT с единственной целью обучения. Чтобы доказать, что моя реализация DFT работает, я подал аудиосигнал, проанализировал его, а затем снова синтезировал без изменений, внесенных в частотный спектр. Пока все хорошо.

Я использую так называемый «стандартный способ вычисления ДПФ», который основан на корреляции. Этот метод вычисляет действительную и мнимую части как N / 2 + 1 выборок в длину. Чтобы ослабить частоту, я просто делаю:

float atnFactor = 0.6;
Re[k] *= atnFactor;
Im[k] *= atnFactor;

где 'k' - это индекс в диапазоне от 0 до N / 2, но то, что я получаю после ресинтеза, - это слегка искаженный сигнал, особенно на низких частотах.

Частота дискретизации входного сигнала составляет 44,1 кГц, и, поскольку я просто хочу 8-полосный эквалайзер, я подаю по 16 выборок DFT одновременно, поэтому у меня есть 8 частотных бинов для воспроизведения.

Может кто-нибудь показать мне, что я делаю не так? Я пытался найти информацию по этому вопросу в интернете, но не смог ее найти.

Заранее спасибо.

1 Ответ

5 голосов
/ 20 мая 2010

DFT и FFT по существу одинаковы для целей этого вопроса.

Чтобы ослабить частотный интервал (или «полосу») в массиве с БПФ-преобразованием, вам необходимо умножить как действительные, так и мнимые компоненты на один и тот же коэффициент, а также умножить действительные и мнимые компоненты соответствующих отрицательная частота бин. БПФ создает преобразованную пару массивов, где первая половина значений представляет положительные частотные компоненты, а вторая половина представляет отрицательные частотные компоненты.

Вот упрощенный пример кода для фильтра нижних частот, который объясняет, что я имею в виду:

// fftsize = size of fft window
int halfFFTsize = fftsize / 2;
float lowpassFreq1 = 1000.0;
float lowpassFreq2 = 2000.0;
for (int i = 0; i < halfFFTsize; i++)
{
    int ineg = fftsize - 1 - i; // index of neg. freq.
    float freq = (float)i * (44100.0F / (float)halfFFTsize);
    if (freq >= lowpassFreq2)
    {
        real[i] = 0;
        imag[i] = 0;
        real[ineg] = 0;
        imag[ineg] = 0;
    }
    else if (freq >= lowpassFreq1)
    {
        float mult = 1.0 - ((freq - lowpassFreq1) / 
            (lowpassFreq2 - lowpassFreq1));
        real[i] *= mult;
        imag[i] *= mult;
        real[ineg] *= mult;
        imag[ineg] *= mult;
    }

}

Обновление: после прочтения вашей правки, я должен сказать, что ваш код работает как положено. Я предположил, что вы получаете сильно искаженный искаженный повторно синтезированный сигнал, а не "слабо искаженный сигнал, особенно на низких частотах".

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

Попробуйте запустить код с более типичным размером окна (например, 1024). 8-полосный эквалайзер обычно не использует 8-разрядное окно FFT. Как правило, настройки 8 ползунков используются для вычисления изогнутой функции, соединяющей 8 точек в частотной области, и эта функция затем используется для установки амплитуд бина для гораздо большего, более мелкозернистого набора частот.

Еще один момент: частотные бины равномерно распределяют доступный диапазон, поэтому независимо от размера окна, более половины бинов покрывают частоты, которые не слышны человеческому уху. Вот почему полосы , охватываемые эквалайзером, обычно масштабируются логарифмически (например, 100 Гц, 1 кГц и 10 кГц для типичного 3-полосного эквалайзера) и, следовательно, не применяются к равному количеству частот бинов .

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

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