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

View file

@ -12,16 +12,20 @@ Check the [documentation](https://docs.zymon.org/STFT.jl/) for more insights.
## Installation
The package is currently not available in [General](https://github.com/JuliaRegistries/General), the default Julia package registry.
To install it, use the following command in Julia package manager:
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:
```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
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

View file

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