Skip to content

Commit 0c2353c

Browse files
committed
Merge pull request #111 from JuliaDSP/jsk/resamplers
resample function
2 parents bfb78ef + 790f2cc commit 0c2353c

16 files changed

+1069
-35
lines changed

doc/filters.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ Filter application
132132
Apply FIR filter ``b`` along the first dimension of array ``x``
133133
using an FFT-based overlap-save algorithm.
134134

135+
.. function:: resample(x, rate[, coef])
136+
137+
Resample ``x`` at rational or arbitrary ``rate``.
138+
``coef`` is an optional vector of FIR filter taps. If ``coef``
139+
is not provided, the taps will be computed using a Kaiser window.
140+
141+
Internally, ``resample`` uses a polyphase ``FIRFilter`` object,
142+
but performs additional operations to make resampling a signal easier.
143+
It compensates for for the ``FIRFilter``'s delay (ramp-up), and appends
144+
zeros to ``x``. The result is that when the input and output signals
145+
are plotted on top of each other, they correlate very well, but one
146+
signal will have more samples that the other.
147+
148+
135149

136150
Filter design
137151
-------------

src/Filters/Filters.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export FilterType,
2929
digitalfilter,
3030
iirnotch,
3131
kaiserord,
32-
FIRWindow
32+
FIRWindow,
33+
resample_filter
3334

3435
include("response.jl")
3536
export freqs,
@@ -42,6 +43,9 @@ include("stream_filt.jl")
4243
export FIRFilter,
4344
outputlength,
4445
inputlength,
45-
reset!
46+
reset!,
47+
resample,
48+
setphase!,
49+
timedelay
4650

4751
end

src/Filters/design.jl

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,7 @@ function kaiserord(transitionwidth::Real, attenuation::Real=60)
423423
β = 0.0
424424
end
425425

426-
α = π*β
427-
428-
return n, α
426+
return n, β/π
429427
end
430428

431429
immutable FIRWindow{T}
@@ -496,3 +494,42 @@ function digitalfilter(ftype::FilterType, proto::FIRWindow)
496494
out = coefs .* proto.window
497495
proto.scale ? scale!(out, 1/scalefactor(out, ftype)) : out
498496
end
497+
498+
499+
# Compute FIR coefficients necessary for arbitrary rate resampling
500+
function resample_filter(rate::FloatingPoint, Nϕ = 32, rel_bw = 1.0, attenuation = 60)
501+
f_nyq = rate >= 1.0 ? 1.0/: rate/
502+
cutoff = f_nyq * rel_bw
503+
trans_width = cutoff * 0.2
504+
505+
# Determine resampling filter order
506+
hLen, α = kaiserord(trans_width, attenuation)
507+
508+
# Round the number of taps up to a multiple of Nϕ.
509+
# Otherwise the missing taps will be filled with 0.
510+
hLen =* ceil(Int, hLen/Nϕ)
511+
512+
# Design filter
513+
h = digitalfilter(Lowpass(cutoff), FIRWindow(kaiser(hLen, α)))
514+
scale!(h, Nϕ)
515+
end
516+
517+
# Compute FIR coefficients necessary for rational rate resampling
518+
function resample_filter(rate::Rational, rel_bw = 1.0, attenuation = 60)
519+
= num(rate)
520+
decimation = den(rate)
521+
f_nyq = min(1/Nϕ, 1/decimation)
522+
cutoff = f_nyq * rel_bw
523+
trans_width = cutoff * 0.2
524+
525+
# Determine resampling filter order
526+
hLen, α = kaiserord(trans_width, attenuation)
527+
528+
# Round the number of taps up to a multiple of Nϕ (same as interpolation factor).
529+
# Otherwise the missing taps will be filled with 0.
530+
hLen =* ceil(Int, hLen/Nϕ)
531+
532+
# Design filter
533+
h = digitalfilter(Lowpass(cutoff), FIRWindow(kaiser(hLen, α)))
534+
scale!(h, Nϕ)
535+
end

0 commit comments

Comments
 (0)