1. Генерация коэффициентов в Python
Проще всего использовать библиотеку SciPy (модуль signal).
Пример: полосовой фильтр (BPF)
Исходные данные:
частота дискретизации: fs = 1000 Hz
полоса: f1 = 100 Hz, f2 = 200 Hz
порядок фильтра: N = 4
import numpy as np
from scipy import signal
fs = 1000.0
f1 = 100.0
f2 = 200.0
N = 4
# Проектирование фильтра Баттерворта
b, a = signal.butter(N, [f1, f2], btype='bandpass', fs=fs)
print("b =", b)
print("a =", a) Ты получишь:
b[] – числитель
a[] – знаменатель (обычно a[0] = 1)
2. (Опционально) более стабильная форма: SOS
Для фильтров более высокого порядка лучше использовать SOS (second-order sections):
sos = signal.butter(N, [f1, f2], btype='bandpass', fs=fs, output='sos')
print(sos)
Это даёт набор би-квад секций — значительно стабильнее численно (важно для embedded).
3. Перенос коэффициентов в C
Вариант A: классическая форма (Direct Form I/II)
Python:
b = [b0, b1, b2, ...]
a = [1, a1, a2, ...]
C:
#define N 5 // длина коэффициентов
float b[N] = { ... };
float a[N] = { ... };
float x[N] = {0}; // входы
float y[N] = {0}; // выходы
float filter(float input) {
// сдвиг выборок
for(int i = N-1; i > 0; i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}
x[0] = input;
float output = 0.0;
// числитель
for(int i = 0; i < N; i++) {
output += b[i] * x[i];
}
// знаменатель (без a[0])
for(int i = 1; i < N; i++) {
output -= a[i] * y[i];
}
y[0] = output;
return output;
} Вариант B (рекомендуется): би-квад (SOS)
Каждая секция:
[b0 b1 b2 a0 a1 a2]
C:
typedef struct {
float b0, b1, b2;
float a1, a2;
float z1, z2;
} Biquad;
float process_biquad(Biquad *s, float x) {
float y = s->b0 * x + s->z1;
s->z1 = s->b1 * x - s->a1 * y + s->z2;
s->z2 = s->b2 * x - s->a2 * y;
return y;
} И применяешь последовательно для каждой секции.
4. Важные замечания
Нормализация: убедись, что a[0] = 1
Стабильность: для больших порядков → использовать SOS
Точность:
float обычно достаточно
для аудио/DSP лучше double
Масштабирование сигнала: избегай переполнения
Тестирование: проверь фильтр в Python (signal.freqz) перед переносом в C
5. Проверка в Python (рекомендуется)
w, h = signal.freqz(b, a, fs=fs)
import matplotlib.pyplot as plt
plt.plot(w, 20*np.log10(abs(h)))
plt.title("Характеристика фильтра")
plt.xlabel("Hz")
plt.ylabel("dB")
plt.grid()
plt.show()
-
- Спасибо, попробую. - mse homjak(Вчера, 22:25)