blob: fb58a5b87054f7e8777ea29f8823d2b1c0c96aca [file] [log] [blame]
peah8d2ade62016-03-22 11:05:12 -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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "api/array_view.h"
13#include "modules/audio_processing/audio_buffer.h"
14#include "modules/audio_processing/echo_control_mobile_impl.h"
15#include "modules/audio_processing/test/audio_buffer_tools.h"
16#include "modules/audio_processing/test/bitexactness_tools.h"
17#include "test/gtest.h"
peah8d2ade62016-03-22 11:05:12 -070018
19namespace webrtc {
20namespace {
21
22// TODO(peah): Increase the number of frames to proces when the issue of
23// non repeatable test results have been found.
24const int kNumFramesToProcess = 200;
25
26void SetupComponent(int sample_rate_hz,
27 EchoControlMobile::RoutingMode routing_mode,
28 bool comfort_noise_enabled,
29 EchoControlMobileImpl* echo_control_mobile) {
30 echo_control_mobile->Initialize(
31 sample_rate_hz > 16000 ? 16000 : sample_rate_hz, 1, 1);
32 EchoControlMobile* ec = static_cast<EchoControlMobile*>(echo_control_mobile);
33 ec->Enable(true);
34 ec->set_routing_mode(routing_mode);
35 ec->enable_comfort_noise(comfort_noise_enabled);
36}
37
38void ProcessOneFrame(int sample_rate_hz,
39 int stream_delay_ms,
40 AudioBuffer* render_audio_buffer,
41 AudioBuffer* capture_audio_buffer,
42 EchoControlMobileImpl* echo_control_mobile) {
43 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
44 render_audio_buffer->SplitIntoFrequencyBands();
45 capture_audio_buffer->SplitIntoFrequencyBands();
46 }
47
peaha0624602016-10-25 04:45:24 -070048 std::vector<int16_t> render_audio;
49 EchoControlMobileImpl::PackRenderAudioBuffer(
50 render_audio_buffer, 1, render_audio_buffer->num_channels(),
51 &render_audio);
52 echo_control_mobile->ProcessRenderAudio(render_audio);
53
peah8d2ade62016-03-22 11:05:12 -070054 echo_control_mobile->ProcessCaptureAudio(capture_audio_buffer,
55 stream_delay_ms);
56
57 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
58 capture_audio_buffer->MergeFrequencyBands();
59 }
60}
61
62void RunBitexactnessTest(int sample_rate_hz,
63 size_t num_channels,
64 int stream_delay_ms,
65 EchoControlMobile::RoutingMode routing_mode,
66 bool comfort_noise_enabled,
67 const rtc::ArrayView<const float>& output_reference) {
68 rtc::CriticalSection crit_render;
69 rtc::CriticalSection crit_capture;
70 EchoControlMobileImpl echo_control_mobile(&crit_render, &crit_capture);
71 SetupComponent(sample_rate_hz, routing_mode, comfort_noise_enabled,
72 &echo_control_mobile);
73
74 const int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
75 const StreamConfig render_config(sample_rate_hz, num_channels, false);
76 AudioBuffer render_buffer(
77 render_config.num_frames(), render_config.num_channels(),
78 render_config.num_frames(), 1, render_config.num_frames());
79 test::InputAudioFile render_file(
80 test::GetApmRenderTestVectorFileName(sample_rate_hz));
81 std::vector<float> render_input(samples_per_channel * num_channels);
82
83 const StreamConfig capture_config(sample_rate_hz, num_channels, false);
84 AudioBuffer capture_buffer(
85 capture_config.num_frames(), capture_config.num_channels(),
86 capture_config.num_frames(), 1, capture_config.num_frames());
87 test::InputAudioFile capture_file(
88 test::GetApmCaptureTestVectorFileName(sample_rate_hz));
89 std::vector<float> capture_input(samples_per_channel * num_channels);
90
91 for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
92 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels,
93 &render_file, render_input);
94 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels,
95 &capture_file, capture_input);
96
97 test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer);
98 test::CopyVectorToAudioBuffer(capture_config, capture_input,
99 &capture_buffer);
100
101 ProcessOneFrame(sample_rate_hz, stream_delay_ms, &render_buffer,
102 &capture_buffer, &echo_control_mobile);
103 }
104
105 // Extract and verify the test results.
106 std::vector<float> capture_output;
107 test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer,
108 &capture_output);
109
110 // Compare the output with the reference. Only the first values of the output
111 // from last frame processed are compared in order not having to specify all
112 // preceeding frames as testvectors. As the algorithm being tested has a
113 // memory, testing only the last frame implicitly also tests the preceeding
114 // frames.
peah7ea928e2016-03-30 08:13:57 -0700115 const float kElementErrorBound = 1.0f / 32768.0f;
116 EXPECT_TRUE(test::VerifyDeinterleavedArray(
peah8d2ade62016-03-22 11:05:12 -0700117 capture_config.num_frames(), capture_config.num_channels(),
peah7ea928e2016-03-30 08:13:57 -0700118 output_reference, capture_output, kElementErrorBound));
peah8d2ade62016-03-22 11:05:12 -0700119}
120
121} // namespace
122
123// TODO(peah): Renable once the integer overflow issue in aecm_core.c:932:69
124// has been solved.
125TEST(EchoControlMobileBitExactnessTest,
126 DISABLED_Mono8kHz_LoudSpeakerPhone_CngOn_StreamDelay0) {
127 const float kOutputReference[] = {0.005280f, 0.002380f, -0.000427f};
128
129 RunBitexactnessTest(8000, 1, 0,
130 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
131 kOutputReference);
132}
133
134TEST(EchoControlMobileBitExactnessTest,
135 DISABLED_Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay0) {
136 const float kOutputReference[] = {0.003601f, 0.002991f, 0.001923f};
137 RunBitexactnessTest(16000, 1, 0,
138 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
139 kOutputReference);
140}
141
142TEST(EchoControlMobileBitExactnessTest,
143 DISABLED_Mono32kHz_LoudSpeakerPhone_CngOn_StreamDelay0) {
144 const float kOutputReference[] = {0.002258f, 0.002899f, 0.003906f};
145
146 RunBitexactnessTest(32000, 1, 0,
147 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
148 kOutputReference);
149}
150
151TEST(EchoControlMobileBitExactnessTest,
152 DISABLED_Mono48kHz_LoudSpeakerPhone_CngOn_StreamDelay0) {
153 const float kOutputReference[] = {-0.000046f, 0.000041f, 0.000249f};
154
155 RunBitexactnessTest(48000, 1, 0,
156 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
157 kOutputReference);
158}
159
160TEST(EchoControlMobileBitExactnessTest,
161 DISABLED_Mono16kHz_LoudSpeakerPhone_CngOff_StreamDelay0) {
162 const float kOutputReference[] = {0.000000f, 0.000000f, 0.000000f};
163
164 RunBitexactnessTest(16000, 1, 0,
165 EchoControlMobile::RoutingMode::kLoudSpeakerphone, false,
166 kOutputReference);
167}
168
169// TODO(peah): Renable once the integer overflow issue in aecm_core.c:932:69
170// has been solved.
171TEST(EchoControlMobileBitExactnessTest,
172 DISABLED_Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay5) {
173 const float kOutputReference[] = {0.003693f, 0.002930f, 0.001801f};
174
175 RunBitexactnessTest(16000, 1, 5,
176 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
177 kOutputReference);
178}
179
180TEST(EchoControlMobileBitExactnessTest,
181 Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay10) {
peah89749732016-10-22 04:00:29 -0700182 const float kOutputReference[] = {-0.002380f, -0.002533f, -0.002563f};
peah8d2ade62016-03-22 11:05:12 -0700183
184 RunBitexactnessTest(16000, 1, 10,
185 EchoControlMobile::RoutingMode::kLoudSpeakerphone, true,
186 kOutputReference);
187}
188
189TEST(EchoControlMobileBitExactnessTest,
190 DISABLED_Mono16kHz_QuietEarpieceOrHeadset_CngOn_StreamDelay0) {
191 const float kOutputReference[] = {0.000397f, 0.000000f, -0.000305f};
192
193 RunBitexactnessTest(16000, 1, 0,
194 EchoControlMobile::RoutingMode::kQuietEarpieceOrHeadset,
195 true, kOutputReference);
196}
197
198TEST(EchoControlMobileBitExactnessTest,
199 DISABLED_Mono16kHz_Earpiece_CngOn_StreamDelay0) {
200 const float kOutputReference[] = {0.002167f, 0.001617f, 0.001038f};
201
202 RunBitexactnessTest(16000, 1, 0, EchoControlMobile::RoutingMode::kEarpiece,
203 true, kOutputReference);
204}
205
206TEST(EchoControlMobileBitExactnessTest,
207 DISABLED_Mono16kHz_LoudEarpiece_CngOn_StreamDelay0) {
208 const float kOutputReference[] = {0.003540f, 0.002899f, 0.001862f};
209
210 RunBitexactnessTest(16000, 1, 0,
211 EchoControlMobile::RoutingMode::kLoudEarpiece, true,
212 kOutputReference);
213}
214
215TEST(EchoControlMobileBitExactnessTest,
216 DISABLED_Mono16kHz_SpeakerPhone_CngOn_StreamDelay0) {
217 const float kOutputReference[] = {0.003632f, 0.003052f, 0.001984f};
218
219 RunBitexactnessTest(16000, 1, 0,
220 EchoControlMobile::RoutingMode::kSpeakerphone, true,
221 kOutputReference);
222}
223
224} // namespace webrtc