Skip to content

Commit bb36d66

Browse files
authored
Merge pull request #26 from kuu8902/kkoiso/chapter05
5章前半を追加 小磯
2 parents ce157b3 + 1399fdd commit bb36d66

File tree

10 files changed

+317
-0
lines changed

10 files changed

+317
-0
lines changed

kkoiso/chapter05/q01.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import numpy as np
2+
3+
4+
def array_manifold_vector_linear(d, M, theta, f, c=334):
5+
theta_rad = np.deg2rad(theta)
6+
u = np.array([np.sin(theta_rad), np.cos(theta_rad), 0])
7+
a = np.zeros(M, dtype=complex)
8+
for m in range(M):
9+
p_m = np.array([((m - 1) - (M - 1) / 2) * d, 0, 0])
10+
a[m] = np.exp(1j * 2 * np.pi * f / c * np.dot(u, p_m))
11+
return a
12+
13+
14+
d = 0.05
15+
M = 3
16+
theta = 45
17+
f = 1000
18+
19+
20+
a_linear = array_manifold_vector_linear(d, M, theta, f)
21+
print(a_linear)

kkoiso/chapter05/q02.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import numpy as np
2+
3+
4+
def array_manifold_vector_circular(r, M, theta, f, c=334):
5+
theta_rad = np.deg2rad(theta)
6+
u = np.array([np.sin(theta_rad), np.cos(theta_rad), 0])
7+
a = np.zeros(M, dtype=complex)
8+
for m in range(M):
9+
p_m = np.array(
10+
[r * np.sin(2 * np.pi * m / M), r * np.cos(2 * np.pi * m / M), 0]
11+
)
12+
a[m] = np.exp(1j * 2 * np.pi * f / c * np.dot(u, p_m))
13+
return a
14+
15+
16+
r = 0.05
17+
M = 3
18+
theta = 45
19+
f = 1000
20+
21+
22+
a_circular = array_manifold_vector_circular(r, M, theta, f)
23+
print(a_circular)

kkoiso/chapter05/q03.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import numpy as np
2+
3+
4+
def array_manifold_vector_general(array_add, theta, f, c=334):
5+
theta_rad = np.deg2rad(theta)
6+
u = np.array([np.sin(theta_rad), np.cos(theta_rad), 0])
7+
M = len(array_add)
8+
a = np.zeros(M, dtype=complex)
9+
for m in range(M):
10+
p_m = np.array([array_add[m][0], array_add[m][1], 0])
11+
a[m] = np.exp(1j * 2 * np.pi * f / c * np.dot(u, p_m))
12+
return a
13+
14+
15+
d = 0.05
16+
M = 3
17+
theta = 45
18+
f = 1000
19+
linear_add = [((m - 1) * d, 0) for m in range(M)]
20+
21+
r = 0.05
22+
circular_add = [
23+
(r * np.sin(2 * np.pi * m / M), r * np.cos(2 * np.pi * m / M)) for m in range(M)
24+
]
25+
26+
27+
a_linear_general = array_manifold_vector_general(linear_add, theta, f)
28+
print(a_linear_general)
29+
30+
a_circular_general = array_manifold_vector_general(circular_add, theta, f)
31+
print(a_circular_general)

kkoiso/chapter05/q04.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import numpy as np
2+
3+
4+
def spatial_correlation_matrix(X):
5+
M, F, T = X.shape
6+
R = np.zeros((F, M, M), dtype=complex)
7+
for f in range(F):
8+
for t in range(T):
9+
x_ft = X[:, f, t]
10+
R[f] += np.power(t, T - 1) * x_ft * np.conj(x_ft).T
11+
R[f] /= T
12+
return R
13+
14+
15+
X1 = np.array([[1, -1j, -1, 1j], [2, -2j, -2, 2j], [3, -3j, -3, 3j]])
16+
X2 = np.array([[4, -2j, 1, 0], [2, -1j, 0, 0], [1, -1j, 1, 0]])
17+
X = np.stack((X1, X2), axis=0)
18+
19+
20+
R = spatial_correlation_matrix(X)
21+
print(R)

