-
Notifications
You must be signed in to change notification settings - Fork 419
/
doa_algorithms.py
125 lines (95 loc) · 4.16 KB
/
doa_algorithms.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
# -*- coding: utf-8 -*-
"""
DOA Algorithms
==============
This example demonstrates how to use the DOA object to perform direction of arrival
finding in 2D using one of several algorithms
- MUSIC [1]_
- SRP-PHAT [2]_
- CSSM [3]_
- WAVES [4]_
- TOPS [5]_
- FRIDA [6]_
.. [1] R. Schmidt, *Multiple emitter location and signal parameter estimation*,
IEEE Trans. Antennas Propag., Vol. 34, Num. 3, pp 276--280, 1986
.. [2] J. H. DiBiase, J H, *A high-accuracy, low-latency technique for talker localization
in reverberant environments using microphone arrays*, PHD Thesis, Brown University, 2000
.. [3] H. Wang, M. Kaveh, *Coherent signal-subspace processing for the detection and
estimation of angles of arrival of multiple wide-band sources*, IEEE Trans. Acoust.,
Speech, Signal Process., Vol. 33, Num. 4, pp 823--831, 1985
.. [4] E. D. di Claudio, R. Parisi, *WAVES: Weighted average of signal subspaces for
robust wideband direction finding*, IEEE Trans. Signal Process., Vol. 49, Num. 10,
2179--2191, 2001
.. [5] Y. Yeo-Sun, L. M. Kaplan, J. H. McClellan, *TOPS: New DOA estimator for wideband
signals*, IEEE Trans. Signal Process., Vol. 54, Num 6., pp 1977--1989, 2006
.. [6] H. Pan, R. Scheibler, E. Bezzam, I. Dokmanić, and M. Vetterli, *FRIDA:
FRI-based DOA estimation for arbitrary array layouts*, Proc. ICASSP,
pp 3186-3190, 2017
In this example, we generate some random signal for a source in the far field
and then simulate propagation using a fractional delay filter bank
corresponding to the relative microphone delays.
Then we perform DOA estimation and compare the errors for different algorithms
"""
import numpy as np
from scipy.signal import fftconvolve
import matplotlib.pyplot as plt
import pyroomacoustics as pra
from pyroomacoustics.doa import circ_dist
######
# We define a meaningful distance measure on the circle
# Location of original source
azimuth = 61.0 / 180.0 * np.pi # 60 degrees
distance = 3.0 # 3 meters
dim = 2 # dimensions (2 or 3)
room_dim = np.r_[10.0, 10.0]
# Use AnechoicRoom or ShoeBox implementation. The results are equivalent because max_order=0 for both.
# The plots change a little because in one case there are no walls.
use_anechoic_class = True
print("============ Using anechoic: {} ==================".format(anechoic))
#######################
# algorithms parameters
SNR = 0.0 # signal-to-noise ratio
c = 343.0 # speed of sound
fs = 16000 # sampling frequency
nfft = 256 # FFT size
freq_bins = np.arange(5, 60) # FFT bins to use for estimation
# compute the noise variance
sigma2 = 10 ** (-SNR / 10) / (4.0 * np.pi * distance) ** 2
# Create an anechoic room
if use_anechoic_class:
aroom = pra.AnechoicRoom(dim, fs=fs, sigma2_awgn=sigma2)
else:
aroom = pra.ShoeBox(room_dim, fs=fs, max_order=0, sigma2_awgn=sigma2)
# add the source
source_location = room_dim / 2 + distance * np.r_[np.cos(azimuth), np.sin(azimuth)]
source_signal = np.random.randn((nfft // 2 + 1) * nfft)
aroom.add_source(source_location, signal=source_signal)
# We use a circular array with radius 15 cm # and 12 microphones
R = pra.circular_2D_array(room_dim / 2, 12, 0.0, 0.15)
aroom.add_microphone_array(pra.MicrophoneArray(R, fs=aroom.fs))
# run the simulation
aroom.simulate()
################################
# Compute the STFT frames needed
X = np.array(
[
pra.transform.stft.analysis(signal, nfft, nfft // 2).T
for signal in aroom.mic_array.signals
]
)
##############################################
# Now we can test all the algorithms available
algo_names = sorted(pra.doa.algorithms.keys())
for algo_name in algo_names:
# Construct the new DOA object
# the max_four parameter is necessary for FRIDA only
doa = pra.doa.algorithms[algo_name](R, fs, nfft, c=c, max_four=4)
# this call here perform localization on the frames in X
doa.locate_sources(X, freq_bins=freq_bins)
doa.polar_plt_dirac()
plt.title(algo_name)
# doa.azimuth_recon contains the reconstructed location of the source
print(algo_name)
print(" Recovered azimuth:", doa.azimuth_recon / np.pi * 180.0, "degrees")
print(" Error:", circ_dist(azimuth, doa.azimuth_recon) / np.pi * 180.0, "degrees")
plt.show()