3 * Copyright (c) 2008 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * different IIR filters implementation
27 #include "iirfilter.h"
29 #include "libavutil/common.h"
32 * IIR filter global parameters
34 typedef struct FFIIRFilterCoeffs
{
44 typedef struct FFIIRFilterState
{
48 /// maximum supported filter order
51 static int butterworth_init_coeffs(void *avc
, struct FFIIRFilterCoeffs
*c
,
52 enum IIRFilterMode filt_mode
,
53 int order
, float cutoff_ratio
,
58 double p
[MAXORDER
+ 1][2];
60 if (filt_mode
!= FF_FILTER_MODE_LOWPASS
) {
61 av_log(avc
, AV_LOG_ERROR
, "Butterworth filter currently only supports "
62 "low-pass filter mode\n");
66 av_log(avc
, AV_LOG_ERROR
, "Butterworth filter currently only supports "
67 "even filter orders\n");
71 wa
= 2 * tan(M_PI
* 0.5 * cutoff_ratio
);
74 for(i
= 1; i
< (order
>> 1) + 1; i
++)
75 c
->cx
[i
] = c
->cx
[i
- 1] * (order
- i
+ 1LL) / i
;
79 for(i
= 1; i
<= order
; i
++)
80 p
[i
][0] = p
[i
][1] = 0.0;
81 for(i
= 0; i
< order
; i
++){
83 double th
= (i
+ (order
>> 1) + 0.5) * M_PI
/ order
;
84 double a_re
, a_im
, c_re
, c_im
;
91 zp
[0] = (a_re
* c_re
+ a_im
* c_im
) / (c_re
* c_re
+ c_im
* c_im
);
92 zp
[1] = (a_im
* c_re
- a_re
* c_im
) / (c_re
* c_re
+ c_im
* c_im
);
94 for(j
= order
; j
>= 1; j
--)
98 p
[j
][0] = a_re
*zp
[0] - a_im
*zp
[1] + p
[j
-1][0];
99 p
[j
][1] = a_re
*zp
[1] + a_im
*zp
[0] + p
[j
-1][1];
101 a_re
= p
[0][0]*zp
[0] - p
[0][1]*zp
[1];
102 p
[0][1] = p
[0][0]*zp
[1] + p
[0][1]*zp
[0];
105 c
->gain
= p
[order
][0];
106 for(i
= 0; i
< order
; i
++){
108 c
->cy
[i
] = (-p
[i
][0] * p
[order
][0] + -p
[i
][1] * p
[order
][1]) /
109 (p
[order
][0] * p
[order
][0] + p
[order
][1] * p
[order
][1]);
111 c
->gain
/= 1 << order
;
116 static int biquad_init_coeffs(void *avc
, struct FFIIRFilterCoeffs
*c
,
117 enum IIRFilterMode filt_mode
, int order
,
118 float cutoff_ratio
, float stopband
)
120 double cos_w0
, sin_w0
;
123 if (filt_mode
!= FF_FILTER_MODE_HIGHPASS
&&
124 filt_mode
!= FF_FILTER_MODE_LOWPASS
) {
125 av_log(avc
, AV_LOG_ERROR
, "Biquad filter currently only supports "
126 "high-pass and low-pass filter modes\n");
130 av_log(avc
, AV_LOG_ERROR
, "Biquad filter must have order of 2\n");
134 cos_w0
= cos(M_PI
* cutoff_ratio
);
135 sin_w0
= sin(M_PI
* cutoff_ratio
);
137 a0
= 1.0 + (sin_w0
/ 2.0);
139 if (filt_mode
== FF_FILTER_MODE_HIGHPASS
) {
140 c
->gain
= ((1.0 + cos_w0
) / 2.0) / a0
;
141 x0
= ((1.0 + cos_w0
) / 2.0) / a0
;
142 x1
= (-(1.0 + cos_w0
)) / a0
;
143 } else { // FF_FILTER_MODE_LOWPASS
144 c
->gain
= ((1.0 - cos_w0
) / 2.0) / a0
;
145 x0
= ((1.0 - cos_w0
) / 2.0) / a0
;
146 x1
= (1.0 - cos_w0
) / a0
;
148 c
->cy
[0] = (-1.0 + (sin_w0
/ 2.0)) / a0
;
149 c
->cy
[1] = (2.0 * cos_w0
) / a0
;
151 // divide by gain to make the x coeffs integers.
152 // during filtering, the delay state will include the gain multiplication
153 c
->cx
[0] = lrintf(x0
/ c
->gain
);
154 c
->cx
[1] = lrintf(x1
/ c
->gain
);
159 av_cold
struct FFIIRFilterCoeffs
* ff_iir_filter_init_coeffs(void *avc
,
160 enum IIRFilterType filt_type
,
161 enum IIRFilterMode filt_mode
,
162 int order
, float cutoff_ratio
,
163 float stopband
, float ripple
)
165 FFIIRFilterCoeffs
*c
;
168 if (order
<= 0 || order
> MAXORDER
|| cutoff_ratio
>= 1.0)
171 FF_ALLOCZ_OR_GOTO(avc
, c
, sizeof(FFIIRFilterCoeffs
),
173 FF_ALLOC_OR_GOTO (avc
, c
->cx
, sizeof(c
->cx
[0]) * ((order
>> 1) + 1),
175 FF_ALLOC_OR_GOTO (avc
, c
->cy
, sizeof(c
->cy
[0]) * order
,
180 case FF_FILTER_TYPE_BUTTERWORTH
:
181 ret
= butterworth_init_coeffs(avc
, c
, filt_mode
, order
, cutoff_ratio
,
184 case FF_FILTER_TYPE_BIQUAD
:
185 ret
= biquad_init_coeffs(avc
, c
, filt_mode
, order
, cutoff_ratio
,
189 av_log(avc
, AV_LOG_ERROR
, "filter type is not currently implemented\n");
197 ff_iir_filter_free_coeffs(c
);
201 av_cold
struct FFIIRFilterState
* ff_iir_filter_init_state(int order
)
203 FFIIRFilterState
* s
= av_mallocz(sizeof(FFIIRFilterState
) + sizeof(s
->x
[0]) * (order
- 1));
207 #define CONV_S16(dest, source) dest = av_clip_int16(lrintf(source));
209 #define CONV_FLT(dest, source) dest = source;
211 #define FILTER_BW_O4_1(i0, i1, i2, i3, fmt) \
212 in = *src0 * c->gain \
213 + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1] \
214 + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3]; \
215 res = (s->x[i0] + in )*1 \
216 + (s->x[i1] + s->x[i3])*4 \
218 CONV_##fmt(*dst0, res) \
223 #define FILTER_BW_O4(type, fmt) { \
225 const type *src0 = src; \
227 for (i = 0; i < size; i += 4) { \
229 FILTER_BW_O4_1(0, 1, 2, 3, fmt); \
230 FILTER_BW_O4_1(1, 2, 3, 0, fmt); \
231 FILTER_BW_O4_1(2, 3, 0, 1, fmt); \
232 FILTER_BW_O4_1(3, 0, 1, 2, fmt); \
236 #define FILTER_DIRECT_FORM_II(type, fmt) { \
238 const type *src0 = src; \
240 for (i = 0; i < size; i++) { \
243 in = *src0 * c->gain; \
244 for(j = 0; j < c->order; j++) \
245 in += c->cy[j] * s->x[j]; \
246 res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1]; \
247 for(j = 1; j < c->order >> 1; j++) \
248 res += (s->x[j] + s->x[c->order - j]) * c->cx[j]; \
249 for(j = 0; j < c->order - 1; j++) \
250 s->x[j] = s->x[j + 1]; \
251 CONV_##fmt(*dst0, res) \
252 s->x[c->order - 1] = in; \
258 #define FILTER_O2(type, fmt) { \
260 const type *src0 = src; \
262 for (i = 0; i < size; i++) { \
263 float in = *src0 * c->gain + \
264 s->x[0] * c->cy[0] + \
265 s->x[1] * c->cy[1]; \
266 CONV_##fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1]) \
274 void ff_iir_filter(const struct FFIIRFilterCoeffs
*c
,
275 struct FFIIRFilterState
*s
, int size
,
276 const int16_t *src
, int sstep
, int16_t *dst
, int dstep
)
279 FILTER_O2(int16_t, S16
)
280 } else if (c
->order
== 4) {
281 FILTER_BW_O4(int16_t, S16
)
283 FILTER_DIRECT_FORM_II(int16_t, S16
)
287 void ff_iir_filter_flt(const struct FFIIRFilterCoeffs
*c
,
288 struct FFIIRFilterState
*s
, int size
,
289 const float *src
, int sstep
, float *dst
, int dstep
)
292 FILTER_O2(float, FLT
)
293 } else if (c
->order
== 4) {
294 FILTER_BW_O4(float, FLT
)
296 FILTER_DIRECT_FORM_II(float, FLT
)
300 av_cold
void ff_iir_filter_free_state(struct FFIIRFilterState
*state
)
305 av_cold
void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs
*coeffs
)
321 struct FFIIRFilterCoeffs
*fcoeffs
= NULL
;
322 struct FFIIRFilterState
*fstate
= NULL
;
323 float cutoff_coeff
= 0.4;
324 int16_t x
[SIZE
], y
[SIZE
];
327 fcoeffs
= ff_iir_filter_init_coeffs(NULL
, FF_FILTER_TYPE_BUTTERWORTH
,
328 FF_FILTER_MODE_LOWPASS
, FILT_ORDER
,
329 cutoff_coeff
, 0.0, 0.0);
330 fstate
= ff_iir_filter_init_state(FILT_ORDER
);
332 for (i
= 0; i
< SIZE
; i
++) {
333 x
[i
] = lrint(0.75 * INT16_MAX
* sin(0.5*M_PI
*i
*i
/SIZE
));
336 ff_iir_filter(fcoeffs
, fstate
, SIZE
, x
, 1, y
, 1);
338 for (i
= 0; i
< SIZE
; i
++)
339 printf("%6d %6d\n", x
[i
], y
[i
]);
341 ff_iir_filter_free_coeffs(fcoeffs
);
342 ff_iir_filter_free_state(fstate
);