kkoiso/chapter05/q05.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import numpy as np
2+
from scipy.signal import stft
3+
import matplotlib.pyplot as plt
4+
from q04 import spatial_correlation_matrix
5+
6+
fs = 16000
7+
T = 5
8+
N = fs * T
9+
np.random.seed(0)
10+
white_noise = np.random.normal(0, 1, (2, N))
11+
12+
f, t, Zxx1 = stft(white_noise[0], fs, window="hann", nperseg=512, noverlap=256)
13+
f, t, Zxx2 = stft(white_noise[1], fs, window="hann", nperseg=512, noverlap=256)
14+
X = np.stack((Zxx1, Zxx2), axis=0)
15+
16+
17+
R = spatial_correlation_matrix(X)
18+
19+
20+
print(R[100].real)

kkoiso/chapter05/q06.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
4+
5+
fs = 16000
6+
T = 1
7+
N = fs * T
8+
t = np.linspace(0, T, N, endpoint=False)
9+
f = 440
10+
a = 1
11+
12+
s = a * np.sin(2 * np.pi * f * t)
13+
14+
15+
np.random.seed(0)
16+
noise = np.random.normal(0, 1, N)
17+
SNR = 10
18+
noise_amplitude = a / (10 ** (SNR / 20))
19+
epsilon = noise_amplitude * noise
20+
21+
22+
x1 = s + epsilon
23+
x2 = np.roll(s, 10) + epsilon
24+
x3 = np.roll(s, 20) + epsilon
25+
26+
x = x1 + x2 + x3
27+
plt.figure(figsize=(10, 6))
28+
plt.plot(t[: int(0.01 * fs)], x[: int(0.01 * fs)])
29+
plt.xlabel("Time [s]")
30+
plt.ylabel("Amplitude")
31+
plt.title("Multichannel Signals")
32+
plt.legend()
33+
plt.show()

kkoiso/chapter05/q07.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from scipy.signal import istft, stft
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
5+
fs = 16000
6+
T = 1
7+
N = fs * T
8+
t = np.linspace(0, T, N, endpoint=False)
9+
f = 440
10+
a = 1
11+
12+
s = a * np.sin(2 * np.pi * f * t)
13+
14+
15+
np.random.seed(0)
16+
noise = np.random.normal(0, 1, N)
17+
SNR = 10
18+
noise_amplitude = a / (10 ** (SNR / 20))
19+
epsilon = noise_amplitude * noise
20+
x = (s + np.roll(s, 10) + np.roll(s, 20)) / 3
21+
22+
x1 = s + epsilon
23+
x2 = np.roll(s, 10) + epsilon
24+
x3 = np.roll(s, 20) + epsilon
25+
26+
27+
f, t, X1 = stft(x1, fs, window="hann", nperseg=1024, noverlap=512)
28+
f, t, X2 = stft(x2, fs, window="hann", nperseg=1024, noverlap=512)
29+
f, t, X3 = stft(x3, fs, window="hann", nperseg=1024, noverlap=512)
30+
31+
X = np.stack((X1, X2, X3), axis=0)
32+
F, T = X1.shape
33+
34+
35+
tau = np.array([0, 10 / fs, 20 / fs])
36+
Y = np.zeros((F, T), dtype=complex)
37+
for f in range(F):
38+
w_f = 1 / 3 * np.exp(-1j * 2 * np.pi * f * tau[:, None] * fs / 2 / F)
39+
for t in range(T):
40+
x_ft = X[:, f, t]
41+
Y[f, t] = np.conj(w_f.T).dot(x_ft)
42+
43+
44+
_, y = istft(Y, fs, window="hann", nperseg=1024, noverlap=512)
45+
t = np.linspace(0, 1, 1 * fs, endpoint=False)
46+
47+
48+
plt.figure(figsize=(10, 6))
49+
plt.plot(t[: int(0.01 * fs)], y[: int(0.01 * fs)])
50+
plt.xlim(0, 0.01)
51+
plt.xlabel("Time [s]")
52+
plt.ylabel("Amplitude")
53+
plt.title("Enhanced Signal by Delay Sum Beamformer")
54+
plt.show()

