ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Понедельник
27 апреля
1583831 Топик полностью
framer (Вчера, 22:19, просмотров: 37) ответил mse homjak на Походу, точности Qedit не хватает. Хотя у него есть и double. Или сам алгоритм рассчёта багованный.
Относительно диверсификации инструментов . Можно попробовать так. Но мопед не мой :) 

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()