Skip to content

Commit 5cf611d

Browse files
authored
Merge pull request #24 from 153hashimoto/khashimoto/chapter04
4章を追加 Hashimoto
2 parents a9a7434 + 349dbe9 commit 5cf611d

File tree

10 files changed

+339
-0
lines changed

10 files changed

+339
-0
lines changed

khashimoto/chapter04/q01.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# 零詰め
2+
3+
import numpy as np
4+
5+
6+
def zeropad(L, S, x):
7+
zero1 = np.zeros(L - S)
8+
# x_pad = np.concatenate([zero1, x, zero1]) # 1.
9+
x_pad = np.concatenate([zero1, x])
10+
zero2 = x_pad.size % S
11+
if zero2 != 0:
12+
x_pad = np.concatenate([x_pad, np.zeros(S - zero2)]) # 2.
13+
x_pad = np.concatenate([x_pad, np.zeros(L - S)])
14+
return x_pad
15+
16+
17+
"""
18+
# 確認
19+
x = np.ones(5)
20+
print(x)
21+
x_pad = zeropad(4, 2, x)
22+
print(x_pad)
23+
24+
25+
# [1. 1. 1. 1. 1.]
26+
# [0. 1. 1. 1. 1. 1. 0. 0. 0.]
27+
28+
# [1. 1. 1. 1. 1.]
29+
# [0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
30+
# 不足分が出ないように零詰め
31+
"""

khashimoto/chapter04/q02.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# フレーム分割
2+
3+
import numpy as np
4+
from q01 import zeropad
5+
6+
7+
def frame(L, S, x):
8+
x_pad = zeropad(L, S, x)
9+
T = (x_pad.size - L) // S + 1 # フレーム数
10+
x_t = np.zeros((T, L))
11+
for t in range(T):
12+
for l in range(L):
13+
x_t[t][l] = x_pad[t * S + l]
14+
return x_t
15+
16+
17+
"""
18+
# 確認
19+
x = np.ones(5)
20+
print(x)
21+
print(zeropad(4, 2, x))
22+
x_2 = frame(4, 2, x)
23+
print(x_2)
24+
25+
26+
# [1. 1. 1. 1. 1.]
27+
# [[0. 1. 1. 1.]
28+
# [1. 1. 1. 0.]]
29+
"""

