1/*
2 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#define _USE_MATH_DEFINES
12
13#include "webrtc/modules/audio_processing/beamformer/covariance_matrix_generator.h"
14
15#include <cmath>
16
17#include "testing/gtest/include/gtest/gtest.h"
18#include "webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h"
19
20namespace webrtc {
21
22using std::complex;
23
24TEST(CovarianceMatrixGeneratorTest, TestUniformCovarianceMatrix2Mics) {
25  const float kWaveNumber = 0.5775f;
26  const int kNumberMics = 2;
27  const float kMicSpacing = 0.05f;
28  const float kTolerance = 0.0001f;
29  std::vector<Point> geometry;
30  float first_mic = (kNumberMics - 1) * kMicSpacing / 2.f;
31  for (int i = 0; i < kNumberMics; ++i) {
32    geometry.push_back(Point(i * kMicSpacing - first_mic, 0.f, 0.f));
33  }
34  ComplexMatrix<float> actual_covariance_matrix(kNumberMics, kNumberMics);
35  CovarianceMatrixGenerator::UniformCovarianceMatrix(kWaveNumber,
36                                                     geometry,
37                                                     &actual_covariance_matrix);
38
39  complex<float>* const* actual_els = actual_covariance_matrix.elements();
40
41  EXPECT_NEAR(actual_els[0][0].real(), 1.f, kTolerance);
42  EXPECT_NEAR(actual_els[0][1].real(), 0.9998f, kTolerance);
43  EXPECT_NEAR(actual_els[1][0].real(), 0.9998f, kTolerance);
44  EXPECT_NEAR(actual_els[1][1].real(), 1.f, kTolerance);
45
46  EXPECT_NEAR(actual_els[0][0].imag(), 0.f, kTolerance);
47  EXPECT_NEAR(actual_els[0][1].imag(), 0.f, kTolerance);
48  EXPECT_NEAR(actual_els[1][0].imag(), 0.f, kTolerance);
49  EXPECT_NEAR(actual_els[1][1].imag(), 0.f, kTolerance);
50}
51
52TEST(CovarianceMatrixGeneratorTest, TestUniformCovarianceMatrix3Mics) {
53  const float kWaveNumber = 10.3861f;
54  const int kNumberMics = 3;
55  const float kMicSpacing = 0.04f;
56  const float kTolerance = 0.0001f;
57  std::vector<Point> geometry;
58  float first_mic = (kNumberMics - 1) * kMicSpacing / 2.f;
59  for (int i = 0; i < kNumberMics; ++i) {
60    geometry.push_back(Point(i * kMicSpacing - first_mic, 0.f, 0.f));
61  }
62  ComplexMatrix<float> actual_covariance_matrix(kNumberMics, kNumberMics);
63  CovarianceMatrixGenerator::UniformCovarianceMatrix(kWaveNumber,
64                                                     geometry,
65                                                     &actual_covariance_matrix);
66
67  complex<float>* const* actual_els = actual_covariance_matrix.elements();
68
69  EXPECT_NEAR(actual_els[0][0].real(), 1.f, kTolerance);
70  EXPECT_NEAR(actual_els[0][1].real(), 0.9573f, kTolerance);
71  EXPECT_NEAR(actual_els[0][2].real(), 0.8347f, kTolerance);
72  EXPECT_NEAR(actual_els[1][0].real(), 0.9573f, kTolerance);
73  EXPECT_NEAR(actual_els[1][1].real(), 1.f, kTolerance);
74  EXPECT_NEAR(actual_els[1][2].real(), 0.9573f, kTolerance);
75  EXPECT_NEAR(actual_els[2][0].real(), 0.8347f, kTolerance);
76  EXPECT_NEAR(actual_els[2][1].real(), 0.9573f, kTolerance);
77  EXPECT_NEAR(actual_els[2][2].real(), 1.f, kTolerance);
78
79  EXPECT_NEAR(actual_els[0][0].imag(), 0.f, kTolerance);
80  EXPECT_NEAR(actual_els[0][1].imag(), 0.f, kTolerance);
81  EXPECT_NEAR(actual_els[0][2].imag(), 0.f, kTolerance);
82  EXPECT_NEAR(actual_els[1][0].imag(), 0.f, kTolerance);
83  EXPECT_NEAR(actual_els[1][1].imag(), 0.f, kTolerance);
84  EXPECT_NEAR(actual_els[1][2].imag(), 0.f, kTolerance);
85  EXPECT_NEAR(actual_els[2][0].imag(), 0.f, kTolerance);
86  EXPECT_NEAR(actual_els[2][1].imag(), 0.f, kTolerance);
87  EXPECT_NEAR(actual_els[2][2].imag(), 0.f, kTolerance);
88}
89
90TEST(CovarianceMatrixGeneratorTest, TestUniformCovarianceMatrix3DArray) {
91  const float kWaveNumber = 1.2345f;
92  const int kNumberMics = 4;
93  const float kTolerance = 0.0001f;
94  std::vector<Point> geometry;
95  geometry.push_back(Point(-0.025f, -0.05f, -0.075f));
96  geometry.push_back(Point(0.075f, -0.05f, -0.075f));
97  geometry.push_back(Point(-0.025f, 0.15f, -0.075f));
98  geometry.push_back(Point(-0.025f, -0.05f, 0.225f));
99  ComplexMatrix<float> actual_covariance_matrix(kNumberMics, kNumberMics);
100  CovarianceMatrixGenerator::UniformCovarianceMatrix(kWaveNumber,
101                                                     geometry,
102                                                     &actual_covariance_matrix);
103
104  complex<float>* const* actual_els = actual_covariance_matrix.elements();
105
106  EXPECT_NEAR(actual_els[0][0].real(), 1.f, kTolerance);
107  EXPECT_NEAR(actual_els[0][1].real(), 0.9962f, kTolerance);
108  EXPECT_NEAR(actual_els[0][2].real(), 0.9848f, kTolerance);
109  EXPECT_NEAR(actual_els[0][3].real(), 0.9660f, kTolerance);
110  EXPECT_NEAR(actual_els[1][0].real(), 0.9962f, kTolerance);
111  EXPECT_NEAR(actual_els[1][1].real(), 1.f, kTolerance);
112  EXPECT_NEAR(actual_els[1][2].real(), 0.9810f, kTolerance);
113  EXPECT_NEAR(actual_els[1][3].real(), 0.9623f, kTolerance);
114  EXPECT_NEAR(actual_els[2][0].real(), 0.9848f, kTolerance);
115  EXPECT_NEAR(actual_els[2][1].real(), 0.9810f, kTolerance);
116  EXPECT_NEAR(actual_els[2][2].real(), 1.f, kTolerance);
117  EXPECT_NEAR(actual_els[2][3].real(), 0.9511f, kTolerance);
118  EXPECT_NEAR(actual_els[3][0].real(), 0.9660f, kTolerance);
119  EXPECT_NEAR(actual_els[3][1].real(), 0.9623f, kTolerance);
120  EXPECT_NEAR(actual_els[3][2].real(), 0.9511f, kTolerance);
121  EXPECT_NEAR(actual_els[3][3].real(), 1.f, kTolerance);
122
123  EXPECT_NEAR(actual_els[0][0].imag(), 0.f, kTolerance);
124  EXPECT_NEAR(actual_els[0][1].imag(), 0.f, kTolerance);
125  EXPECT_NEAR(actual_els[0][2].imag(), 0.f, kTolerance);
126  EXPECT_NEAR(actual_els[0][3].imag(), 0.f, kTolerance);
127  EXPECT_NEAR(actual_els[1][0].imag(), 0.f, kTolerance);
128  EXPECT_NEAR(actual_els[1][1].imag(), 0.f, kTolerance);
129  EXPECT_NEAR(actual_els[1][2].imag(), 0.f, kTolerance);
130  EXPECT_NEAR(actual_els[1][3].imag(), 0.f, kTolerance);
131  EXPECT_NEAR(actual_els[2][0].imag(), 0.f, kTolerance);
132  EXPECT_NEAR(actual_els[2][1].imag(), 0.f, kTolerance);
133  EXPECT_NEAR(actual_els[2][2].imag(), 0.f, kTolerance);
134  EXPECT_NEAR(actual_els[2][3].imag(), 0.f, kTolerance);
135  EXPECT_NEAR(actual_els[3][0].imag(), 0.f, kTolerance);
136  EXPECT_NEAR(actual_els[3][1].imag(), 0.f, kTolerance);
137  EXPECT_NEAR(actual_els[3][2].imag(), 0.f, kTolerance);
138  EXPECT_NEAR(actual_els[3][3].imag(), 0.f, kTolerance);
139}
140
141TEST(CovarianceMatrixGeneratorTest, TestAngledCovarianceMatrix2Mics) {
142  const float kSpeedOfSound = 340;
143  const float kAngle = static_cast<float>(M_PI) / 4.f;
144  const float kFrequencyBin = 6;
145  const float kFftSize = 512;
146  const int kNumberFrequencyBins = 257;
147  const int kSampleRate = 16000;
148  const int kNumberMics = 2;
149  const float kMicSpacing = 0.04f;
150  const float kTolerance = 0.0001f;
151  std::vector<Point> geometry;
152  float first_mic = (kNumberMics - 1) * kMicSpacing / 2.f;
153  for (int i = 0; i < kNumberMics; ++i) {
154    geometry.push_back(Point(i * kMicSpacing - first_mic, 0.f, 0.f));
155  }
156  ComplexMatrix<float> actual_covariance_matrix(kNumberMics, kNumberMics);
157  CovarianceMatrixGenerator::AngledCovarianceMatrix(kSpeedOfSound,
158                                                    kAngle,
159                                                    kFrequencyBin,
160                                                    kFftSize,
161                                                    kNumberFrequencyBins,
162                                                    kSampleRate,
163                                                    geometry,
164                                                    &actual_covariance_matrix);
165
166  complex<float>* const* actual_els = actual_covariance_matrix.elements();
167
168  EXPECT_NEAR(actual_els[0][0].real(), 0.5f, kTolerance);
169  EXPECT_NEAR(actual_els[0][1].real(), 0.4976f, kTolerance);
170  EXPECT_NEAR(actual_els[1][0].real(), 0.4976f, kTolerance);
171  EXPECT_NEAR(actual_els[1][1].real(), 0.5f, kTolerance);
172
173  EXPECT_NEAR(actual_els[0][0].imag(), 0.f, kTolerance);
174  EXPECT_NEAR(actual_els[0][1].imag(), 0.0489f, kTolerance);
175  EXPECT_NEAR(actual_els[1][0].imag(), -0.0489f, kTolerance);
176  EXPECT_NEAR(actual_els[1][1].imag(), 0.f, kTolerance);
177}
178
179TEST(CovarianceMatrixGeneratorTest, TestAngledCovarianceMatrix3Mics) {
180  const float kSpeedOfSound = 340;
181  const float kAngle = static_cast<float>(M_PI) / 4.f;
182  const float kFrequencyBin = 9;
183  const float kFftSize = 512;
184  const int kNumberFrequencyBins = 257;
185  const int kSampleRate = 42000;
186  const int kNumberMics = 3;
187  const float kMicSpacing = 0.05f;
188  const float kTolerance = 0.0001f;
189  std::vector<Point> geometry;
190  float first_mic = (kNumberMics - 1) * kMicSpacing / 2.f;
191  for (int i = 0; i < kNumberMics; ++i) {
192    geometry.push_back(Point(i * kMicSpacing - first_mic, 0.f, 0.f));
193  }
194  ComplexMatrix<float> actual_covariance_matrix(kNumberMics, kNumberMics);
195  CovarianceMatrixGenerator::AngledCovarianceMatrix(kSpeedOfSound,
196                                                    kAngle,
197                                                    kFrequencyBin,
198                                                    kFftSize,
199                                                    kNumberFrequencyBins,
200                                                    kSampleRate,
201                                                    geometry,
202                                                    &actual_covariance_matrix);
203
204  complex<float>* const* actual_els = actual_covariance_matrix.elements();
205
206  EXPECT_NEAR(actual_els[0][0].real(), 0.3333f, kTolerance);
207  EXPECT_NEAR(actual_els[0][1].real(), 0.2953f, kTolerance);
208  EXPECT_NEAR(actual_els[0][2].real(), 0.1899f, kTolerance);
209  EXPECT_NEAR(actual_els[1][0].real(), 0.2953f, kTolerance);
210  EXPECT_NEAR(actual_els[1][1].real(), 0.3333f, kTolerance);
211  EXPECT_NEAR(actual_els[1][2].real(), 0.2953f, kTolerance);
212  EXPECT_NEAR(actual_els[2][0].real(), 0.1899f, kTolerance);
213  EXPECT_NEAR(actual_els[2][1].real(), 0.2953f, kTolerance);
214  EXPECT_NEAR(actual_els[2][2].real(), 0.3333f, kTolerance);
215
216  EXPECT_NEAR(actual_els[0][0].imag(), 0.f, kTolerance);
217  EXPECT_NEAR(actual_els[0][1].imag(), 0.1546f, kTolerance);
218  EXPECT_NEAR(actual_els[0][2].imag(), 0.274f, kTolerance);
219  EXPECT_NEAR(actual_els[1][0].imag(), -0.1546f, kTolerance);
220  EXPECT_NEAR(actual_els[1][1].imag(), 0.f, kTolerance);
221  EXPECT_NEAR(actual_els[1][2].imag(), 0.1546f, kTolerance);
222  EXPECT_NEAR(actual_els[2][0].imag(), -0.274f, kTolerance);
223  EXPECT_NEAR(actual_els[2][1].imag(), -0.1546f, kTolerance);
224  EXPECT_NEAR(actual_els[2][2].imag(), 0.f, kTolerance);
225}
226
227// PhaseAlignmentMasks is tested by AngledCovarianceMatrix and by
228// InitBeamformerWeights in BeamformerUnittest.
229
230}  // namespace webrtc
231