forked from r9y9/julia-nmf-ss-toy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstft.jl
78 lines (64 loc) · 2.28 KB
/
stft.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
### STFT/ISTFT ###
function blackman(n::Integer)
const a0, a1, a2 = 0.42, 0.5, 0.08
t = 2*pi/(n-1)
[a0 - a1*cos(t*k) + a2*cos(t*k*2) for k=0:n-1]
end
function hanning(n::Integer)
[0.5*(1-cos(2*pi*k/(n-1))) for k=0:n-1]
end
# countframes returns the number of frames that will be processed.
function countframes{T<:Number}(x::Vector{T}, framelen::Int, hopsize::Int)
div(length(x) - framelen, hopsize) + 1
end
# splitframes performs overlapping frame splitting.
function splitframes{T<:Number}(x::Vector{T},
framelen::Int=1024,
hopsize::Int=framelen/2)
const N = countframes(x, framelen, hopsize)
frames = Array(eltype(x), framelen, N)
for i=1:N
frames[:,i] = x[(i-1)*hopsize+1:(i-1)*hopsize+framelen]
end
return frames
end
# stft performs the Short-Time Fourier Transform (STFT) for real signals.
function stft{T<:Real}(x::Vector{T},
framelen::Int=1024,
hopsize::Int=div(framelen,2),
window=hanning(framelen))
frames = splitframes(x, framelen, hopsize)
const freqbins = div(framelen, 2) + 1
spectrogram = Array(Complex64, freqbins, size(frames,2))
for i=1:size(frames,2)
spectrogram[:,i] = rfft(frames[:,i] .* window)
end
return spectrogram
end
# istft peforms the Inverse STFT to recover the original signal from STFT
# coefficients.
function istft{T<:Complex}(spectrogram::Matrix{T},
framelen::Int=1024,
hopsize::Int=div(framelen,2),
window=hanning(framelen))
const numframes = size(spectrogram, 2)
expectedlen = framelen + (numframes-1)*hopsize
reconstructed = zeros(expectedlen)
windowsum = zeros(expectedlen)
const windowsquare = window .* window
# Overlapping addition
for i=1:numframes
s, e = (i-1)*hopsize+1, (i-1)*hopsize+framelen
r = irfft(spectrogram[:,i], framelen)
reconstructed[s:e] += r .* window
windowsum[s:e] += windowsquare
end
# Normalized by window
for i=1:endof(reconstructed)
# avoid zero division
if windowsum[i] > 1.0e-7
reconstructed[i] /= windowsum[i]
end
end
return reconstructed
end