khashimoto/chapter04/q03.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# STFTの実装
2+
3+
import numpy as np
4+
from q02 import frame
5+
6+
7+
def stft(L, S, w, x):
8+
x_t = frame(L, S, x)
9+
T = len(x_t)
10+
x_stft = np.zeros((T, L // 2 + 1), dtype=complex)
11+
for t in range(T):
12+
x_stft[t] = np.fft.rfft(x_t[t] * w)
13+
return x_stft

khashimoto/chapter04/q04.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# STFTの確認
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from q03 import stft
6+
7+
A = 1
8+
f = 440
9+
fs = 16000
10+
time = np.arange(fs * 0.1) / fs
11+
x = A * np.sin(2 * np.pi * f * time) # 正弦波
12+
13+
L = 1000
14+
S = 500
15+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
16+
x_stft = stft(L, S, w, x)
17+
18+
19+
# プロット
20+
T = np.arange(len(x_stft)) # 時間軸
21+
fr = np.arange(x_stft.shape[1]) / x_stft.shape[1] * fs / 2 # 周波数軸
22+
23+
plt.subplot(1, 2, 1)
24+
plt.pcolormesh(T, fr, abs(x_stft).T)
25+
plt.xlabel("Time[s]")
26+
plt.ylabel("Frequency[Hz]")
27+
plt.title("Amplitude spectrum")
28+
plt.subplot(1, 2, 2)
29+
plt.pcolormesh(T, fr, np.angle(x_stft).T)
30+
plt.xlabel("Time[s]")
31+
plt.ylabel("Frequency[kHz]")
32+
plt.title("Phase spectrum")
33+
plt.show()

khashimoto/chapter04/q05.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# 合成窓
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
6+
7+
def window(S, w):
8+
L = w.size
9+
Q = L // S # 1.
10+
w_s = np.zeros(L)
11+
for l in range(L):
12+
sum = 0
13+
for m in range(-(Q - 1), Q):
14+
if 0 <= l - m * S < L:
15+
sum += w[l - m * S] ** 2 # 2.
16+
w_s[l] = w[l] / sum
17+
return w_s
18+
19+
20+
"""
21+
# 確認
22+
L = 1024
23+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
24+
plt.plot(window(256, w))
25+
plt.show()
26+
27+
28+
# [0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.33333333]
29+
"""

khashimoto/chapter04/q06.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ISTFTの実装
2+
3+
import numpy as np
4+
from q05 import window
5+
6+
7+
def istft(S, X):
8+
F = len(X)
9+
T = X.shape[1]
10+
11+
# 1.
12+
N = 2 * (F - 1)
13+
M = S * (T - 1) + N
14+
15+
# 2.
16+
x = np.zeros(M)
17+
18+
# 3.
19+
z = np.zeros((N, T))
20+
for t in range(T):
21+
z[:, t] = np.fft.irfft(X[:, t])
22+
23+
# 4.
24+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(N) / (N - 1)) # Hamming窓
25+
w_s = window(S, w)
26+
n = np.arange(N)
27+
for t in range(T):
28+
x[t * S + n] = x[t * S + n] + w_s[n] * z[n, t]
29+
30+
return x

khashimoto/chapter04/q07.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# ISTFTの確認
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from q06 import istft
6+
from q03 import stft
7+
8+
A = 1
9+
f = 440
10+
fs = 16000
11+
time = np.arange(fs * 0.1) / fs
12+
x = A * np.sin(2 * np.pi * f * time) # 正弦波
13+
14+
L = 1000
15+
S = 500
16+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
17+
x_stft = stft(L, S, w, x) # 4. の結果
18+
19+
x_istft = istft(S, x_stft.T)
20+
21+
plt.plot(x_istft)
22+
plt.show()

khashimoto/chapter04/q08.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# 合成窓の確認
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from q03 import stft
6+
7+
8+
def istft_2(S, X):
9+
F = len(X)
10+
T = X.shape[1]
11+
12+
# 1.
13+
N = 2 * (F - 1)
14+
M = S * (T - 1) + N
15+
16+
# 2.
17+
x = np.zeros(M)
18+
19+
# 3.
20+
z = np.zeros((N, T))
21+
for t in range(T):
22+
z[:, t] = np.fft.irfft(X[:, t])
23+
24+
# 4.
25+
n = np.arange(N)
26+
for t in range(T):
27+
x[t * S + n] = x[t * S + n] + 1 * z[n, t] # w_s[n] = 1
28+
29+
return x
30+
31+
32+
A = 1
33+
f = 440
34+
fs = 16000
35+
time = np.arange(fs * 0.1) / fs
36+
x = A * np.sin(2 * np.pi * f * time) # 正弦波
37+
38+
L = 1000
39+
S = 500
40+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
41+
x_stft = stft(L, S, w, x) # 4. の結果
42+
43+
x_istft = istft_2(S, x_stft.T)
44+
45+
plt.plot(x_istft)
46+
plt.show()

khashimoto/chapter04/q09.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# 不確定性原理の確認
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from scipy.signal import chirp
6+
from q03 import stft
7+
8+
fs = 16000
9+
t = np.arange(0, fs) / fs
10+
sig = chirp(t, f0=100, f1=16000, t1=1)
11+
12+
# スペクトログラムのプロット
13+
14+
# 100/50
15+
L = 100
16+
S = 50
17+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
18+
sig_stft = stft(L, S, w, sig)
19+
20+
plt.subplot(4, 2, 1)
21+
plt.pcolormesh(abs(sig_stft).T)
22+
plt.title("Amplitude spectrum (100/50)")
23+
plt.subplot(4, 2, 2)
24+
plt.pcolormesh(np.angle(sig_stft).T)
25+
plt.title("Phase spectrum (100/50)")
26+
27+
# 200/100
28+
L = 200
29+
S = 100
30+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
31+
sig_stft = stft(L, S, w, sig)
32+
33+
plt.subplot(4, 2, 3)
34+
plt.pcolormesh(abs(sig_stft).T)
35+
plt.title("Amplitude spectrum (200/100)")
36+
plt.subplot(4, 2, 4)
37+
plt.pcolormesh(np.angle(sig_stft).T)
38+
plt.title("Phase spectrum (200/100)")
39+
40+
# 400/200
41+
L = 400
42+
S = 200
43+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
44+
sig_stft = stft(L, S, w, sig)
45+
46+
plt.subplot(4, 2, 5)
47+
plt.pcolormesh(abs(sig_stft).T)
48+
plt.title("Amplitude spectrum (400/200)")
49+
plt.subplot(4, 2, 6)
50+
plt.pcolormesh(np.angle(sig_stft).T)
51+
plt.title("Phase spectrum (400/200)")
52+
53+
# 800/400
54+
L = 800
55+
S = 400
56+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
57+
sig_stft = stft(L, S, w, sig)
58+
59+
plt.subplot(4, 2, 7)
60+
plt.pcolormesh(abs(sig_stft).T)
61+
plt.title("Amplitude spectrum (800/400)")
62+
plt.subplot(4, 2, 8)
63+
plt.pcolormesh(np.angle(sig_stft).T)
64+
plt.title("Phase spectrum (800/400)")
65+
plt.show()

khashimoto/chapter04/q10.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# 時間周波数のインデクスと物理量との対応
2+
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from q03 import stft
6+
7+
8+
def convert(x, fs, S):
9+
L = (len(x) - 1) * 2
10+
f = np.arange(len(x)) * fs / L
11+
t = np.arange(x.shape[1]) * S / fs
12+
return f, t
13+
14+
15+
# 4. の結果を再度プロット
16+
A = 1
17+
f = 440
18+
fs = 16000
19+
time = np.arange(fs * 0.1) / fs
20+
x = A * np.sin(2 * np.pi * f * time) # 正弦波
21+
22+
L = 1000
23+
S = 500
24+
w = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(L) / (L - 1)) # Hamming窓
25+
x_stft = stft(L, S, w, x)
26+
27+
28+
# プロット
29+
fr, t = convert(x_stft.T, fs, S)
30+
31+
plt.subplot(1, 2, 1)
32+
plt.pcolormesh(t, fr, abs(x_stft).T)
33+
plt.xlabel("Time[s]")
34+
plt.ylabel("Frequency[Hz]")
35+
plt.title("Amplitude spectrum")
36+
plt.subplot(1, 2, 2)
37+
plt.pcolormesh(t, fr, np.angle(x_stft).T)
38+
plt.xlabel("Time[s]")
39+
plt.ylabel("Frequency[Hz]")
40+
plt.title("Phase spectrum")
41+
plt.show()

0 commit comments

Comments
 (0)