Skip to content

Commit

Permalink
Fix bounds errors when resampling with some arbitrary ratios (#539)
Browse files Browse the repository at this point in the history
In some cases when `filt(::FIRFilter{FIRArbitrary}, x)` is called
with certain values of `x`, `filt!(buffer, ::FIRFilter{FIRArbitrary}, x)`
tries to write one sample too many to the buffer and a `BoundsError`
is thrown.  Add one extra sample to the buffer to catch these
exceptional cases.

(This code is really a hack and simply works around the deeper problem
of calculating the correct output buffer length; this should instead be
addressed properly in a future change.)

Closes #317.

(cherry picked from commit 73d3214)
  • Loading branch information
anowacki authored and martinholters committed Sep 13, 2024
1 parent d2e69ee commit 0079c28
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Filters/stream_filt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,19 @@ end

function filt(self::FIRFilter{Tk}, x::AbstractVector{Tx}) where {Th,Tx,Tk<:FIRKernel{Th}}
bufLen = outputlength(self, length(x))
# In some cases when `filt(::FIRFilter{FIRArbitrary}, x)` is called
# with certain values of `x`, `filt!(buffer, ::FIRFilter{FIRArbitrary}, x)`
# tries to write one sample too many to the buffer and a `BoundsError`
# is thrown. Add one extra sample to catch these exceptional cases.
#
# See https://github.com/JuliaDSP/DSP.jl/issues/317
#
# FIXME: Remove this if and when the code in
# `filt!(buffer, ::FIRFilter{FIRArbitrary}, x)`
# is updated to properly account for pathological arbitrary rates.
if Tk <: FIRArbitrary
bufLen += 1
end
buffer = Vector{promote_type(Th,Tx)}(undef, bufLen)
samplesWritten = filt!(buffer, self, x)

Expand Down
10 changes: 10 additions & 0 deletions test/resample.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ end
@test all(map(delta -> abs(delta) < 0.005, yDelta))
end

@testset "arbitrary ratio" begin
# https://github.com/JuliaDSP/DSP.jl/issues/317
@testset "Buffer length calculation" begin
@test length(resample(sin.(1:1:35546), 1/55.55)) == 641
@test length(resample(randn(1822), 0.9802414928649835)) == 1787
@test length(resample(1:16_367_000*2, 10_000_000/16_367_000)) == 20_000_001
@test resample(zeros(1000), 0.012) == zeros(13)
end
end

@testset "resample_filter" begin
@testset "decimation" begin
ratio = 1//2
Expand Down

0 comments on commit 0079c28

Please sign in to comment.