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
11 #include <numeric>
12 #include <vector>
13
14 #include "api/array_view.h"
15 #include "modules/audio_processing/audio_buffer.h"
16 #include "modules/audio_processing/include/audio_processing.h"
17 #include "modules/audio_processing/level_controller/level_controller.h"
18 #include "modules/audio_processing/test/audio_buffer_tools.h"
19 #include "modules/audio_processing/test/bitexactness_tools.h"
20 #include "modules/audio_processing/test/performance_timer.h"
21 #include "modules/audio_processing/test/simulator_buffers.h"
22 #include "rtc_base/random.h"
23 #include "system_wrappers/include/clock.h"
24 #include "test/gtest.h"
25 #include "test/testsupport/perf_test.h"
26
27 namespace webrtc {
28 namespace {
29
30 const size_t kNumFramesToProcess = 300;
31 const size_t kNumFramesToProcessAtWarmup = 300;
32 const size_t kToTalNumFrames =
33 kNumFramesToProcess + kNumFramesToProcessAtWarmup;
34
RunStandaloneSubmodule(int sample_rate_hz,size_t num_channels)35 void RunStandaloneSubmodule(int sample_rate_hz, size_t num_channels) {
36 test::SimulatorBuffers buffers(sample_rate_hz, sample_rate_hz, sample_rate_hz,
37 sample_rate_hz, num_channels, num_channels,
38 num_channels, num_channels);
39 test::PerformanceTimer timer(kNumFramesToProcess);
40
41 LevelController level_controller;
42 level_controller.Initialize(sample_rate_hz);
43
44 for (size_t frame_no = 0; frame_no < kToTalNumFrames; ++frame_no) {
45 buffers.UpdateInputBuffers();
46
47 if (frame_no >= kNumFramesToProcessAtWarmup) {
48 timer.StartTimer();
49 }
50 level_controller.Process(buffers.capture_input_buffer.get());
51 if (frame_no >= kNumFramesToProcessAtWarmup) {
52 timer.StopTimer();
53 }
54 }
55 webrtc::test::PrintResultMeanAndError(
56 "level_controller_call_durations",
57 "_" + std::to_string(sample_rate_hz) + "Hz_" +
58 std::to_string(num_channels) + "_channels",
59 "StandaloneLevelControl", timer.GetDurationAverage(),
60 timer.GetDurationStandardDeviation(), "us", false);
61 }
62
RunTogetherWithApm(const std::string & test_description,int render_input_sample_rate_hz,int render_output_sample_rate_hz,int capture_input_sample_rate_hz,int capture_output_sample_rate_hz,size_t num_channels,bool use_mobile_aec,bool include_default_apm_processing)63 void RunTogetherWithApm(const std::string& test_description,
64 int render_input_sample_rate_hz,
65 int render_output_sample_rate_hz,
66 int capture_input_sample_rate_hz,
67 int capture_output_sample_rate_hz,
68 size_t num_channels,
69 bool use_mobile_aec,
70 bool include_default_apm_processing) {
71 test::SimulatorBuffers buffers(
72 render_input_sample_rate_hz, capture_input_sample_rate_hz,
73 render_output_sample_rate_hz, capture_output_sample_rate_hz, num_channels,
74 num_channels, num_channels, num_channels);
75 test::PerformanceTimer render_timer(kNumFramesToProcess);
76 test::PerformanceTimer capture_timer(kNumFramesToProcess);
77 test::PerformanceTimer total_timer(kNumFramesToProcess);
78
79 webrtc::Config config;
80 AudioProcessing::Config apm_config;
81 if (include_default_apm_processing) {
82 config.Set<DelayAgnostic>(new DelayAgnostic(true));
83 config.Set<ExtendedFilter>(new ExtendedFilter(true));
84 }
85 apm_config.level_controller.enabled = true;
86 apm_config.residual_echo_detector.enabled = include_default_apm_processing;
87
88 std::unique_ptr<AudioProcessing> apm;
89 apm.reset(AudioProcessing::Create(config));
90 ASSERT_TRUE(apm.get());
91 apm->ApplyConfig(apm_config);
92
93 ASSERT_EQ(AudioProcessing::kNoError,
94 apm->gain_control()->Enable(include_default_apm_processing));
95 if (use_mobile_aec) {
96 ASSERT_EQ(AudioProcessing::kNoError,
97 apm->echo_cancellation()->Enable(false));
98 ASSERT_EQ(AudioProcessing::kNoError, apm->echo_control_mobile()->Enable(
99 include_default_apm_processing));
100 } else {
101 ASSERT_EQ(AudioProcessing::kNoError,
102 apm->echo_cancellation()->Enable(include_default_apm_processing));
103 ASSERT_EQ(AudioProcessing::kNoError,
104 apm->echo_control_mobile()->Enable(false));
105 }
106 apm_config.high_pass_filter.enabled = include_default_apm_processing;
107 ASSERT_EQ(AudioProcessing::kNoError,
108 apm->noise_suppression()->Enable(include_default_apm_processing));
109 ASSERT_EQ(AudioProcessing::kNoError,
110 apm->voice_detection()->Enable(include_default_apm_processing));
111 ASSERT_EQ(AudioProcessing::kNoError,
112 apm->level_estimator()->Enable(include_default_apm_processing));
113
114 StreamConfig render_input_config(render_input_sample_rate_hz, num_channels,
115 false);
116 StreamConfig render_output_config(render_output_sample_rate_hz, num_channels,
117 false);
118 StreamConfig capture_input_config(capture_input_sample_rate_hz, num_channels,
119 false);
120 StreamConfig capture_output_config(capture_output_sample_rate_hz,
121 num_channels, false);
122
123 for (size_t frame_no = 0; frame_no < kToTalNumFrames; ++frame_no) {
124 buffers.UpdateInputBuffers();
125
126 if (frame_no >= kNumFramesToProcessAtWarmup) {
127 total_timer.StartTimer();
128 render_timer.StartTimer();
129 }
130 ASSERT_EQ(AudioProcessing::kNoError,
131 apm->ProcessReverseStream(
132 &buffers.render_input[0], render_input_config,
133 render_output_config, &buffers.render_output[0]));
134
135 if (frame_no >= kNumFramesToProcessAtWarmup) {
136 render_timer.StopTimer();
137
138 capture_timer.StartTimer();
139 }
140
141 ASSERT_EQ(AudioProcessing::kNoError, apm->set_stream_delay_ms(0));
142 ASSERT_EQ(
143 AudioProcessing::kNoError,
144 apm->ProcessStream(&buffers.capture_input[0], capture_input_config,
145 capture_output_config, &buffers.capture_output[0]));
146
147 if (frame_no >= kNumFramesToProcessAtWarmup) {
148 capture_timer.StopTimer();
149 total_timer.StopTimer();
150 }
151 }
152
153 webrtc::test::PrintResultMeanAndError(
154 "level_controller_call_durations",
155 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
156 std::to_string(render_output_sample_rate_hz) + "_" +
157 std::to_string(capture_input_sample_rate_hz) + "_" +
158 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
159 std::to_string(num_channels) + "_channels" + "_render",
160 test_description, render_timer.GetDurationAverage(),
161 render_timer.GetDurationStandardDeviation(), "us", false);
162 webrtc::test::PrintResultMeanAndError(
163 "level_controller_call_durations",
164 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
165 std::to_string(render_output_sample_rate_hz) + "_" +
166 std::to_string(capture_input_sample_rate_hz) + "_" +
167 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
168 std::to_string(num_channels) + "_channels" + "_capture",
169 test_description, capture_timer.GetDurationAverage(),
170 capture_timer.GetDurationStandardDeviation(), "us", false);
171 webrtc::test::PrintResultMeanAndError(
172 "level_controller_call_durations",
173 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
174 std::to_string(render_output_sample_rate_hz) + "_" +
175 std::to_string(capture_input_sample_rate_hz) + "_" +
176 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
177 std::to_string(num_channels) + "_channels" + "_total",
178 test_description, total_timer.GetDurationAverage(),
179 total_timer.GetDurationStandardDeviation(), "us", false);
180 }
181
182 } // namespace
183
184 // TODO(peah): Reactivate once issue 7712 has been resolved.
TEST(LevelControllerPerformanceTest,DISABLED_StandaloneProcessing)185 TEST(LevelControllerPerformanceTest, DISABLED_StandaloneProcessing) {
186 int sample_rates_to_test[] = {
187 AudioProcessing::kSampleRate8kHz, AudioProcessing::kSampleRate16kHz,
188 AudioProcessing::kSampleRate32kHz, AudioProcessing::kSampleRate48kHz};
189 for (auto sample_rate : sample_rates_to_test) {
190 for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
191 RunStandaloneSubmodule(sample_rate, num_channels);
192 }
193 }
194 }
195
TestSomeSampleRatesWithApm(const std::string & test_name,bool use_mobile_agc,bool include_default_apm_processing)196 void TestSomeSampleRatesWithApm(const std::string& test_name,
197 bool use_mobile_agc,
198 bool include_default_apm_processing) {
199 // Test some stereo combinations first.
200 size_t num_channels = 2;
201 RunTogetherWithApm(test_name, 48000, 48000, AudioProcessing::kSampleRate16kHz,
202 AudioProcessing::kSampleRate32kHz, num_channels,
203 use_mobile_agc, include_default_apm_processing);
204 RunTogetherWithApm(test_name, 48000, 48000, AudioProcessing::kSampleRate48kHz,
205 AudioProcessing::kSampleRate8kHz, num_channels,
206 use_mobile_agc, include_default_apm_processing);
207 RunTogetherWithApm(test_name, 48000, 48000, 44100, 44100, num_channels,
208 use_mobile_agc, include_default_apm_processing);
209
210 // Then test mono combinations.
211 num_channels = 1;
212 RunTogetherWithApm(test_name, 48000, 48000, AudioProcessing::kSampleRate48kHz,
213 AudioProcessing::kSampleRate48kHz, num_channels,
214 use_mobile_agc, include_default_apm_processing);
215 }
216
217 // TODO(peah): Reactivate once issue 7712 has been resolved.
218 #if !defined(WEBRTC_ANDROID)
TEST(LevelControllerPerformanceTest,DISABLED_ProcessingViaApm)219 TEST(LevelControllerPerformanceTest, DISABLED_ProcessingViaApm) {
220 #else
221 TEST(LevelControllerPerformanceTest, DISABLED_ProcessingViaApm) {
222 #endif
223 // Run without default APM processing and desktop AGC.
224 TestSomeSampleRatesWithApm("SimpleLevelControlViaApm", false, false);
225 }
226
227 // TODO(peah): Reactivate once issue 7712 has been resolved.
228 #if !defined(WEBRTC_ANDROID)
229 TEST(LevelControllerPerformanceTest, DISABLED_InteractionWithDefaultApm) {
230 #else
231 TEST(LevelControllerPerformanceTest, DISABLED_InteractionWithDefaultApm) {
232 #endif
233 bool include_default_apm_processing = true;
234 TestSomeSampleRatesWithApm("LevelControlAndDefaultDesktopApm", false,
235 include_default_apm_processing);
236 TestSomeSampleRatesWithApm("LevelControlAndDefaultMobileApm", true,
237 include_default_apm_processing);
238 }
239
240 } // namespace webrtc
241