Python-библиотека для синтеза и анализа цифровых фильтров: реализует три классических метода — метод инвариантной импульсной характеристики, прямой синтез по полюсам системной функции и билинейное z-преобразование с частотными предыскажениями (prewarping) — поверх NumPy, с автоматическим выбором порядка, проверкой устойчивости и диагностической визуализацией для каждого получившегося фильтра.
Методы и инструменты: метод инвариантной импульсной характеристики · прямой синтез по полюсам системной функции · билинейное z-преобразование, prewarping · разностные уравнения, структуры FIR/IIR (трансверсальная/каноническая) · анализ в z-плоскости: нули, полюса, критерий устойчивости |z|<1 · синтез фильтра Баттерворта произвольного порядка · NumPy (свёртка полиномов, np.roots) · SciPy (freqz, lfilter) · Python (dataclasses, типизация) · Matplotlib
- Три метода синтеза — модифицированный метод инвариантной импульсной характеристики (RC-цепи), прямой синтез по полюсам (резонатор), билинейное z-преобразование с prewarping (ФНЧ Баттерворта) — реализованы на NumPy, без вызовов
scipy.signal.butter/iirdesign. SciPy используется отдельно, ниже по пайплайну, только для анализа уже рассчитанных коэффициентов (freqz,lfilter). - В методических пособиях явно приведена формула передаточной функции фильтра Баттерворта только для порядка N=2 (пример «расчёт фильтра второго порядка»). В
butterworth.pyта же схема расчёта — полюса аналогового прототипа → раскрытие полинома по этим полюсам → билинейная подстановка — записана для произвольного N, а сам порядок вычисляется автоматически по частоте среза$f_0$ , контрольной частоте$f_1$ и требуемому затуханию в дБ. При N=2 обобщённая формула численно сходится к явному виду из методических указаний. - Устойчивость каждого IIR-фильтра проверяется вычислением корней знаменателя (
np.roots) и условием$|z_i|<1$ — включая цифровой резонатор, где устойчивость и так следует из метода синтеза (полюса задаются внутри единичной окружности по построению), но всё равно проходит через ту же функциюis_stable(), что и остальные фильтры. - Переход FIR → IIR — не ручное решение по каждому конкретному τ, а следствие порогового условия на затухание импульсной характеристики (5% от первого отсчёта); переключение проверено по обе стороны границы N=10 на нескольких значениях τ/T для дифференциатора и интегратора.
- Коэффициенты, полюса и результат проверки устойчивости для всех реализованных фильтров сверены с расчётом варианта 20 (МГТУ им. Н.Э. Баумана, курс «Цифровая обработка сигналов», преп. Г.В. Круглов) — совпадение с ручными вычислениями отчёта до 4–7 значащих цифр (таблица ниже).
- Происхождение и цель проекта
- Архитектура репозитория
- Теоретическая база
- Результаты и верификация
- Инженерные решения
- Быстрый старт
- Возможные улучшения
- См. также
- Литература
Репозиторий вырос из необходимости расчёта нескольких классов цифровых фильтров разными методами синтеза — ЦФ, эквивалентный дифференцирующей RC-цепи; ЦФ, эквивалентный интегрирующей RC-цепи; цифровой резонатор; ФНЧ Баттерворта, для дальнейшей проверки, при помощи макетирования, расчитанных фильтров.
Расчёт оформлен не набором одноразовых скриптов под конкретное ТЗ, а небольшой типизированной библиотекой: единые модели данных (FIRFilter/IIRFilter), единая функция проверки устойчивости, единый модуль визуализации — так, что любой новый набор входных параметров (
digital_filters/
├── digital_filters/
│ ├── fir/
│ │ ├── __init__.py
│ │ └── rc.py # differentiating_rc_fir, integrating_rc_fir
│ ├── iir/
│ │ ├── __init__.py
│ │ ├── rc.py # differentiating_rc_iir, integrating_rc_iir
│ │ ├── resonator.py # resonator_iir (прямой синтез по полюсам)
│ │ └── butterworth.py # butterworth_lowpass (билинейное преобразование, произвольный N)
│ ├── modeles.py # dataclass-модели FIRFilter / IIRFilter
│ ├── analysis.py # is_stable() — проверка полюсов по |z|<1
│ ├── plot.py # ИХ / АЧХ / карта нулей-полюсов, сводная панель
│ └── __init__.py
├── images/ # сохранённые графики по каждому фильтру
└── Test_filters_calc_and_plot.ipynb # расчёт и визуализация для всех фильтров
FIRFilter/IIRFilter — @dataclass(slots=True)-модели: коэффициенты числителя/знаменателя, метаданные синтеза (design), и вычисляемые (не хранимые) свойства zeros/poles — is_stable() всегда отражает текущие коэффициенты, а не сохранённое ранее значение.
Дифференцирующая RC-цепь — фильтр верхних частот, поэтому прямой метод инвариантной импульсной характеристики (ИХ) здесь не работает: полоса пропускания выходит выше половины частоты дискретизации, и АЧХ ЦФ искажается наложением спектров (алиасинг складывает АЧХ дифференциатора с постоянной составляющей). Используется модификация метода — через переходную характеристику (ПХ)
Коэффициенты нерекурсивного (FIR) фильтра:
Число звеньев N определяется условием
Так как
Та же схема расчёта, симметрично:
FIR:
Устойчивость гарантирована по той же причине, что и для дифференциатора.
Здесь используется не метод по прототипу, а прямой синтез: полюса системной функции задаются напрямую в нужной точке z-плоскости —
Отдельная проверка устойчивости не требуется: полюса изначально размещаются строго внутри единичной окружности при любой полосе
Аналоговый прототип задаётся не ИХ, а АЧХ, поэтому переход к ЦФ выполняется билинейным z-преобразованием, а не методом инвариантной ИХ:
Порядок фильтра по заданным
Полюса нормированного прототипа:
Частота среза «искажается» под билинейное преобразование (prewarping), чтобы аналоговая и цифровая частоты среза совпали после подстановки:
Методичка курса раскрывает передаточную функцию только для N=2. В butterworth.py та же схема — с тем же prewarping и той же билинейной подстановкой
где np.poly). При N=2 выражение численно сворачивается ровно к явной формуле из методички — этим соответствием оно и проверялось.
Коэффициенты, полюса/нули и проверка устойчивости, полученные библиотекой для (
| Фильтр | Метод | N | Реализация | Коэффициенты | Устойчив |
|---|---|---|---|---|---|
| Дифференцирующая RC (τ/T=1.28) | Модиф. инвариантная ИХ | 5 | FIR (трансверсальная) | a=[1, -0.5422, -0.2482, -0.1136, -0.0520, -0.0238] |
не требуется (FIR) |
| Интегрирующая RC (τ/T=20.5) | Модиф. инвариантная ИХ | 63→IIR | IIR (каноническая, 1 порядок) |
a=[0, 0.04761], b=[1, -0.95239]
|
|
| Цифровой резонатор (f0=1520, B=136) | Прямой синтез по полюсам | 2 (фикс.) | IIR (каноническая) | b=[1, -1.10683, 0.91810] |
полюса |
| ФНЧ Баттерворта (f0=1520, f1=3040, L=15дБ) | Билинейное преобразование + prewarping | 2 (автовыбор) | IIR (каноническая) |
a=[0.13391, 0.26783, 0.13391], b=[1, -0.73238, 0.26804]
|
полюса |
Значения коэффициентов дифференцирующего/интегрирующего FIR, b₁/b₂ резонатора и всех пяти коэффициентов Баттерворта совпадают с ручным расчётом отчёта до 4–7 значащих цифр.
Графики (импульсная характеристика · АЧХ · карта нулей-полюсов для IIR) — в digital_filters/images/:
Структурные схемы (трансверсальная/каноническая), построенные по рассчитанным коэффициентам:
За пределами варианта 20. Каждый метод дополнительно прогонялся на других наборах параметров:
- Дифференциатор/интегратор — на нескольких соотношениях τ/T по разные стороны порога N=10: τ/T=1.28→N=5 (FIR), τ/T=3.4→N=12 (IIR), τ/T=2.6→N=9 (FIR), τ/T=20.5→N=63 (IIR).
- Синтез Баттерворта — на параметрах, не совпадающих с вариантом 20 (например,
$f_0=40\text{ кГц}$ ,$F_д=400\text{ кГц}$ ,$L=22\text{ дБ}$ ), что даёт порядок N, отличный от 2, и проверяет обобщённую формулу за пределами частного случая из методички.
- Расчёт коэффициентов — на NumPy, без
scipy.signal.butter/bilinear/iirdesign. SciPy применяется ниже по пайплайну, только дляfreqz/lfilter— анализ уже готовых коэффициентов, не их расчёт. - Первая версия
differentiating_rc_firиспользовала ту же формулу масштабирования, что иintegrating_rc_fir, отличаясь только начальным коэффициентом$a_0$ . Это давало АЧХ дифференциатора с тем же спадающим профилем, что у интегратора, вместо ожидаемого роста усиления к высоким частотам (нулевой коэффициент передачи на постоянном токе — характерное свойство дифференцирующей цепи). Расхождение стало видно при сравнении графика АЧХ с этим свойством и было исправлено сменой знака в масштабирующем множителе. - В модели
a— числитель,b— знаменатель, что обратно порядку имён вscipy.signal(там числитель передаётся первым позиционным аргументом, но называетсяb). Во всех вызовахfreqz/lfilterпорядок аргументов прокомментирован явно. -
is_stable()вanalysis.py— общая точка проверки для всех фильтров: даже для резонатора, где устойчивость следует из метода синтеза, она пересчитывается по факту, а не принимается по умолчанию.
git clone <URL_репозитория>
cd digital_filters
pip install numpy scipy matplotlib
jupyter notebook Test_filters_calc_and_plot.ipynbПример использования библиотеки напрямую:
from digital_filters.fir import *
from digital_filters.iir import *
# RC fir дифференциатор
tau_T = 1.28
my_RC_filter_1 = differentiating_rc_fir(tau_T)
# ФНЧ Баттерворта, вариант 20: автоматический расчёт порядка по f0/f1/L
F_d = 10000
f_0 = 1520
f_1 = 2 * f_0
L_dB = 15
lp = butterworth_lowpass(f_0, F_d, f1 = f_1, attenuation_db = L_dB)
print(lp.a, lp.b, is_stable(lp))
plot_filter(lp, fd=10000) # ИХ + АЧХ + карта нулей-полюсов на одной панели
# Цифровой резонатор: прямой синтез по полюсам
res = resonator_iir(center_frequency=1520, bandwidth=136, sample_rate=10000)
plot_filter(res, fd=10000)- Обобщить пайплайн Баттерворта (прототип → prewarping → билинейная подстановка) на фильтры верхних частот, полосовые и режекторные — три этапа уже разделены как отдельные функции, добавление нового типа не требует переписывать билинейное преобразование.
- Добавить прототипы Чебышева/эллиптический как альтернативные
poles_prototypeв тот же пайплайн билинейного преобразования. - Формализовать текущую ручную кросс-проверку с вариантом 20 в
pytest-тесты с эталонными значениями коэффициентов. - Сравнить с
scipy.signal.butter/bilinearкак эталоном для произвольного порядка N. - Добавить в
plot.pyпанель ФЧХ/групповой задержки в дополнение к ИХ/АЧХ/нулям-полюсам.
ofdm-phy-simulation — полностью смоделированный в GNU Radio OFDM-приёмопередатчик, где decimating LPF после квадратурного смесителя (тот же класс задачи, что и ФНЧ здесь) убирает image-частоту и LO-leakage перед демодуляцией, а весь тракт TX → AWGN-канал → RX измерен по packet delivery rate на 30 уровнях шума.
Круглов Г.В. К выполнению домашнего задания и лабораторной работы по курсу «Цифровая обработка сигналов». — М.: МГТУ им. Н.Э. Баумана, 2015.
MIT — см. LICENSE.









