Description
Hello,
Following discussion started at https://discourse.julialang.org/t/scipy-signal-iirfilter-equivalent-in-dsp-jl-and-more/110783/4 I wonder if DSP.jl provides structure of digital filter which can be used for streaming input data ie processing live data and not a vector of precalculated values ?
ie is there some kind of filter which preserve its state each time a new input is coming.
I did this Pluto.jl notebook https://gist.github.com/scls19fr/0ae16d92ca39d3eb9c42cc0fc618c723 for experimenting this kind of problem (both for filtering a vector of input signal and for displaying streamed signal and output of filter thanks to PlutoUI Clock).
I end up to convert idea mentioned https://www.samproell.io/posts/yarppg/yarppg-live-digital-filter/ with Julia.
OnlineStatsBase.jl API looks interesting for this kind of work (this is API which is used by OnlineStats.jl
So I did
abstract type AbstractLiveFilter{T} <: OnlineStat{T} end
mutable struct LiveDigitalFilter{T} <: AbstractLiveFilter{T}
value::T
n::Int
b::Vector
a::Vector
_xs::CircularBuffer
_ys::CircularBuffer
function LiveDigitalFilter{T}(pr::PolynomialRatio) where {T}
b = reverse(pr.b.coeffs)
a = reverse(pr.a.coeffs)
_xs = CircularBuffer{T}(length(b))
fill!(_xs, zero(T))
_ys = CircularBuffer{T}(length(a) - 1)
fill!(_ys, zero(T))
new{T}(0, 0, b, a, _xs, _ys)
end
end
function reset!(f::LiveDigitalFilter)
f.n = 0
empty!(f._xs)
empty!(f._ys)
fill!(f._xs, zero(eltype(f.b)))
fill!(f._ys, zero(eltype(f.a)))
end
function OnlineStatsBase._fit!(f::LiveDigitalFilter, x)
f.n += 1
pushfirst!(f._xs, x)
y = sum(f.b .* f._xs) - sum(f.a[2:end] .* f._ys)
y = y / f.a[1]
pushfirst!(f._ys, y)
f.value = y
end
Notebook run on my side at around 10fps.
Any opinion?