Учитывая уравнение временной области рецидива (например, тот, который вы цитата из Википедии), соответствующая передаточная функция в Z-домен может относительно легко быть получены с помощью следующих свойств:
Где X(z)
и Y(z)
являются z-преобразованиями входной последовательности во временной области x
и выходной последовательностью y
соответственно. Переход в другую сторону вокруг, дали передаточную функцию, которая может быть выражена как отношение многочленов от г, таких как:
рекуррентное уравнение передаточной функции может быть записана в виде:
есть, конечно, много различных способов реализации такого рекуррентного уравнения, но простая реализация фильтра после Direct Form II бы по линии:
// Implementation of an Infinite Impulse Response (IIR) filter
// with recurrence equation:
// y[n] = -\sum_{i=1}^M a_i y[n-i] + \sum_{i=0}^N b_i x[n-i]
public class IIRFilter {
public IIRFilter(float a_[], float b_[]) {
// initialize memory elements
int N = Math.max(a_.length, b_.length);
memory = new float[N-1];
for (int i = 0; i < memory.length; i++) {
memory[i] = 0.0f;
}
// copy filter coefficients
a = new float[N];
int i = 0;
for (; i < a_.length; i++) {
a[i] = a_[i];
}
for (; i < N; i++) {
a[i] = 0.0f;
}
b = new float[N];
i = 0;
for (; i < b_.length; i++) {
b[i] = b_[i];
}
for (; i < N; i++) {
b[i] = 0.0f;
}
}
// Filter samples from input buffer, and store result in output buffer.
// Implementation based on Direct Form II.
// Works similar to matlab's "output = filter(b,a,input)" command
public void process(float input[], float output[]) {
for (int i = 0; i < input.length; i++) {
float in = input[i];
float out = 0.0f;
for (int j = memory.length-1; j >= 0; j--) {
in -= a[j+1] * memory[j];
out += b[j+1] * memory[j];
}
out += b[0] * in;
output[i] = out;
// shift memory
for (int j = memory.length-1; j > 0; j--) {
memory[j] = memory[j - 1];
}
memory[0] = in;
}
}
private float[] a;
private float[] b;
private float[] memory;
}
, которые вы могли бы использовать для реализации вашей конкретной передаточной функции следующим образом:
float g = 1.0f/32.0f; // overall filter gain
float[] a = {1, -2, 1};
float[] b = {g, 0, 0, 0, 0, 0, -2*g, 0, 0, 0, 0, 0, g};
IIRFilter filter = new IIRFilter(a, b);
filter.process(input, output);
Обратите внимание, что вы в качестве альтернативы можно также разложить на множители числитель и знаменатель в 2 й полиномов порядка и получить каскад 2 0d Фильтры для заказов (известные как biquad filters).
спасибо :), но в цикле для (int j = memory.length-1; j> = 0; j--) Я вижу ошибку. cuz если память.length = N и индексы вкладки [0 ... N-1] , то, если u вызывать вкладку, как вкладка [N-1 + 1], то это вызовет ошибку –
Да, я забыл включить настройку на 'memory' будет иметь длину' N-1'. Благодарю. – SleuthEye