@@ -234,61 +234,84 @@ Elliptic(n::Integer, rp::Real, rs::Real) = Elliptic(Float64, n, rp, rs)
234234# returns frequency in half-cycles per sample ∈ (0, 1)
235235function normalize_freq (w:: Real , fs:: Real )
236236 w <= 0 && throw (DomainError (w, " frequencies must be positive" ))
237- f = 2 * w / fs
237+ f = 2 * w / fs
238238 f >= 1 && throw (DomainError (f, " frequencies must be less than the Nyquist frequency $(fs/ 2 ) " ))
239239 f
240240end
241-
242- struct Lowpass{T} <: FilterType
243- w:: T
241+ function normalize_complex_freq (w:: Real , fs:: Real )
242+ f = 2 * w / fs
243+ f >= 2 && throw (DomainError (f, " frequencies must be less than the sampling frequency $(fs) " ))
244+ f
244245end
245246
246247"""
247248 Lowpass(Wn::Real)
248249
249250Low pass filter with cutoff frequency `Wn`.
250251"""
251- Lowpass (w:: Real ) = Lowpass {typeof(w/1)} (w)
252-
253- struct Highpass{T} <: FilterType
252+ struct Lowpass{T<: Real } <: FilterType
254253 w:: T
254+ Lowpass {T} (w:: Real ) where {T<: Real } = new {T} (w)
255+ Lowpass (w:: Real ) = Lowpass {typeof(w / 1)} (w)
255256end
256257
257258"""
258259 Highpass(Wn::Real)
259260
260261High pass filter with cutoff frequency `Wn`.
261262"""
262- Highpass (w:: Real ) = Highpass {typeof(w/1)} (w)
263-
264- struct Bandpass{T} <: FilterType
265- w1:: T
266- w2:: T
263+ struct Highpass{T<: Real } <: FilterType
264+ w:: T
265+ Highpass {T} (w:: Real ) where {T<: Real } = new {T} (w)
266+ Highpass (w:: Real ) = Highpass {typeof(w / 1)} (w)
267267end
268268
269269"""
270270 Bandpass(Wn1::Real, Wn2::Real)
271271
272272Band pass filter with pass band frequencies (`Wn1`, `Wn2`).
273273"""
274- function Bandpass (w1:: Real , w2:: Real )
275- w1 < w2 || throw (ArgumentError (" w1 must be less than w2" ))
276- Bandpass {Base.promote_typeof(w1/1, w2/1)} (w1, w2)
274+ struct Bandpass{T<: Real } <: FilterType
275+ w1:: T
276+ w2:: T
277+ function Bandpass {T} (w1:: Real , w2:: Real ) where {T<: Real }
278+ w1 < w2 || throw (ArgumentError (" w1 must be less than w2" ))
279+ new {T} (w1, w2)
280+ end
281+ Bandpass (w1:: T , w2:: V ) where {T<: Real ,V<: Real } =
282+ Bandpass {typeof(one(promote_type(T, V)) / 1)} (w1, w2)
277283end
278284
279- struct Bandstop{T} <: FilterType
285+ """
286+ ComplexBandpass(Wn1, Wn2)
287+
288+ Complex band pass filter with pass band frequencies (`Wn1`, `Wn2`).
289+ """
290+ struct ComplexBandpass{T<: Real } <: FilterType
280291 w1:: T
281292 w2:: T
293+ function ComplexBandpass {T} (w1:: Real , w2:: Real ) where {T<: Real }
294+ w1 < w2 || throw (ArgumentError (" w1 must be less than w2" ))
295+ new {T} (w1, w2)
296+ end
297+ ComplexBandpass (w1:: T , w2:: V ) where {T,V} =
298+ ComplexBandpass {typeof(one(promote_type(T, V)) / 1)} (w1, w2)
282299end
283300
284301"""
285302 Bandstop(Wn1::Real, Wn2::Real)
286303
287304Band stop filter with stop band frequencies (`Wn1`, `Wn2`).
288305"""
289- function Bandstop (w1:: Real , w2:: Real )
290- w1 < w2 || throw (ArgumentError (" w1 must be less than w2" ))
291- Bandstop {Base.promote_typeof(w1/1, w2/1)} (w1, w2)
306+ struct Bandstop{T<: Real } <: FilterType
307+ w1:: T
308+ w2:: T
309+ function Bandstop {T} (w1:: Real , w2:: Real ) where {T<: Real }
310+ w1 < w2 || throw (ArgumentError (" w1 must be less than w2" ))
311+ new {T} (w1, w2)
312+ end
313+ Bandstop (w1:: T , w2:: V ) where {T,V} =
314+ Bandstop {typeof(one(promote_type(T, V)) / 1)} (w1, w2)
292315end
293316
294317#
@@ -472,8 +495,10 @@ function bilinear(f::ZeroPoleGain{:s,Z,P,K}, fs::Real) where {Z,P,K}
472495end
473496
474497# Pre-warp filter frequencies for digital filtering
475- prewarp (ftype:: Union{Lowpass, Highpass} , fs:: Real ) = (typeof (ftype))(prewarp (normalize_freq (ftype. w, fs)))
476- prewarp (ftype:: Union{Bandpass, Bandstop} , fs:: Real ) = (typeof (ftype))(prewarp (normalize_freq (ftype. w1, fs)), prewarp (normalize_freq (ftype. w2, fs)))
498+ prewarp (ftype:: Lowpass , fs:: Real ) = Lowpass (prewarp (normalize_freq (ftype. w, fs)))
499+ prewarp (ftype:: Highpass , fs:: Real ) = Highpass (prewarp (normalize_freq (ftype. w, fs)))
500+ prewarp (ftype:: Bandpass , fs:: Real ) = Bandpass (prewarp (normalize_freq (ftype. w1, fs)), prewarp (normalize_freq (ftype. w2, fs)))
501+ prewarp (ftype:: Bandstop , fs:: Real ) = Bandstop (prewarp (normalize_freq (ftype. w1, fs)), prewarp (normalize_freq (ftype. w2, fs)))
477502# freq in half-samples per cycle
478503prewarp (f:: Real ) = 4 * tan (pi * f/ 2 )
479504
@@ -569,19 +594,31 @@ FIRWindow(; transitionwidth::Real=throw(ArgumentError("must specify transitionwi
569594 FIRWindow (kaiser (kaiserord (transitionwidth, attenuation)... ), scale)
570595
571596# Compute coefficients for FIR prototype with specified order
572- function firprototype (n:: Integer , ftype:: Lowpass , fs:: Real )
597+ function _firprototype (n:: Integer , ftype:: Lowpass , fs:: Real , :: Type{T} ) where {T <: Number }
573598 w = normalize_freq (ftype. w, fs)
574599
575- [w* sinc (w* (k- (n+ 1 )/ 2 )) for k = 1 : n]
600+ promote_type ( typeof (w), T) [w* sinc (w* (k- (n+ 1 )/ 2 )) for k = 1 : n]
576601end
577602
603+ firprototype (n:: Integer , ftype:: Lowpass , fs:: Real ) =
604+ _firprototype (n, ftype, fs, typeof (fs))
605+
578606function firprototype (n:: Integer , ftype:: Bandpass , fs:: Real )
579607 w1 = normalize_freq (ftype. w1, fs)
580608 w2 = normalize_freq (ftype. w2, fs)
581609
582610 [w2* sinc (w2* (k- (n+ 1 )/ 2 )) - w1* sinc (w1* (k- (n+ 1 )/ 2 )) for k = 1 : n]
583611end
584612
613+ function firprototype (n:: Integer , ftype:: ComplexBandpass , fs:: T ) where {T<: Real }
614+ w1 = normalize_complex_freq (ftype. w1, fs)
615+ w2 = normalize_complex_freq (ftype. w2, fs)
616+ w_center = (w2 + w1) / 2
617+ w_cutoff = (w2 - w1) / 2
618+ lp = Lowpass (w_cutoff)
619+ _firprototype (n, lp, 2 , Complex{T}) .*= cispi .(w_center * (0 : (n- 1 )))
620+ end
621+
585622function firprototype (n:: Integer , ftype:: Highpass , fs:: Real )
586623 w = normalize_freq (ftype. w, fs)
587624 isodd (n) || throw (ArgumentError (" FIRWindow highpass filters must have an odd number of coefficients" ))
@@ -602,14 +639,14 @@ function firprototype(n::Integer, ftype::Bandstop, fs::Real)
602639end
603640
604641scalefactor (coefs:: Vector , :: Union{Lowpass, Bandstop} , fs:: Real ) = sum (coefs)
605- function scalefactor (coefs:: Vector{T} , :: Highpass , fs:: Real ) where T
642+ function scalefactor (coefs:: Vector{T} , :: Highpass , fs:: Real ) where {T <: Number }
606643 c = zero (T)
607644 for k = 1 : length (coefs)
608645 c += ifelse (isodd (k), coefs[k], - coefs[k])
609646 end
610647 c
611648end
612- function scalefactor (coefs:: Vector{T} , ftype:: Bandpass , fs:: Real ) where T
649+ function scalefactor (coefs:: Vector{T} , ftype:: Bandpass , fs:: Real ) where {T <: Number }
613650 n = length (coefs)
614651 freq = normalize_freq (middle (ftype. w1, ftype. w2), fs)
615652 c = zero (T)
@@ -618,11 +655,20 @@ function scalefactor(coefs::Vector{T}, ftype::Bandpass, fs::Real) where T
618655 end
619656 c
620657end
658+ function scalefactor (coefs:: Vector{T} , ftype:: ComplexBandpass , fs:: Real ) where T<: Number
659+ n = length (coefs)
660+ freq = normalize_complex_freq (middle (ftype. w1, ftype. w2), fs)
661+ c = zero (T)
662+ for k = 1 : n
663+ c = muladd (coefs[k], cispi (- freq * (k - (n + 1 ) / 2 )), c)
664+ end
665+ return abs (c)
666+ end
621667
622668function digitalfilter (ftype:: FilterType , proto:: FIRWindow ; fs:: Real = 2 )
623669 coefs = firprototype (length (proto. window), ftype, fs)
624670 @assert length (proto. window) == length (coefs)
625- out = coefs .* proto. window
671+ out = ( coefs .*= proto. window)
626672 proto. scale ? rmul! (out, 1 / scalefactor (out, ftype, fs)) : out
627673end
628674
0 commit comments