kkoiso/chapter05/q08.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from scipy.signal import istft, stft
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
from q03 import array_manifold_vector_general
5+
6+
7+
def plot_beam_pattern(w_f, p, fs):
8+
fs_2 = fs / 2
9+
angles = np.linspace(0, 360, 361)
10+
F = w_f.shape[0]
11+
Psi = np.zeros((F, len(angles)), dtype=complex)
12+
for f in range(F):
13+
for i, theta in enumerate(angles):
14+
a_f_theta = array_manifold_vector_general(p, theta, f * (fs_2 / (F - 1)))
15+
Psi[f, i] = np.conj(w_f[f]).dot(a_f_theta)
16+
plt.figure(figsize=(10, 6))
17+
plt.imshow(20 * np.log10(np.abs(Psi)), aspect="auto", extent=[0, 360, 0, fs / 2])
18+
plt.colorbar(label="Amplitude [dB]")
19+
plt.xlabel("Angle [degrees]")
20+
plt.ylabel("Frequency [Hz]")
21+
plt.title("Beam Pattern")
22+
plt.show()
23+
24+
25+
d = 0.05
26+
M = 3
27+
theta = 45
28+
F = 1000
29+
linear_coords = [((m - 1) * d, 0) for m in range(M)]
30+
fs = 16000
31+
32+
33+
w_f = np.zeros((F, M), dtype=complex)
34+
for f in range(F):
35+
fs_2 = fs / 2
36+
tau = np.array([0, 10 / fs, 20 / fs])
37+
w_f[f] = 1 / 3 * np.exp(-1j * 2 * np.pi * f * tau * fs_2 / (F - 1))
38+
39+
40+
plot_beam_pattern(w_f, linear_coords, fs)

kkoiso/chapter05/q09.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from q08 import plot_beam_pattern
4+
5+
6+
M = 3
7+
theta = 45
8+
F = 1000
9+
fs = 16000
10+
11+
12+
for d in [0.02, 0.05, 0.10]:
13+
linear_coords = [((m - 1) * d, 0) for m in range(M)]
14+
w_f = np.zeros((F, M), dtype=complex)
15+
for f in range(F):
16+
tau = np.array([0, 10 / fs, 20 / fs])
17+
fs_2 = fs / 2
18+
w_f[f] = 1 / 3 * np.exp(-1j * 2 * np.pi * f * tau * fs_2 / (F - 1))
19+
plot_beam_pattern(w_f, linear_coords, fs)

kkoiso/chapter05/q10.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from scipy.signal import stft
4+
from q04 import spatial_correlation_matrix
5+
from q01 import array_manifold_vector_linear
6+
7+
8+
def compute_spatial_spectrum(z, p, fs):
9+
F, T, Z = stft(z, fs, window="hann", nperseg=1024, noverlap=512)
10+
angles = np.linspace(0, 360, 361)
11+
P = np.zeros((31, len(angles)))
12+
R_z = spatial_correlation_matrix(Z)
13+
tau = np.array([0, 10 / fs, 20 / fs])
14+
15+
for i, theta in enumerate(angles):
16+
w = 1 / 3 * np.exp(-1j * 2 * np.pi * theta * tau)
17+
for f_bin in range(20, 31):
18+
P[f_bin, i] = np.abs(np.conj(w.T).dot(R_z[f_bin]).dot(w))
19+
20+
plt.figure(figsize=(10, 6))
21+
for f_bin in range(20, 31):
22+
plt.plot(angles, 20 * np.log10(P[f_bin, :]), label=f"Frequency bin {f_bin}")
23+
plt.xlabel("Angle [degrees]")
24+
plt.ylabel("20log10|P(θ)|")
25+
plt.title("Spatial Spectrum")
26+
plt.legend()
27+
plt.show()
28+
29+
30+
fs = 16000
31+
T = 1
32+
N = fs * T
33+
t = np.linspace(0, T, N, endpoint=False)
34+
f = 440
35+
a = 1
36+
37+
s = a * np.sin(2 * np.pi * f * t)
38+
39+
np.random.seed(0)
40+
noise = np.random.normal(0, 1, N)
41+
SNR = 10
42+
noise_amplitude = a / (10 ** (SNR / 20))
43+
epsilon = noise_amplitude * noise
44+
45+
x1 = s + epsilon
46+
x2 = np.roll(s, 10) + epsilon
47+
x3 = np.roll(s, 20) + epsilon
48+
x = np.array([x1, x2, x3])
49+
50+
51+
d = 0.05
52+
M = 3
53+
linear_coords = [(m * d, 0) for m in range(M)]
54+
55+
compute_spatial_spectrum(x, linear_coords, fs)

0 commit comments

Comments
 (0)