Skip to content

Commit

Permalink
Move DSP functions from Base into this package
Browse files Browse the repository at this point in the history
  • Loading branch information
ararslan committed Jun 14, 2017
1 parent 5b40e51 commit 1374a0a
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 157 deletions.
2 changes: 2 additions & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ julia 0.6-rc1
Polynomials 0.1.0
Reexport
SpecialFunctions
AbstractFFTs
FFTW
25 changes: 24 additions & 1 deletion src/DSP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,37 @@ __precompile__()

module DSP

# We want to be very sure we don't pull in Base names unless we're very sure we want them
# This macro will be called in each submodule herein to do the appropriate imports
macro importffts()
quote
using AbstractFFTs, FFTW
importall AbstractFFTs, FFTW
if VERSION >= v"0.7.0-DEV.585"
import AbstractFFTs: fftshift, ifftshift
import FFTW: plan_fft, plan_fft!, plan_rfft, plan_brfft, plan_irfft, plan_bfft, plan_bfft!,
fft, fft!, ifft, ifft!, irfft, bfft, bfft!
if isdefined(Base, :DSP)
import Base: conv, conv2, deconv, filt, filt!, xcorr
end
else
import Base: plan_fft, plan_fft!, plan_rfft, plan_brfft, plan_irfft, plan_bfft, plan_bfft!,
fft, fft!, ifft, ifft!, irfft, bfft, bfft!, fftshift, ifftshift
end
end
end

@importffts

include("dspbase.jl")
include("util.jl")
include("windows.jl")
include("periodograms.jl")
include("Filters/Filters.jl")
include("lpc.jl")

using Reexport
@reexport using .Util, .Windows, .Periodograms, .Filters, .LPC
@reexport using .Util, .Windows, .Periodograms, .Filters, .LPC

include("deprecated.jl")
end
2 changes: 2 additions & 0 deletions src/Filters/Filters.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Filters
import ..DSP: @importffts, filt, filt!
using Polynomials, ..Util
import Base: *
@importffts

include("coefficients.jl")
export FilterCoefficients,
Expand Down
34 changes: 17 additions & 17 deletions src/Filters/filt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
_zerosi(f::PolynomialRatio{T}, x::AbstractArray{S}) where {T,S} =
zeros(promote_type(T, S), max(length(f.a), length(f.b))-1)

Base.filt!(out, f::PolynomialRatio{T}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,S} =
filt!(out, f::PolynomialRatio{T}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,S} =
filt!(out, coefb(f), coefa(f), x, si)
Base.filt(f::PolynomialRatio, x, si=_zerosi(f, x)) = filt(coefb(f), coefa(f), x, si)
filt(f::PolynomialRatio, x, si=_zerosi(f, x)) = filt(coefb(f), coefa(f), x, si)

