Compare commits

..

14 commits
v1.0.0 ... main

Author SHA1 Message Date
43c1486f7d synthesis bugfix 2023-11-23 11:54:39 +01:00
26c9c70f3c synthesis cosmetic change 2023-11-13 15:28:52 +01:00
702628ed9c Constant size input STFT 2023-08-30 13:28:29 +02:00
a55523d7ee Project.toml update 2023-08-29 18:59:11 +02:00
f4c51a7e8e bugfix 2023-08-29 18:57:21 +02:00
7b9c732478 change version 2023-08-29 16:36:18 +02:00
136d84ae9d multichannel analysis support 2023-08-29 16:32:04 +02:00
22d3057a2d Project.toml update v3 2023-08-28 20:08:24 +02:00
f7c3d2fbb2 Project.toml update v2 2023-08-28 18:17:03 +02:00
e36f8160fc Project.toml update 2023-08-28 17:00:27 +02:00
06ec0944c6 source repo url changed 2023-08-28 15:58:35 +02:00
b13e54dddb SIMD instruction added 2023-08-28 15:56:36 +02:00
89dcd1bc92 Function name correction + new dev repo link 2022-10-09 14:05:53 +02:00
0a417837b7 README update 2022-06-25 11:31:58 +02:00
3 changed files with 71 additions and 29 deletions

View file

@ -1,13 +1,13 @@
name = "STFT" name = "STFT"
uuid = "58bb99bf-048b-48b7-93e7-1cbf3ee61509" uuid = "58bb99bf-048b-48b7-93e7-1cbf3ee61509"
authors = ["Szymon M. Woźniak"] authors = ["Szymon M. Woźniak <s@zymon.org>"]
version = "1.0.0" version = "1.3.0"
[deps] [deps]
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
LoopVectorization = "bdcacae8-1622-11e9-2a5c-532679323890"
[compat] [compat]
FFTW = "1.7"
FFTW = "1.4" LoopVectorization = "0.12.101"
julia = "1.6" julia = "1.6"

View file

@ -12,16 +12,20 @@ Check the [documentation](https://docs.zymon.org/STFT.jl/) for more insights.
## Installation ## Installation
The package is currently not available in [General](https://github.com/JuliaRegistries/General), the default Julia package registry. The package is currently available in General, the default Julia package registry.
To install this package from General registry, use the following command in Julia REPL:
To install it, use the following command in Julia package manager:
```julia ```julia
pkg> add https://github.com/s-zymon/STFT.jl ] add STFT
``` ```
Alternatively, directly via repository:
```julia
pkg> add https://codeberg.org/zymon/STFT.jl
```
## Examples ## Examples
Below you can find a few standalone example with basic usage of the package. Below you can find a few standalone examples with basic usage of the package.
### Show spectrogram ### Show spectrogram

View file

@ -1,12 +1,25 @@
module STFT module STFT
using LoopVectorization
using FFTW using FFTW
export stft, istft export stft, istft
_fft(x::AbstractMatrix{<:Real}, d) = rfft(x, d) _fft(x::AbstractArray{<:Real}, d) = rfft(x, d)
_fft(x::AbstractMatrix{<:Complex}, d) = fft(x, d) _fft(x::AbstractArray{<:Complex}, d) = fft(x, d)
function malloc_stft(
x::M,
w::V,
L::I = zero(I),
N::I = length(w);
) where {T<:Number, I<:Integer, V<:AbstractVector{T}, M<:AbstractMatrix{T}}
X, K = size(x) # Length of the signal in samples
W = length(w) # Length of the window in samples
S = (X-L) ÷ (W - L) # Number of segments
N = N < W ? W : N # DFT size
zeros(T, (N, S, K)) # Allocate container for signal segments
end
doc_analysis = """ doc_analysis = """
@ -94,24 +107,31 @@ function analysis() end
stft(x, w, L=0, N=length(w)) = analysis(x, w, L, N) stft(x, w, L=0, N=length(w)) = analysis(x, w, L, N)
function analysis( function analysis(
x::AbstractVector{T}, x::M,
w::AbstractVector{T}, w::V,
L::Integer = 0, L::I = zero(I),
N::Integer = length(w); N::I = length(w);
)::AbstractMatrix{<:Complex} where {T<:Number} ) where {T<:Number, I<:Integer, V<:AbstractVector{T}, M<:AbstractMatrix{T}}
X = length(x) # Length of the signal in samples sc = malloc_stft(x, w, L, N)
W = length(w) # Length of the window in samples N, S, K = sc |> size
H = W - L # Hop W = w |> length
S = (X-L) ÷ H # Number of segments
N = N < W ? W : N # DFT size
sc = zeros(T, N, S) # Allocate container for signal segments
for s 1:S, n 1:W # Slice the signal @turbo for k 1:K, s 1:S, n 1:W
sc[n, s] = w[n] * x[(s-1)*H+n] sc[n, s, k] = w[n] * x[(s-1)*(W-L)+n, k]
end end
_fft(sc, 1) # Convert segments to frequency-domain _fft(sc, 1) # Convert segments to frequency-domain
end end
function analysis(
x::V,
w::V,
L::I = zero(I),
N::I = length(w);
)::Matrix{T |> complex} where {T<:Number, I<:Integer, V<:AbstractVector{T}}
xx = @view x[:,:]
@view analysis(xx, w, L, N)[:, :, 1]
end
function analysis( function analysis(
xs::AbstractArray{<:AbstractVector{T}}, xs::AbstractArray{<:AbstractVector{T}},
w::AbstractVector{T}, w::AbstractVector{T},
@ -211,7 +231,7 @@ xr = istft(X, w, L) # Synthesis
function synthesis() end function synthesis() end
"$doc_synthesis" "$doc_synthesis"
isftf(X, w, L=0, N=length(w)) = synthesis(X, w, L, N) istft(X, w, L=0, N=length(w)) = synthesis(X, w, L, N)
function synthesis( function synthesis(
X::AbstractMatrix{<:Complex}, X::AbstractMatrix{<:Complex},
@ -229,14 +249,32 @@ function synthesis(
xs = irfft(X, N, 1) # Convert segments to time-domain xs = irfft(X, N, 1) # Convert segments to time-domain
for s 1:S @turbo for s 0:(S-1)
ss = (s-1)*H # Segment start ss = s*H # Segment shift
for n = 1:W for n = 1:W
xn[ss+n] += xs[n, s] * w[n] xn[ss+n] += xs[n, s+1] * w[n]
xd[ss+n] += [n] xd[ss+n] += [n]
end end
end end
xn ./ xd # Normalize xn ./ xd # Normalize
end end
"""
Real-value signal STFT with constant input size.
"""
function rSTFTm(A, w, L, N=length(w))
mem = STFT.malloc_stft(A, w, L, N)
N, S, K = mem |> size
W = w |> length
P = plan_rfft(mem, 1)
function f(x)
@turbo for k 1:K, s 1:S, n 1:W
mem[n, s, k] = w[n] * x[(s-1)*(W-L)+n, k]
end
P * mem
end
return f
end
end # module end # module