1
+ using .. DSP: _zeropad
2
+
1
3
const PFB{T} = Matrix{T} # polyphase filter bank
2
4
3
5
abstract type FIRKernel{T} end
@@ -132,11 +134,11 @@ end
132
134
FIRArbitrary (h:: Vector , rate:: Real , Nϕ:: Integer ) = FIRArbitrary (h, convert (Float64, rate), convert (Int, Nϕ))
133
135
134
136
# FIRFilter - the kernel does the heavy lifting
135
- mutable struct FIRFilter{Tk<: FIRKernel }
136
- kernel:: Tk
137
+ mutable struct FIRFilter{Tk<: FIRKernel ,T}
138
+ const kernel:: Tk
139
+ const h:: Vector{T}
140
+ const historyLen:: Int
137
141
history:: Vector
138
- historyLen:: Int
139
- h:: Vector
140
142
end
141
143
142
144
# Constructor for single-rate, decimating, interpolating, and rational resampling filters
@@ -172,7 +174,7 @@ function FIRFilter(h::Vector, resampleRatio::Union{Integer,Rational} = 1)
172
174
173
175
history = zeros (historyLen)
174
176
175
- FIRFilter (kernel, history , historyLen, h )
177
+ FIRFilter (kernel, h , historyLen, history )
176
178
end
177
179
178
180
# Constructor for arbitrary resampling filter (polyphase interpolator w/ intra-phase linear interpolation)
@@ -193,7 +195,7 @@ function FIRFilter(h::Vector, rate::AbstractFloat, Nϕ::Integer=32)
193
195
kernel = FIRArbitrary (h, rate, Nϕ)
194
196
historyLen = kernel. tapsPerϕ - 1
195
197
history = zeros (historyLen)
196
- FIRFilter (kernel, history , historyLen, h )
198
+ FIRFilter (kernel, h , historyLen, history )
197
199
end
198
200
199
201
# Constructor for a resampling FIR filter, where the user needs only to set the sampling rate
@@ -623,31 +625,34 @@ function filt!(
623
625
return bufIdx
624
626
end
625
627
626
- function filt (self:: FIRFilter{Tk} , x:: AbstractVector{Tx} ) where {Th,Tx,Tk<: FIRKernel{Th} }
627
- bufLen = outputlength (self, length (x))
628
+ function filt (self:: FIRFilter{Tk} , x:: AbstractVector ) where Tk<: FIRKernel
629
+ buffer = allocate_output (self, x)
630
+ bufLen = length (buffer)
631
+ samplesWritten = filt! (buffer, self, x)
632
+ if Tk <: FIRArbitrary
633
+ samplesWritten == bufLen || resize! (buffer, samplesWritten)
634
+ else
635
+ samplesWritten == bufLen || throw (AssertionError (" Length of resampled output different from expectation." ))
636
+ end
637
+ return buffer
638
+ end
639
+
640
+ function allocate_output (sf:: FIRFilter{Tk} , x:: AbstractVector{Tx} ) where {Th,Tx,Tk<: FIRKernel{Th} }
628
641
# In some cases when `filt(::FIRFilter{FIRArbitrary}, x)` is called
629
642
# with certain values of `x`, `filt!(buffer, ::FIRFilter{FIRArbitrary}, x)`
630
643
# tries to write one sample too many to the buffer and a `BoundsError`
631
- # is thrown. Add one extra sample to catch these exceptional cases.
644
+ # is thrown. Add one extra sample to catch these exceptional cases.
632
645
#
633
646
# See https://github.com/JuliaDSP/DSP.jl/issues/317
634
647
#
635
648
# FIXME : Remove this if and when the code in
636
649
# `filt!(buffer, ::FIRFilter{FIRArbitrary}, x)`
637
650
# is updated to properly account for pathological arbitrary rates.
651
+ outLen = outputlength (sf, length (x))
638
652
if Tk <: FIRArbitrary
639
- bufLen += 1
653
+ outLen += 1
640
654
end
641
- buffer = Vector {promote_type(Th,Tx)} (undef, bufLen)
642
- samplesWritten = filt! (buffer, self, x)
643
-
644
- if Tk <: FIRArbitrary
645
- samplesWritten == bufLen || resize! (buffer, samplesWritten)
646
- else
647
- @assert samplesWritten == bufLen
648
- end
649
-
650
- return buffer
655
+ return Vector {promote_type(Th, Tx)} (undef, outLen)
651
656
end
652
657
653
658
@@ -689,24 +694,34 @@ function resample(x::AbstractVector, rate::AbstractFloat, h::Vector, Nϕ::Intege
689
694
_resample! (x, rate, FIRFilter (h, rate, Nϕ))
690
695
end
691
696
692
- function _resample! (x:: AbstractVector , rate:: Real , self:: FIRFilter )
697
+ function _resample! (x:: AbstractVector , rate:: Real , sf:: FIRFilter )
698
+ undelay! (sf)
699
+ outLen = ceil (Int, length (x) * rate)
700
+ xPadded = _zeropad (x, inputlength (sf, outLen, RoundUp))
701
+
702
+ buffer = allocate_output (sf, xPadded)
703
+ samplesWritten = filt! (buffer, sf, xPadded)
704
+ return checked_resample_output! (buffer, outLen, samplesWritten, sf)
705
+ end
706
+
707
+ function undelay! (sf:: FIRFilter )
693
708
# Get delay, in # of samples at the output rate, caused by filtering processes
694
- τ = timedelay (self )
709
+ τ = timedelay (sf )
695
710
696
711
# Use setphase! to
697
712
# a) adjust the input samples to skip over before producing and output (integer part of τ)
698
713
# b) set the ϕ index of the PFB (fractional part of τ)
699
- setphase! (self, τ)
700
-
701
- # Calculate the number of 0's required
702
- outLen = ceil (Int, length (x) * rate)
703
- reqInlen = inputlength (self, outLen, RoundUp)
704
- reqZerosLen = reqInlen - length (x)
705
- xPadded = [x; zeros (eltype (x), reqZerosLen)]
714
+ setphase! (sf, τ)
715
+ end
706
716
707
- y = filt (self, xPadded)
708
- @assert length (y) >= outLen
709
- length (y) > outLen && resize! (y, outLen)
717
+ function checked_resample_output! (y:: AbstractVector , outLen, samplesWritten, :: FIRFilter{Tk} ) where Tk<: FIRKernel
718
+ if ! (Tk <: FIRArbitrary )
719
+ samplesWritten == length (y) || throw (AssertionError (" Length of resampled output different from expectation." ))
720
+ end
721
+ # outLen: the desired output length ceil(Int, rate * length(input)), but we can overshoot
722
+ # samplesWritten: number of samples actually written to y; if longer, y[samplesWritten+1:end] contains invalid data
723
+ samplesWritten >= outLen || throw (AssertionError (" Resample output shorter than expected." ))
724
+ length (y) == outLen || resize! (y, outLen)
710
725
return y
711
726
end
712
727
@@ -742,11 +757,23 @@ end
742
757
resample (x:: AbstractArray , rate:: Real , args:: Real... ; dims) =
743
758
_resample! (x, rate, FIRFilter (rate, args... ); dims)
744
759
745
- _resample! (x:: AbstractArray , rate:: Real , sf:: FIRFilter ; dims) =
746
- mapslices (x; dims) do v
747
- reset! (sf)
748
- _resample! (v, rate, sf)
760
+ function _resample! (x:: AbstractArray{T} , rate:: Real , sf:: FIRFilter ; dims:: Int ) where T
761
+ undelay! (sf)
762
+ size_v = size (x, dims)
763
+ outLen = ceil (Int, size_v * rate)
764
+ xPadded = Vector {T} (undef, inputlength (sf, outLen, RoundUp))
765
+ xPadded[size_v+ 1 : end ] .= zero (T)
766
+ buffer = allocate_output (sf, xPadded)
767
+ bufLen = length (buffer)
768
+
769
+ mapslices (x; dims) do v:: AbstractVector
770
+ undelay! (reset! (sf))
771
+ length (buffer) == bufLen || resize! (buffer, bufLen)
772
+ copyto! (xPadded, v)
773
+ samplesWritten = filt! (buffer, sf, xPadded)
774
+ return checked_resample_output! (buffer, outLen, samplesWritten, sf)
749
775
end
776
+ end
750
777
751
778
#
752
779
# References
0 commit comments