Если вы хотите протестировать, как будет работать тот или иной фильтр "вживую", можно использовать SuperCollider. Увы, для этого фильтр должен брать только сигналы, использующий только текущий и прошлые семплы :(
Например, возьмем простейший low-pass фильтр, имеющий ядро $\left\{ 1/2, 1/2, 0, 0, 0, \cdots \right\}$ Т.е. отфильтрованный сигнал будет равен $f'_{n} = \frac{1}{2} f_{n} + \frac{1}{2} f_{n-1}$
Формально этот фильтр можно представить в time-domain в виде функции $f(t) = \frac{1}{2}\delta (t) + \frac{1}{2} \delta (t + \frac {2 \pi}{\omega_{0}})$, где $\omega_{0}$ — частота дискретизации.
Преобразование Фурье равно $F(\xi) = \frac{1}{2} + \frac{1}{2} e^{-\frac {2 \pi}{\omega_{0}} i\xi}$
Модуль этой функции — АЧХ нашего фильтра $\left| F(\omega) \right| = \sqrt{F^{*}F} = \sqrt {1/2 (1 + cos (\frac{2 \pi}{\omega_{0}} \omega}))$
Для $\omega = 0$ получаем $\left| F \right| = 1$ и для $\omega = \omega_{0}/2$ получаем $\left| F \right| = 0$ — как я и говорил, low-pass фильтр.
Теперь мы как будто не верим полученному результату и хотим его протестировать на Supercollider. Для этого есть UGen Convolution2. Смотрим код:
В итоге через freqscope видим картину:
Верхние частоты идут на спад, как и ожидалось
Например, возьмем простейший low-pass фильтр, имеющий ядро $\left\{ 1/2, 1/2, 0, 0, 0, \cdots \right\}$ Т.е. отфильтрованный сигнал будет равен $f'_{n} = \frac{1}{2} f_{n} + \frac{1}{2} f_{n-1}$
Формально этот фильтр можно представить в time-domain в виде функции $f(t) = \frac{1}{2}\delta (t) + \frac{1}{2} \delta (t + \frac {2 \pi}{\omega_{0}})$, где $\omega_{0}$ — частота дискретизации.
Преобразование Фурье равно $F(\xi) = \frac{1}{2} + \frac{1}{2} e^{-\frac {2 \pi}{\omega_{0}} i\xi}$
Модуль этой функции — АЧХ нашего фильтра $\left| F(\omega) \right| = \sqrt{F^{*}F} = \sqrt {1/2 (1 + cos (\frac{2 \pi}{\omega_{0}} \omega}))$
Для $\omega = 0$ получаем $\left| F \right| = 1$ и для $\omega = \omega_{0}/2$ получаем $\left| F \right| = 0$ — как я и говорил, low-pass фильтр.
АЧХ фильтра. По горизонтальной оси — частота в единицах $\omega_{0}$ |
Теперь мы как будто не верим полученному результату и хотим его протестировать на Supercollider. Для этого есть UGen Convolution2. Смотрим код:
// Аллоцируем буфер на сервере
b = Buffer.alloc (s, 2)
a = [0.5, 0.5]
// Копируем туда коэффициенты фильтра
b.setn (0, a)
// Шлем SynthDef на сервер, сворачивающий вход на шине 0 с ядром kernel
SynthDef (\flt, {|kernel| ReplaceOut.ar (0, Convolution2.ar (In.ar (0), kernel))}).send (s)
// Играем белый шум
{WhiteNoise.ar}.play
// И фильтруем его
f = Synth (\flt, [\kernel, b], addAction: \addToTail)
В итоге через freqscope видим картину:
Верхние частоты идут на спад, как и ожидалось
Comments
Post a Comment