# I have a hard time finding a good "upfirdn"

**URL:** <https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540>\
**Category:** Signal and Image Processing\
**Tags:** dsp\
**Created:** [August 17, 2021, 10:56am UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540 "2021-08-17T10:56:02Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![psteffensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/psteffensen/32/37583_2.png) [@psteffensen](https://discourse.julialang.org/u/psteffensen)\
**Post date:** [August 17, 2021, 10:56am UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/1 "2021-08-17T10:56:02Z")

</div>

Hi,

I am translating some code from Matlab to Julia and can’t find an equvalent to upfirdn. The only working option I have is to use PyCall and use the Python (SciPy) version. Like this:

```julia
scipy_signal = pyimport("scipy.signal")
s = scipy_signal.upfirdn(filter, s, p, q)

```

I also tried to make my own version using DSP.resample and DSP.Filters.filt. But it doesn’t work…yet 🙂 .

Have I missed some great library?

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [August 17, 2021, 1:38pm UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/3 "2021-08-17T13:38:45Z")

</div>

It seems like you should be able to implement this easily with resample and filter. What is the issue you are having?

---

<div class="post-metadata">

**Author:** ![psteffensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/psteffensen/32/37583_2.png) [@psteffensen](https://discourse.julialang.org/u/psteffensen)\
**Post date:** [August 18, 2021, 7:34pm UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/4 "2021-08-18T19:34:25Z")

</div>

I had problems with padding. It works now, but an explanation why it works would be appreciated 🙂

```julia
function upfirdn(s, filter, p, q)
    pad = length(s)*p+length(filter)-p
    if p != 1
        s_padded = [s; zeros(ComplexF64, length(filter))] # need padding for the filter
        s = DSP.resample(s_padded, p, [1]) # [1] makes it a zero insertion upsampling
    end

    s = DSP.Filters.filt(FIRFilter(filter), s)
    s = s[1:pad] # Take away padding

    if q != 1
        #result_length = Int(p * length(s))
        s = DSP.resample(s, 1/q, [1]) # downsample
        #s = [s; zeros(ComplexF64, result_length - length(s))] # zero padding to get correct length
    end

    #=
    @show size(s), p, q, size(filter)
    scipy_signal = pyimport("scipy.signal")
    s = scipy_signal.upfirdn(filter, s, p, q)
    @show size(s)
    =#
    return s

end

```

It works but it is slightly slower than using PyCall. So I need to find a way to speed it up.

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [August 18, 2021, 8:56pm UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/5 "2021-08-18T20:56:24Z")

</div>

> [@psteffensen](#):
>
> So I need to find a way to speed it up.

There are a number of things that you could try, but the first thing would be to

```julia
using BenchmarkTools

@benchmark upfirdn(...)

```

to figure out how much time it’s taking and how much GC it’s doing.

Your best bets are going to be to reduce allocations. perhaps create a buffer that you reuse by calling filt! and then use a @view to strip padding etc.

---

<div class="post-metadata">

**Author:** ![sirtom67](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sirtom67/32/3689_2.png) [@sirtom67](https://discourse.julialang.org/u/sirtom67)\
**Post date:** [October 26, 2021, 2:02am UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/6 "2021-10-26T02:02:30Z")

</div>

Hi @psteffensen,I just needed to point something out here.  
What you have implemented is exactly correct for getting the result, but it is a very slow and inefficient algorithm. You should use the FIRFilter stateful filter object with a rational rate, which uses an efficient polyphase resampler.

```julia
FIRFilter(h[, ratio])

```

Construct a stateful FIRFilter object from the vector of filter taps `h` . `ratio` is an optional rational integer which specifies the input to output sample rate relationship (e.g. `147//160` for converting recorded audio from 48 KHz to 44.1 KHz).

[https://github.com/JuliaDSP/DSP.jl/blob/7beb55d71231ec1e66abcfe23791553a549a2f44/src/Filters/stream\_filt.jl#L148-L155](https://github.com/JuliaDSP/DSP.jl/blob/7beb55d71231ec1e66abcfe23791553a549a2f44/src/Filters/stream_filt.jl#L148-L155)

Best regards,  
Tom

---

<div class="post-metadata">

**Author:** ![psteffensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/psteffensen/32/37583_2.png) [@psteffensen](https://discourse.julialang.org/u/psteffensen)\
**Post date:** [November 1, 2021, 7:12am UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/7 "2021-11-01T07:12:28Z")

</div>

Thank you Tom (sirtom67) for pointing that out,

I actually ended up using “DSP.Filters.filt!” in my code. I guess it is the same as FIRfilter. I used it because it was much faster, like you say, but I thought I was cheating 😊

My code only needed “upfir” and not the “down” part, so it ended up looking like this:

```julia
function upfirdn(s, filter, p, q)
    ## FIR (Filter)
    result = zeros(ComplexF64, length(s)*p+length(filter))
    DSP.Filters.filt!(result, FIRFilter(filter, p), s)

    return result
end

```

Then for the “down” part i guess you can you resample to decimate, like this:

```julia
    if q != 1
        s = DSP.resample(s, 1/q, [1])
    end

```

---

<div class="post-metadata">

**Author:** ![sirtom67](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sirtom67/32/3689_2.png) [@sirtom67](https://discourse.julialang.org/u/sirtom67)\
**Post date:** [November 2, 2021, 12:52am UTC](https://discourse.julialang.org/t/i-have-a-hard-time-finding-a-good-upfirdn/66540/8 "2021-11-02T00:52:29Z")

</div>

Looks good.

The “down” part here suggests part of the problem - for downsampling with factor q \> 1, it is inefficient to call filt first, and then throw away (q-1) out of q samples - you’ve done “q”-times as much work as required! So - if it matters (and it may very well not matter if the code runs fast enough due to small signal and / or filter lengths) - it is better to include the “q” downsample factor in the FIRFilter.
