blob: a79a03d5dc84a2b69aaf98d16d0932c998012479 [file] [log] [blame]
peahd4f6ea72016-03-29 00:37:44 -07001/*
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
peahd4f6ea72016-03-29 00:37:44 -070019namespace webrtc {
20namespace {
21
22const int kNumFramesToProcess = 100;
23
24void 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
40void 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
66void 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.
peah7ea928e2016-03-30 08:13:57 -0700125 const float kElementErrorBound = 1.0f / 32768.0f;
126 EXPECT_TRUE(test::VerifyDeinterleavedArray(
peahd4f6ea72016-03-29 00:37:44 -0700127 capture_config.num_frames(), capture_config.num_channels(),
peah7ea928e2016-03-30 08:13:57 -0700128 output_reference, capture_output, kElementErrorBound));
peahd4f6ea72016-03-29 00:37:44 -0700129}
130
131const bool kStreamHasEchoReference = false;
132
133} // namespace
134
135// TODO(peah): Activate all these tests for ARM and ARM64 once the issue on the
peah51fbdd62016-03-30 14:58:32 -0700136// 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.
peahd4f6ea72016-03-29 00:37:44 -0700138
peah51fbdd62016-03-30 14:58:32 -0700139#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
140 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700141TEST(EchoCancellationBitExactnessTest,
142 Mono8kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700143#else
144TEST(EchoCancellationBitExactnessTest,
145 DISABLED_Mono8kHz_HighLevel_NoDrift_StreamDelay0) {
146#endif
peahd4f6ea72016-03-29 00:37:44 -0700147 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
peah51fbdd62016-03-30 14:58:32 -0700153#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
154 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700155TEST(EchoCancellationBitExactnessTest,
156 Mono16kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700157#else
158TEST(EchoCancellationBitExactnessTest,
159 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay0) {
160#endif
peahd4f6ea72016-03-29 00:37:44 -0700161 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
peah51fbdd62016-03-30 14:58:32 -0700167#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
168 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700169TEST(EchoCancellationBitExactnessTest,
170 Mono32kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700171#else
172TEST(EchoCancellationBitExactnessTest,
173 DISABLED_Mono32kHz_HighLevel_NoDrift_StreamDelay0) {
174#endif
peahd4f6ea72016-03-29 00:37:44 -0700175 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
peah51fbdd62016-03-30 14:58:32 -0700181#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
182 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700183TEST(EchoCancellationBitExactnessTest,
184 Mono48kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700185#else
186TEST(EchoCancellationBitExactnessTest,
187 DISABLED_Mono48kHz_HighLevel_NoDrift_StreamDelay0) {
188#endif
peahd4f6ea72016-03-29 00:37:44 -0700189 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
peah51fbdd62016-03-30 14:58:32 -0700195#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
196 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700197TEST(EchoCancellationBitExactnessTest,
198 Mono16kHz_LowLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700199#else
200TEST(EchoCancellationBitExactnessTest,
201 DISABLED_Mono16kHz_LowLevel_NoDrift_StreamDelay0) {
202#endif
peahd4f6ea72016-03-29 00:37:44 -0700203 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
peah51fbdd62016-03-30 14:58:32 -0700209#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
210 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700211TEST(EchoCancellationBitExactnessTest,
212 Mono16kHz_ModerateLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700213#else
214TEST(EchoCancellationBitExactnessTest,
215 DISABLED_Mono16kHz_ModerateLevel_NoDrift_StreamDelay0) {
216#endif
peahd4f6ea72016-03-29 00:37:44 -0700217 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
peah51fbdd62016-03-30 14:58:32 -0700223#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
224 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700225TEST(EchoCancellationBitExactnessTest,
226 Mono16kHz_HighLevel_NoDrift_StreamDelay10) {
peah51fbdd62016-03-30 14:58:32 -0700227#else
228TEST(EchoCancellationBitExactnessTest,
229 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay10) {
230#endif
peahd4f6ea72016-03-29 00:37:44 -0700231 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
peah51fbdd62016-03-30 14:58:32 -0700237#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
238 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700239TEST(EchoCancellationBitExactnessTest,
240 Mono16kHz_HighLevel_NoDrift_StreamDelay20) {
peah51fbdd62016-03-30 14:58:32 -0700241#else
242TEST(EchoCancellationBitExactnessTest,
243 DISABLED_Mono16kHz_HighLevel_NoDrift_StreamDelay20) {
244#endif
peahd4f6ea72016-03-29 00:37:44 -0700245 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
peah51fbdd62016-03-30 14:58:32 -0700251#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
252 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700253TEST(EchoCancellationBitExactnessTest,
254 Mono16kHz_HighLevel_Drift0_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700255#else
256TEST(EchoCancellationBitExactnessTest,
257 DISABLED_Mono16kHz_HighLevel_Drift0_StreamDelay0) {
258#endif
peahd4f6ea72016-03-29 00:37:44 -0700259 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
peah51fbdd62016-03-30 14:58:32 -0700265#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
266 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700267TEST(EchoCancellationBitExactnessTest,
268 Mono16kHz_HighLevel_Drift5_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700269#else
270TEST(EchoCancellationBitExactnessTest,
271 DISABLED_Mono16kHz_HighLevel_Drift5_StreamDelay0) {
272#endif
peahd4f6ea72016-03-29 00:37:44 -0700273 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
peah51fbdd62016-03-30 14:58:32 -0700279#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
280 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700281TEST(EchoCancellationBitExactnessTest,
282 Stereo8kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700283#else
284TEST(EchoCancellationBitExactnessTest,
285 DISABLED_Stereo8kHz_HighLevel_NoDrift_StreamDelay0) {
286#endif
peahd4f6ea72016-03-29 00:37:44 -0700287 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
peah51fbdd62016-03-30 14:58:32 -0700294#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
295 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700296TEST(EchoCancellationBitExactnessTest,
297 Stereo16kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700298#else
299TEST(EchoCancellationBitExactnessTest,
300 DISABLED_Stereo16kHz_HighLevel_NoDrift_StreamDelay0) {
301#endif
peahd4f6ea72016-03-29 00:37:44 -0700302 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
peah51fbdd62016-03-30 14:58:32 -0700309#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
310 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700311TEST(EchoCancellationBitExactnessTest,
312 Stereo32kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700313#else
314TEST(EchoCancellationBitExactnessTest,
315 DISABLED_Stereo32kHz_HighLevel_NoDrift_StreamDelay0) {
316#endif
peahd4f6ea72016-03-29 00:37:44 -0700317 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
peah51fbdd62016-03-30 14:58:32 -0700324#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
325 defined(WEBRTC_ANDROID))
peahd4f6ea72016-03-29 00:37:44 -0700326TEST(EchoCancellationBitExactnessTest,
327 Stereo48kHz_HighLevel_NoDrift_StreamDelay0) {
peah51fbdd62016-03-30 14:58:32 -0700328#else
329TEST(EchoCancellationBitExactnessTest,
330 DISABLED_Stereo48kHz_HighLevel_NoDrift_StreamDelay0) {
331#endif
peahd4f6ea72016-03-29 00:37:44 -0700332 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