## SecondOrderSections
_zerosi(f::SecondOrderSections{T,G}, x::AbstractArray{S}) where {T,G,S} =
Expand All @@ -36,7 +36,7 @@ function _filt!(out::AbstractArray, si::AbstractArray{S,N}, f::SecondOrderSectio
si
end

function Base.filt!(out::AbstractArray, f::SecondOrderSections, x::AbstractArray,
function filt!(out::AbstractArray, f::SecondOrderSections, x::AbstractArray,
si::AbstractArray{S,N}=_zerosi(f, x)) where {S,N}
biquads = f.biquads
ncols = Base.trailingsize(x, 2)
Expand All @@ -54,7 +54,7 @@ function Base.filt!(out::AbstractArray, f::SecondOrderSections, x::AbstractArray
out
end

Base.filt(f::SecondOrderSections{T,G}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,G,S<:Number} =
filt(f::SecondOrderSections{T,G}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,G,S<:Number} =
filt!(Array{promote_type(T, G, S)}(size(x)), f, x, si)

## Biquad
Expand All @@ -75,7 +75,7 @@ function _filt!(out::AbstractArray, si1::Number, si2::Number, f::Biquad,
end

# filt! variant that preserves si
function Base.filt!(out::AbstractArray, f::Biquad, x::AbstractArray,
function filt!(out::AbstractArray, f::Biquad, x::AbstractArray,
si::AbstractArray{S,N}=_zerosi(f, x)) where {S,N}
ncols = Base.trailingsize(x, 2)

Expand All @@ -90,12 +90,12 @@ function Base.filt!(out::AbstractArray, f::Biquad, x::AbstractArray,
out
end

Base.filt(f::Biquad{T}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,S<:Number} =
filt(f::Biquad{T}, x::AbstractArray{S}, si=_zerosi(f, x)) where {T,S<:Number} =
filt!(Array{promote_type(T, S)}(size(x)), f, x, si)

## For arbitrary filters, convert to SecondOrderSections
Base.filt(f::FilterCoefficients, x) = filt(convert(SecondOrderSections, f), x)
Base.filt!(out, f::FilterCoefficients, x) = filt!(out, convert(SecondOrderSections, f), x)
filt(f::FilterCoefficients, x) = filt(convert(SecondOrderSections, f), x)
filt!(out, f::FilterCoefficients, x) = filt!(out, convert(SecondOrderSections, f), x)

#
# Direct form II transposed filter with state
Expand Down Expand Up @@ -126,7 +126,7 @@ DF2TFilter(coef::PolynomialRatio{T},
state::Vector{S}=zeros(T, max(length(coef.a), length(coef.b))-1)) where {T,S} =
DF2TFilter{PolynomialRatio{T}, Vector{S}}(coef, state)

function Base.filt!(out::AbstractVector, f::DF2TFilter{PolynomialRatio{T},Vector{S}}, x::AbstractVector) where {T,S}
function filt!(out::AbstractVector, f::DF2TFilter{PolynomialRatio{T},Vector{S}}, x::AbstractVector) where {T,S}
length(x) != length(out) && throw(ArgumentError("out size must match x"))

si = f.state
Expand Down Expand Up @@ -156,7 +156,7 @@ DF2TFilter(coef::SecondOrderSections{T,G},
state::Matrix{S}=zeros(promote_type(T, G), 2, length(coef.biquads))) where {T,G,S} =
DF2TFilter{SecondOrderSections{T,G}, Matrix{S}}(coef, state)

function Base.filt!(out::AbstractVector, f::DF2TFilter{SecondOrderSections{T,G},Matrix{S}}, x::AbstractVector) where {T,G,S}
function filt!(out::AbstractVector, f::DF2TFilter{SecondOrderSections{T,G},Matrix{S}}, x::AbstractVector) where {T,G,S}
length(x) != length(out) && throw(ArgumentError("out size must match x"))
_filt!(out, f.state, f.coef, x, 1)
out
Expand All @@ -165,15 +165,15 @@ end
## Biquad
DF2TFilter(coef::Biquad{T}, state::Vector{S}=zeros(T, 2)) where {T,S} =
DF2TFilter{Biquad{T}, Vector{S}}(coef, state)
function Base.filt!(out::AbstractVector, f::DF2TFilter{Biquad{T},Vector{S}}, x::AbstractVector) where {T,S}
function filt!(out::AbstractVector, f::DF2TFilter{Biquad{T},Vector{S}}, x::AbstractVector) where {T,S}
length(x) != length(out) && throw(ArgumentError("out size must match x"))
si = f.state
(si[1], si[2]) =_filt!(out, si[1], si[2], f.coef, x, 1)
out
end

# Variant that allocates the output
Base.filt(f::DF2TFilter{T,S}, x::AbstractVector) where {T,S<:Array} =
filt(f::DF2TFilter{T,S}, x::AbstractVector) where {T,S<:Array} =
filt!(Array{eltype(S)}(length(x)), f, x)

# Fall back to SecondOrderSections
Expand Down Expand Up @@ -353,7 +353,7 @@ end
for n = 2:15
silen = n-1
si = [Symbol("si$i") for i = 1:silen]
@eval function Base.filt!(out, b::NTuple{$n,T}, x) where T
@eval function filt!(out, b::NTuple{$n,T}, x) where T
size(x) != size(out) && error("out size must match x")
ncols = Base.trailingsize(x, 2)
for col = 0:ncols-1
Expand Down Expand Up @@ -386,7 +386,7 @@ end
$chain
end

function Base.filt!(out::AbstractArray, h::AbstractVector, x::AbstractArray)
function filt!(out::AbstractArray, h::AbstractVector, x::AbstractArray)
if length(h) == 1
return scale!(out, h[1], x)
elseif length(h) <= 15
Expand Down Expand Up @@ -415,8 +415,8 @@ function Base.filt!(out::AbstractArray, h::AbstractVector, x::AbstractArray)
out
end

Base.filt(h::AbstractArray, x::AbstractArray) =
Base.filt!(Array{eltype(x)}(size(x)), h, x)
filt(h::AbstractArray, x::AbstractArray) =
filt!(Array{eltype(x)}(size(x)), h, x)

#
# fftfilt and filt
Expand Down Expand Up @@ -511,7 +511,7 @@ end
# Filter x using FIR filter b, heuristically choosing to perform
# convolution in the time domain using filt or in the frequency domain
# using fftfilt
function Base.filt(b::AbstractVector{T}, x::AbstractArray{T}) where T<:Number
function filt(b::AbstractVector{T}, x::AbstractArray{T}) where T<:Number
nb = length(b)
nx = size(x, 1)

Expand Down
24 changes: 12 additions & 12 deletions src/Filters/stream_filt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ end
# Single rate filtering
#

function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRStandard{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
function filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRStandard{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
kernel = self.kernel
history::Vector{Tx} = self.history
bufLen = length(buffer)
Expand All @@ -398,7 +398,7 @@ function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRStandard{Th}}
return xLen
end

function Base.filt(self::FIRFilter{FIRStandard{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
function filt(self::FIRFilter{FIRStandard{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
bufLen = outputlength(self, length(x))
buffer = Array{promote_type(Th,Tx)}(bufLen)
samplesWritten = filt!(buffer, self, x)
Expand All @@ -413,7 +413,7 @@ end
# Interpolation
#

function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRInterpolator{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
function filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRInterpolator{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
kernel = self.kernel
history::Vector{Tx} = self.history
interpolation = kernel.interpolation
Expand Down Expand Up @@ -449,7 +449,7 @@ function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRInterpolator{
return bufIdx
end

function Base.filt(self::FIRFilter{FIRInterpolator{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
function filt(self::FIRFilter{FIRInterpolator{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
bufLen = outputlength(self, length(x))
buffer = Array{promote_type(Th,Tx)}(bufLen)
samplesWritten = filt!(buffer, self, x)
Expand All @@ -464,7 +464,7 @@ end
# Rational resampling
#

function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRRational{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
function filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRRational{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
kernel = self.kernel
history::Vector{Tx} = self.history
xLen = length(x)
Expand Down Expand Up @@ -505,7 +505,7 @@ function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRRational{Th}}
return bufIdx
end

function Base.filt(self::FIRFilter{FIRRational{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
function filt(self::FIRFilter{FIRRational{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
bufLen = outputlength(self, length(x))
buffer = Array{promote_type(Th,Tx)}(bufLen)
samplesWritten = filt!(buffer, self, x)
Expand All @@ -519,7 +519,7 @@ end
# Decimation
#

function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRDecimator{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
function filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRDecimator{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
kernel = self.kernel
xLen = length(x)
history::Vector{Tx} = self.history
Expand Down Expand Up @@ -553,7 +553,7 @@ function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRDecimator{Th}
return bufIdx
end

function Base.filt(self::FIRFilter{FIRDecimator{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
function filt(self::FIRFilter{FIRDecimator{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
bufLen = outputlength(self, length(x))
buffer = Array{promote_type(Th,Tx)}(bufLen)
samplesWritten = filt!(buffer, self, x)
Expand Down Expand Up @@ -582,7 +582,7 @@ function update(kernel::FIRArbitrary)
kernel.α = kernel.ϕAccumulator - kernel.ϕIdx
end

function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRArbitrary{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
function filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRArbitrary{Th}}, x::AbstractVector{Tx}) where {Tb,Th,Tx}
kernel = self.kernel
pfb = kernel.pfb
dpfb = kernel.dpfb
Expand Down Expand Up @@ -624,7 +624,7 @@ function Base.filt!(buffer::AbstractVector{Tb}, self::FIRFilter{FIRArbitrary{Th}
return bufIdx
end

function Base.filt(self::FIRFilter{FIRArbitrary{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
function filt(self::FIRFilter{FIRArbitrary{Th}}, x::AbstractVector{Tx}) where {Th,Tx}
bufLen = outputlength(self, length(x))
buffer = Array{promote_type(Th,Tx)}(bufLen)
samplesWritten = filt!(buffer, self, x)
Expand All @@ -640,13 +640,13 @@ end
#

# Single-rate, decimation, interpolation, and rational resampling.
function Base.filt(h::Vector, x::AbstractVector, ratio::Rational)
function filt(h::Vector, x::AbstractVector, ratio::Rational)
self = FIRFilter(h, ratio)
filt(self, x)
end

# Arbitrary resampling with polyphase interpolation and two neighbor linear interpolation.
function Base.filt(h::Vector, x::AbstractVector, rate::AbstractFloat, Nϕ::Integer=32)
function filt(h::Vector, x::AbstractVector, rate::AbstractFloat, Nϕ::Integer=32)
self = FIRFilter(h, rate, Nϕ)
filt(self, x)
end
Expand Down
8 changes: 1 addition & 7 deletions src/dspbase.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

module DSP
# This file was formerly a part of Julia. License is MIT: https://julialang.org/license

import Base.trailingsize

export filt, filt!, deconv, conv, conv2, xcorr

_zerosi(b,a,T) = zeros(promote_type(eltype(b), eltype(a), T), max(length(a), length(b))-1)

"""
Expand Down Expand Up @@ -203,5 +199,3 @@ function xcorr(u, v)
end
flipdim(conv(flipdim(u, 1), v), 1)
end

end # module
16 changes: 9 additions & 7 deletions src/periodograms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
# of the methods is available at:
# http://www.ee.lamar.edu/gleb/adsp/Lecture%2008%20-%20Nonparametric%20SE.pdf
module Periodograms
using ..DSP: @importffts
using ..Util, ..Windows
export arraysplit, nextfastfft, periodogram, welch_pgram, mt_pgram,
spectrogram, power, freq, stft
@importffts

## ARRAY SPLITTER

Expand Down Expand Up @@ -188,15 +190,15 @@ end
power(p::TFR) = p.power
freq(p::TFR) = p.freq
freq(p::Periodogram2) = (p.freq1, p.freq2)
Base.fftshift(p::Periodogram{T,F}) where {T,F<:Frequencies} =
fftshift(p::Periodogram{T,F}) where {T,F<:Frequencies} =
Periodogram(p.freq.nreal == p.freq.n ? p.power : fftshift(p.power), fftshift(p.freq))
Base.fftshift(p::Periodogram{T,F}) where {T,F<:Range} = p
fftshift(p::Periodogram{T,F}) where {T,F<:Range} = p
# 2-d
Base.fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Frequencies,F2<:Frequencies} =
fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Frequencies,F2<:Frequencies} =
Periodogram2(p.freq1.nreal == p.freq1.n ? fftshift(p.power,2) : fftshift(p.power), fftshift(p.freq1), fftshift(p.freq2))
Base.fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Range,F2<:Frequencies} =
fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Range,F2<:Frequencies} =
Periodogram2(fftshift(p.power,2), p.freq1, fftshift(p.freq2))
Base.fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Range,F2<:Range} = p
fftshift(p::Periodogram2{T,F1,F2}) where {T,F1<:Range,F2<:Range} = p

# Compute the periodogram of a signal S, defined as 1/N*X[s(n)]^2, where X is the
# DTFT of the signal S.
Expand Down Expand Up @@ -343,9 +345,9 @@ struct Spectrogram{T,F<:Union{Frequencies,Range}} <: TFR{T}
freq::F
time::FloatRange{Float64}
end
Base.fftshift(p::Spectrogram{T,F}) where {T,F<:Frequencies} =
fftshift(p::Spectrogram{T,F}) where {T,F<:Frequencies} =
Spectrogram(p.freq.nreal == p.freq.n ? p.power : fftshift(p.power, 1), fftshift(p.freq), p.time)
Base.fftshift(p::Spectrogram{T,F}) where {T,F<:Range} = p
fftshift(p::Spectrogram{T,F}) where {T,F<:Range} = p
Base.time(p::Spectrogram) = p.time

function spectrogram(s::AbstractVector{T}, n::Int=length(s)>>3, noverlap::Int=n>>1;
Expand Down
Loading

0 comments on commit 1374a0a

Please sign in to comment.