@@ -268,41 +268,23 @@ function filtfilt(b::AbstractVector, a::AbstractVector, x::AbstractArray)
268268 end
269269end
270270
271- # Extract si for a biquad, multiplied by a scaling factor
272- function biquad_si! (zitmp, zi, i, scal)
273- zitmp[1 ] = zi[1 , i]* scal
274- zitmp[2 ] = zi[2 , i]* scal
275- zitmp
276- end
277-
278271# Zero phase digital filtering for second order sections
279272function filtfilt {T,G,S} (f:: SecondOrderSections{T,G} , x:: AbstractArray{S} )
280273 zi = filt_stepstate (f)
281- zi2 = zeros (2 )
282- zitmp = zeros (2 )
283- pad_length = 3 * size (zi, 1 )
274+ zitmp = similar (zi)
275+ pad_length = 6 * length (f. biquads)
284276 t = Base. promote_type (T, G, S)
285277 extrapolated = Array (t, size (x, 1 )+ pad_length* 2 )
286278 out = similar (x, t)
287279
288280 istart = 1
289- for i = 1 : size (x, 2 )
290- # First biquad
281+ for i = 1 : Base. trailingsize (x, 2 )
291282 extrapolate_signal! (extrapolated, 1 , x, istart, size (x, 1 ), pad_length)
292- f2 = f. biquads[1 ]* f. g
293- reverse! (filt! (extrapolated, f2, extrapolated, biquad_si! (zitmp, zi, 1 , extrapolated[1 ])))
294- reverse! (filt! (extrapolated, f2, extrapolated, biquad_si! (zitmp, zi, 1 , extrapolated[1 ])))
295-
296- # Subsequent biquads
297- for j = 2 : length (f. biquads)
298- f2 = f. biquads[j]
299- extrapolate_signal! (extrapolated, 1 , extrapolated, pad_length+ 1 , size (x, 1 ), pad_length)
300- reverse! (filt! (extrapolated, f2, extrapolated, biquad_si! (zitmp, zi, j, extrapolated[1 ])))
301- reverse! (filt! (extrapolated, f2, extrapolated, biquad_si! (zitmp, zi, j, extrapolated[1 ])))
283+ reverse! (filt! (extrapolated, f, extrapolated, scale! (zitmp, zi, extrapolated[1 ])))
284+ filt! (extrapolated, f, extrapolated, scale! (zitmp, zi, extrapolated[1 ]))
285+ for j = 1 : size (x, 1 )
286+ @inbounds out[j, i] = extrapolated[end - pad_length+ 1 - j]
302287 end
303-
304- # Copy to output
305- copy! (out, istart, extrapolated, pad_length+ 1 , size (x, 1 ))
306288 istart += size (x, 1 )
307289 end
308290
@@ -345,16 +327,22 @@ function filt_stepstate{T<:Number}(b::Union(AbstractVector{T}, T), a::Union(Abst
345327function filt_stepstate {T} (f:: SecondOrderSections{T} )
346328 biquads = f. biquads
347329 si = Array (T, 2 , length (biquads))
330+ y = one (T)
348331 for i = 1 : length (biquads)
349332 biquad = biquads[i]
350- A = [one (T)+ biquad. a1 - one (T)
351- + biquad. a2 one (T)]
352- B = [biquad. b1 - biquad. a1* biquad. b0,
353- biquad. b2 - biquad. a2* biquad. b0]
354- si[:, i] = A \ B
333+
334+ # At steady state, we have:
335+ # y = s1 + b0*x
336+ # s1 = s2 + b1*x - a1*y
337+ # s2 = b2*x - a2*y
338+ # where x is the input and y is the output. Solving these
339+ # equations yields the following.
340+ si[1 , i] = (- (biquad. a1 + biquad. a2)* biquad. b0 + biquad. b1 + biquad. b2)/
341+ (1 + biquad. a1 + biquad. a2)* y
342+ si[2 , i] = (biquad. a1* biquad. b2 - biquad. a2* (biquad. b0 + biquad. b1) + biquad. b2)/
343+ (1 + biquad. a1 + biquad. a2)* y
344+ y *= (biquad. b0 + biquad. b1 + biquad. b2)/ (1 + biquad. a1 + biquad. a2)
355345 end
356- si[1 , 1 ] *= f. g
357- si[2 , 1 ] *= f. g
358346 si
359347end
360348
0 commit comments