OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2016 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 #include <vector> | |
11 | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 #include "webrtc/base/array_view.h" | |
14 #include "webrtc/modules/audio_processing/audio_buffer.h" | |
15 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h" | |
16 #include "webrtc/modules/audio_processing/test/audio_buffer_tools.h" | |
17 #include "webrtc/modules/audio_processing/test/bitexactness_tools.h" | |
18 | |
19 namespace webrtc { | |
20 namespace { | |
21 | |
22 const int kNumFramesToProcess = 100; | |
23 | |
24 void SetupComponent(int sample_rate_hz, | |
25 EchoCancellation::SuppressionLevel suppression_level, | |
26 bool drift_compensation_enabled, | |
27 EchoCancellationImpl* echo_canceller) { | |
28 echo_canceller->Initialize(sample_rate_hz, 1, 1, 1); | |
29 EchoCancellation* ec = static_cast<EchoCancellation*>(echo_canceller); | |
30 ec->Enable(true); | |
31 ec->set_suppression_level(suppression_level); | |
32 ec->enable_drift_compensation(drift_compensation_enabled); | |
33 | |
34 Config config; | |
35 config.Set<DelayAgnostic>(new DelayAgnostic(true)); | |
36 config.Set<ExtendedFilter>(new ExtendedFilter(true)); | |
37 echo_canceller->SetExtraOptions(config); | |
38 } | |
39 | |
40 void ProcessOneFrame(int sample_rate_hz, | |
41 int stream_delay_ms, | |
42 bool drift_compensation_enabled, | |
43 int stream_drift_samples, | |
44 AudioBuffer* render_audio_buffer, | |
45 AudioBuffer* capture_audio_buffer, | |
46 EchoCancellationImpl* echo_canceller) { | |
47 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { | |
48 render_audio_buffer->SplitIntoFrequencyBands(); | |
49 capture_audio_buffer->SplitIntoFrequencyBands(); | |
50 } | |
51 | |
52 echo_canceller->ProcessRenderAudio(render_audio_buffer); | |
53 | |
54 if (drift_compensation_enabled) { | |
55 static_cast<EchoCancellation*>(echo_canceller) | |
56 ->set_stream_drift_samples(stream_drift_samples); | |
57 } | |
58 | |
59 echo_canceller->ProcessCaptureAudio(capture_audio_buffer, stream_delay_ms); | |
60 | |
61 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { | |
62 capture_audio_buffer->MergeFrequencyBands(); | |
63 } | |
64 } | |
65 | |
66 void RunBitexactnessTest(int sample_rate_hz, | |
67 size_t num_channels, | |
68 int stream_delay_ms, | |
69 bool drift_compensation_enabled, | |
70 int stream_drift_samples, | |
71 EchoCancellation::SuppressionLevel suppression_level, | |
72 bool stream_has_echo_reference, | |
73 const rtc::ArrayView<const float>& output_reference) { | |
74 rtc::CriticalSection crit_render; | |
75 rtc::CriticalSection crit_capture; | |
76 EchoCancellationImpl echo_canceller(&crit_render, &crit_capture); | |
77 SetupComponent(sample_rate_hz, suppression_level, drift_compensation_enabled, | |
78 &echo_canceller); | |
79 | |
80 const int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100); | |
81 const StreamConfig render_config(sample_rate_hz, num_channels, false); | |
82 AudioBuffer render_buffer( | |
83 render_config.num_frames(), render_config.num_channels(), | |
84 render_config.num_frames(), 1, render_config.num_frames()); | |
85 test::InputAudioFile render_file( | |
86 test::GetApmRenderTestVectorFileName(sample_rate_hz)); | |
87 std::vector<float> render_input(samples_per_channel * num_channels); | |
88 | |
89 const StreamConfig capture_config(sample_rate_hz, num_channels, false); | |
90 AudioBuffer capture_buffer( | |
91 capture_config.num_frames(), capture_config.num_channels(), | |
92 capture_config.num_frames(), 1, capture_config.num_frames()); | |
93 test::InputAudioFile capture_file( | |
94 test::GetApmCaptureTestVectorFileName(sample_rate_hz)); | |
95 std::vector<float> capture_input(samples_per_channel * num_channels); | |
96 | |
97 for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) { | |
98 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, | |
99 &render_file, render_input); | |
100 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, | |
101 &capture_file, capture_input); | |
102 | |
103 test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer); | |
104 test::CopyVectorToAudioBuffer(capture_config, capture_input, | |
105 &capture_buffer); | |
106 | |
107 ProcessOneFrame(sample_rate_hz, stream_delay_ms, drift_compensation_enabled, | |
108 stream_drift_samples, &render_buffer, &capture_buffer, | |
109 &echo_canceller); | |
110 } | |
111 | |
112 // Extract and verify the test results. | |
113 std::vector<float> capture_output; | |
114 test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer, | |
115 &capture_output); | |
116 | |
117 EXPECT_EQ(stream_has_echo_reference, | |
118 static_cast<EchoCancellation*>(&echo_canceller)->stream_has_echo()); | |
119 | |
120 // Compare the output with the reference. Only the first values of the output | |
121 // from last frame processed are compared in order not having to specify all | |
122 // preceeding frames as testvectors. As the algorithm being tested has a | |
123 // memory, testing only the last frame implicitly also tests the preceeding | |
124 // frames. | |
125 const float kElementErrorBound = 1.0f / 32768.0f; | |
126 EXPECT_TRUE(test::VerifyDeinterleavedArray( | |
127 capture_config.num_frames(), capture_config.num_channels(), | |
128 output_reference, capture_output, kElementErrorBound)); | |
129 } | |
130 | |
131 const bool kStreamHasEchoReference = false; | |
132 | |
133 } // namespace | |
134 | |
135 // TODO(peah): Activate all these tests for ARM and ARM64 once the issue on the | |
136 // Chromium ARM and ARM64 boths have been identified. This is tracked in the | |
137 // issue https://bugs.chromium.org/p/webrtc/issues/detail?id=5711. | |
138 | |
139 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
140 defined(WEBRTC_ANDROID)) | |
141 TEST(EchoCancellationBitExactnessTest, | |
142 Mono8kHz_HighLevel_NoDrift_StreamDelay0) { | |
143 #else | |
144 TEST(EchoCancellationBitExactnessTest, | |
145 DISABLED_Mono8kHz_HighLevel_NoDrift_StreamDelay0) { | |
146 #endif | |
147 const float kOutputReference[] = {-0.006622f, -0.002747f, 0.001587f}; | |
148 RunBitexactnessTest(8000, 1, 0, false, 0, | |
149 EchoCancellation::SuppressionLevel::kHighSuppression, | |
150 kStreamHasEchoReference, kOutputReference); | |
151 } | |
152 | |
153 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
154 defined(WEBRTC_ANDROID)) | |
155 TEST(EchoCancellationBitExactnessTest, | |
156 Mono16kHz_HighLevel_NoDrift_StreamDelay0) { | |
157 #else | |
158 TEST(EchoCancellationBitExactnessTest, | |
159 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay0) { | |
160 #endif | |
161 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
162 RunBitexactnessTest(16000, 1, 0, false, 0, | |
163 EchoCancellation::SuppressionLevel::kHighSuppression, | |
164 kStreamHasEchoReference, kOutputReference); | |
165 } | |
166 | |
167 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
168 defined(WEBRTC_ANDROID)) | |
169 TEST(EchoCancellationBitExactnessTest, | |
170 Mono32kHz_HighLevel_NoDrift_StreamDelay0) { | |
171 #else | |
172 TEST(EchoCancellationBitExactnessTest, | |
173 DISABLED_Mono32kHz_HighLevel_NoDrift_StreamDelay0) { | |
174 #endif | |
175 const float kOutputReference[] = {-0.010162f, -0.009155f, -0.008301f}; | |
176 RunBitexactnessTest(32000, 1, 0, false, 0, | |
177 EchoCancellation::SuppressionLevel::kHighSuppression, | |
178 kStreamHasEchoReference, kOutputReference); | |
179 } | |
180 | |
181 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
182 defined(WEBRTC_ANDROID)) | |
183 TEST(EchoCancellationBitExactnessTest, | |
184 Mono48kHz_HighLevel_NoDrift_StreamDelay0) { | |
185 #else | |
186 TEST(EchoCancellationBitExactnessTest, | |
187 DISABLED_Mono48kHz_HighLevel_NoDrift_StreamDelay0) { | |
188 #endif | |
189 const float kOutputReference[] = {-0.009554f, -0.009857f, -0.009868f}; | |
190 RunBitexactnessTest(48000, 1, 0, false, 0, | |
191 EchoCancellation::SuppressionLevel::kHighSuppression, | |
192 kStreamHasEchoReference, kOutputReference); | |
193 } | |
194 | |
195 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
196 defined(WEBRTC_ANDROID)) | |
197 TEST(EchoCancellationBitExactnessTest, | |
198 Mono16kHz_LowLevel_NoDrift_StreamDelay0) { | |
199 #else | |
200 TEST(EchoCancellationBitExactnessTest, | |
201 DISABLED_Mono16kHz_LowLevel_NoDrift_StreamDelay0) { | |
202 #endif | |
203 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
204 RunBitexactnessTest(16000, 1, 0, false, 0, | |
205 EchoCancellation::SuppressionLevel::kLowSuppression, | |
206 kStreamHasEchoReference, kOutputReference); | |
207 } | |
208 | |
209 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
210 defined(WEBRTC_ANDROID)) | |
211 TEST(EchoCancellationBitExactnessTest, | |
212 Mono16kHz_ModerateLevel_NoDrift_StreamDelay0) { | |
213 #else | |
214 TEST(EchoCancellationBitExactnessTest, | |
215 DISABLED_Mono16kHz_ModerateLevel_NoDrift_StreamDelay0) { | |
216 #endif | |
217 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
218 RunBitexactnessTest(16000, 1, 0, false, 0, | |
219 EchoCancellation::SuppressionLevel::kModerateSuppression, | |
220 kStreamHasEchoReference, kOutputReference); | |
221 } | |
222 | |
223 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
224 defined(WEBRTC_ANDROID)) | |
225 TEST(EchoCancellationBitExactnessTest, | |
226 Mono16kHz_HighLevel_NoDrift_StreamDelay10) { | |
227 #else | |
228 TEST(EchoCancellationBitExactnessTest, | |
229 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay10) { | |
230 #endif | |
231 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
232 RunBitexactnessTest(16000, 1, 10, false, 0, | |
233 EchoCancellation::SuppressionLevel::kHighSuppression, | |
234 kStreamHasEchoReference, kOutputReference); | |
235 } | |
236 | |
237 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
238 defined(WEBRTC_ANDROID)) | |
239 TEST(EchoCancellationBitExactnessTest, | |
240 Mono16kHz_HighLevel_NoDrift_StreamDelay20) { | |
241 #else | |
242 TEST(EchoCancellationBitExactnessTest, | |
243 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay20) { | |
244 #endif | |
245 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
246 RunBitexactnessTest(16000, 1, 20, false, 0, | |
247 EchoCancellation::SuppressionLevel::kHighSuppression, | |
248 kStreamHasEchoReference, kOutputReference); | |
249 } | |
250 | |
251 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
252 defined(WEBRTC_ANDROID)) | |
253 TEST(EchoCancellationBitExactnessTest, | |
254 Mono16kHz_HighLevel_Drift0_StreamDelay0) { | |
255 #else | |
256 TEST(EchoCancellationBitExactnessTest, | |
257 DISABLED_Mono16kHz_HighLevel_Drift0_StreamDelay0) { | |
258 #endif | |
259 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
260 RunBitexactnessTest(16000, 1, 0, true, 0, | |
261 EchoCancellation::SuppressionLevel::kHighSuppression, | |
262 kStreamHasEchoReference, kOutputReference); | |
263 } | |
264 | |
265 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
266 defined(WEBRTC_ANDROID)) | |
267 TEST(EchoCancellationBitExactnessTest, | |
268 Mono16kHz_HighLevel_Drift5_StreamDelay0) { | |
269 #else | |
270 TEST(EchoCancellationBitExactnessTest, | |
271 DISABLED_Mono16kHz_HighLevel_Drift5_StreamDelay0) { | |
272 #endif | |
273 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; | |
274 RunBitexactnessTest(16000, 1, 0, true, 5, | |
275 EchoCancellation::SuppressionLevel::kHighSuppression, | |
276 kStreamHasEchoReference, kOutputReference); | |
277 } | |
278 | |
279 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
280 defined(WEBRTC_ANDROID)) | |
281 TEST(EchoCancellationBitExactnessTest, | |
282 Stereo8kHz_HighLevel_NoDrift_StreamDelay0) { | |
283 #else | |
284 TEST(EchoCancellationBitExactnessTest, | |
285 DISABLED_Stereo8kHz_HighLevel_NoDrift_StreamDelay0) { | |
286 #endif | |
287 const float kOutputReference[] = {-0.027359f, -0.015823f, -0.028488f, | |
288 -0.027359f, -0.015823f, -0.028488f}; | |
289 RunBitexactnessTest(8000, 2, 0, false, 0, | |
290 EchoCancellation::SuppressionLevel::kHighSuppression, | |
291 kStreamHasEchoReference, kOutputReference); | |
292 } | |
293 | |
294 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
295 defined(WEBRTC_ANDROID)) | |
296 TEST(EchoCancellationBitExactnessTest, | |
297 Stereo16kHz_HighLevel_NoDrift_StreamDelay0) { | |
298 #else | |
299 TEST(EchoCancellationBitExactnessTest, | |
300 DISABLED_Stereo16kHz_HighLevel_NoDrift_StreamDelay0) { | |
301 #endif | |
302 const float kOutputReference[] = {-0.027298f, -0.015900f, -0.028107f, | |
303 -0.027298f, -0.015900f, -0.028107f}; | |
304 RunBitexactnessTest(16000, 2, 0, false, 0, | |
305 EchoCancellation::SuppressionLevel::kHighSuppression, | |
306 kStreamHasEchoReference, kOutputReference); | |
307 } | |
308 | |
309 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
310 defined(WEBRTC_ANDROID)) | |
311 TEST(EchoCancellationBitExactnessTest, | |
312 Stereo32kHz_HighLevel_NoDrift_StreamDelay0) { | |
313 #else | |
314 TEST(EchoCancellationBitExactnessTest, | |
315 DISABLED_Stereo32kHz_HighLevel_NoDrift_StreamDelay0) { | |
316 #endif | |
317 const float kOutputReference[] = {0.004547f, -0.004456f, -0.000946f, | |
318 0.004547f, -0.004456f, -0.000946f}; | |
319 RunBitexactnessTest(32000, 2, 0, false, 0, | |
320 EchoCancellation::SuppressionLevel::kHighSuppression, | |
321 kStreamHasEchoReference, kOutputReference); | |
322 } | |
323 | |
324 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ | |
325 defined(WEBRTC_ANDROID)) | |
326 TEST(EchoCancellationBitExactnessTest, | |
327 Stereo48kHz_HighLevel_NoDrift_StreamDelay0) { | |
328 #else | |
329 TEST(EchoCancellationBitExactnessTest, | |
330 DISABLED_Stereo48kHz_HighLevel_NoDrift_StreamDelay0) { | |
331 #endif | |
332 const float kOutputReference[] = {-0.003500f, -0.001894f, -0.003176f, | |
333 -0.003500f, -0.001894f, -0.003176f}; | |
334 RunBitexactnessTest(48000, 2, 0, false, 0, | |
335 EchoCancellation::SuppressionLevel::kHighSuppression, | |
336 kStreamHasEchoReference, kOutputReference); | |
337 } | |
338 | |
339 } // namespace webrtc | |
OLD | NEW |