-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTFT.py
executable file
·182 lines (149 loc) · 4.84 KB
/
STFT.py
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
def Stft(x, wlen, h, nfft, fs, winType='hamming'):
"""
Compute the Short-Time Fourier Transform of a signal, with an hamming window.
Parameters
----------
x : numpy array (n x 1)
vector signal for which we want to compute the STFT
wlen : int
length of the window, in samples
h : int
hop size, in samples
nfft : int
number of samples used to compute the FFT algorithm
fs : int
sampling frequency
winType : char*
type of window used
Returns
-------
X : numpy array (F x N)
STFT of the input signal
f : numpy array (F,)
frequency vector (Hz)
t : numpy array (N,)
time vector of the center of the frames (seconds)
AUTHORS
======
[email protected], based on the 'stft.m' function from Hristo Zhivomirov (dated 12/21/13).
Copyright (c) 2015 IRCAM under GNU General Public License version 3.
Developed on MatLab 7.7.0.471 (R2008b)
Translation to python, E. L. Benaroya - 09/2018 - Telecom ParisTech - [email protected]
"""
if winType.lower() == 'hamming':
win = np.hamming(wlen)
else:
raise Exception("window type Not implemented yet")
xlen = len(x)
rown = int(np.ceil((1+nfft)/2))
coln = 1+int(np.floor((xlen-wlen)/h))
X = np.zeros((rown, coln), dtype=np.complex128)
indx = 0
col = 0
while indx+wlen < xlen:
xw = x[indx:(indx+wlen)]*win
Xtmp = scipy.fftpack.fft(xw, nfft)
X[:, col] = Xtmp[:rown]
indx += h
col += 1
t = np.arange(int(wlen/2), xlen-int(wlen/2), h)/fs
f = np.arange(rown)*fs/nfft
return X, f, t
def Istft(X, wlen, h, nfft, fs, winType='hamming'):
"""
Inverse STFT
Parameters
----------
X : numpy array (F, N)
wlen : int
window length in samples
h : int
offset in samples
nfft : int
number of samples used to compute the IFFT algorithm
fs : int
sampling frequency
winType : char*
analysis and synthesis overlap add window type
Returns
-------
x : numpy array (n,)
output waveform
t : numpy array (n,)
time vector in seconds
"""
if winType.lower() == 'hamming':
win = np.hamming(wlen)
else:
raise Exception("window type Not implemented yet")
rown, coln = X.shape
xlen = wlen + (coln-1) * h
x = np.zeros((xlen,))
tmp = np.zeros((xlen,))
if int(nfft/2)*2 != nfft: # nfft is odd, exclude Nyquist frequency
for b in np.arange(0, h*coln, h):
Xtmp = X[:, int(b/h)]
xprim = np.concatenate((Xtmp, np.flip(np.conj(Xtmp[1:]), axis=0)), axis=0)
xprim = np.real(scipy.fftpack.ifft(xprim, nfft))
xprim = xprim[:wlen]
x[b:(b+wlen)] += xprim*win
tmp[b:(b+wlen)] += win*win
else:
for b in np.arange(0, h*coln, h):
Xtmp = X[:, int(b/h)]
xprim = np.concatenate((Xtmp, np.flip(np.conj(Xtmp[1:-1]), axis=0)), axis=0)
xprim = np.real(scipy.fftpack.ifft(xprim, nfft))
xprim = xprim[:wlen]
x[b:(b+wlen)] += xprim*win
tmp[b:(b+wlen)] += win*win
x = x/tmp
actlen = len(x)
t = np.arange(0, actlen)/fs
return x, t
def spectrogram(x, wlen, h, nfft, fs, dB=True, plot=False, show=False):
""""
Compute and display the spectrogram of a 1D signal
Parameters
----------
x : np array (n,)
signal for which we want to compute (and plot) the spectrogram
wlen : int
length of the analysis window, in samples
h : int
hop size, in samples
nfft : int
number of samples used to compute the FFT
fs : int
sampling frequency
dB : bool
take 20*log10(spectrogram) if True
plot : bool
plot spectrogram if True
show : bool
call plt.show() if True
Returns
-------
Xspec : numpy array (F x N)
spectrogram
f : np array (F,)
frequency vector (Hz)
t : np array (N,)
time vector of the center of the frames (seconds)
E. L. Benaroya - 09/2018 - Telecom ParisTech - [email protected]
"""
X, f, t = Stft(x, wlen, h, nfft, fs)
Xspec = np.abs(X)
if dB:
Xspec = 20*np.log10(Xspec) # in dB
if plot:
plt.imshow(Xspec, origin='lower', interpolation='nearest',
aspect='auto', extent=(0, t[-1], 0, f[-1]))
# plt.colorbar()
plt.xlabel('Temps (secondes)')
plt.ylabel('Fréquence (Hz)')
if show:
plt.show()
return Xspec, f, t