Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1460)

Side by Side Diff: webrtc/modules/audio_processing/level_controller/level_controller_complexity_unittest.cc

Issue 2090583002: New module for the adaptive level controlling functionality in the audio processing module (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added reporting of metrics Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
11 #include <numeric>
12 #include <vector>
13
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/base/array_view.h"
16 #include "webrtc/base/random.h"
17 #include "webrtc/modules/audio_processing/audio_buffer.h"
18 #include "webrtc/modules/audio_processing/include/audio_processing.h"
19 #include "webrtc/modules/audio_processing/level_controller/level_controller.h"
20 #include "webrtc/modules/audio_processing/test/audio_buffer_tools.h"
21 #include "webrtc/modules/audio_processing/test/bitexactness_tools.h"
22 #include "webrtc/system_wrappers/include/clock.h"
23 #include "webrtc/test/testsupport/perf_test.h"
24
25 namespace webrtc {
26 namespace {
27
28 const size_t kNumFramesToProcess = 100;
29
30 struct SimulatorBuffers {
31 SimulatorBuffers(int render_input_sample_rate_hz,
32 int capture_input_sample_rate_hz,
33 int render_output_sample_rate_hz,
34 int capture_output_sample_rate_hz,
35 size_t num_render_input_channels,
36 size_t num_capture_input_channels,
37 size_t num_render_output_channels,
38 size_t num_capture_output_channels) {
39 Random rand_gen(42);
40 CreateConfigAndBuffer(render_input_sample_rate_hz,
41 num_render_input_channels, &rand_gen,
42 &render_input_buffer, &render_input_config,
43 &render_input, &render_input_samples);
44
45 CreateConfigAndBuffer(render_output_sample_rate_hz,
46 num_render_output_channels, &rand_gen,
47 &render_output_buffer, &render_output_config,
48 &render_output, &render_output_samples);
49
50 CreateConfigAndBuffer(capture_input_sample_rate_hz,
51 num_capture_input_channels, &rand_gen,
52 &capture_input_buffer, &capture_input_config,
53 &capture_input, &capture_input_samples);
54
55 CreateConfigAndBuffer(capture_output_sample_rate_hz,
56 num_capture_output_channels, &rand_gen,
57 &capture_output_buffer, &capture_output_config,
58 &capture_output, &capture_output_samples);
59
60 UpdateInputBuffers();
61 }
62
63 void CreateConfigAndBuffer(int sample_rate_hz,
64 size_t num_channels,
65 Random* rand_gen,
66 std::unique_ptr<AudioBuffer>* buffer,
67 StreamConfig* config,
68 std::vector<float*>* buffer_data,
69 std::vector<float>* buffer_data_samples) {
70 int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
71 *config = StreamConfig(sample_rate_hz, num_channels, false);
72 buffer->reset(new AudioBuffer(config->num_frames(), config->num_channels(),
73 config->num_frames(), config->num_channels(),
74 config->num_frames()));
75
76 buffer_data_samples->resize(samples_per_channel * num_channels);
77 for (auto& v : *buffer_data_samples) {
78 v = rand_gen->Rand<float>();
79 }
80
81 buffer_data->resize(num_channels);
82 for (size_t ch = 0; ch < num_channels; ++ch) {
83 (*buffer_data)[ch] = &(*buffer_data_samples)[ch * samples_per_channel];
84 }
85 }
86
87 void UpdateInputBuffers() {
88 test::CopyVectorToAudioBuffer(capture_input_config, capture_input_samples,
89 capture_input_buffer.get());
90 test::CopyVectorToAudioBuffer(render_input_config, render_input_samples,
91 render_input_buffer.get());
92 }
93
94 std::unique_ptr<AudioBuffer> render_input_buffer;
95 std::unique_ptr<AudioBuffer> capture_input_buffer;
96 std::unique_ptr<AudioBuffer> render_output_buffer;
97 std::unique_ptr<AudioBuffer> capture_output_buffer;
98 StreamConfig render_input_config;
99 StreamConfig capture_input_config;
100 StreamConfig render_output_config;
101 StreamConfig capture_output_config;
102 std::vector<float*> render_input;
103 std::vector<float> render_input_samples;
104 std::vector<float*> capture_input;
105 std::vector<float> capture_input_samples;
106 std::vector<float*> render_output;
107 std::vector<float> render_output_samples;
108 std::vector<float*> capture_output;
109 std::vector<float> capture_output_samples;
110 };
111
112 class SubmodulePerformanceTimer {
113 public:
114 SubmodulePerformanceTimer() : clock_(webrtc::Clock::GetRealTimeClock()) {
115 timestamps_us_.reserve(kNumFramesToProcess);
116 }
117
118 void StartTimer() {
119 start_timestamp_us_ = rtc::Optional<int64_t>(clock_->TimeInMicroseconds());
120 }
121 void StopTimer() {
122 RTC_DCHECK(start_timestamp_us_);
123 timestamps_us_.push_back(clock_->TimeInMicroseconds() -
124 *start_timestamp_us_);
125 }
126
127 double GetDurationAverage() const {
128 RTC_DCHECK(!timestamps_us_.empty());
129 return static_cast<double>(std::accumulate(timestamps_us_.begin(),
130 timestamps_us_.end(), 0)) /
131 timestamps_us_.size();
132 }
133
134 double GetDurationStandardDeviation() const {
135 RTC_DCHECK(!timestamps_us_.empty());
136 double average_duration = GetDurationAverage();
137
138 int64_t variance =
139 std::accumulate(timestamps_us_.begin(), timestamps_us_.end(), 0,
140 [average_duration](const int64_t& a, const int64_t& b) {
141 return a + (b - average_duration);
142 });
143
144 return sqrt(variance / timestamps_us_.size());
145 }
146
147 private:
148 webrtc::Clock* clock_;
149 rtc::Optional<int64_t> start_timestamp_us_;
150 std::vector<int64_t> timestamps_us_;
151 };
152
153 std::string FormPerformanceMeasureString(
154 const SubmodulePerformanceTimer& timer) {
155 std::string s = std::to_string(timer.GetDurationAverage());
156 s += ", ";
157 s += std::to_string(timer.GetDurationStandardDeviation());
158 return s;
159 }
160
161 void RunStandaloneSubmodule(int sample_rate_hz, size_t num_channels) {
162 SimulatorBuffers buffers(sample_rate_hz, sample_rate_hz, sample_rate_hz,
163 sample_rate_hz, num_channels, num_channels,
164 num_channels, num_channels);
165 SubmodulePerformanceTimer timer;
166
167 LevelController level_controller;
168 level_controller.Initialize(sample_rate_hz);
169
170 for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
171 buffers.UpdateInputBuffers();
172
173 timer.StartTimer();
174 level_controller.Process(buffers.capture_input_buffer.get());
175 timer.StopTimer();
176 }
177 webrtc::test::PrintResultMeanAndError(
178 "level_controller_call_durations",
179 "_" + std::to_string(sample_rate_hz) + "Hz_" +
180 std::to_string(num_channels) + "_channels",
181 "StandaloneLevelControl", FormPerformanceMeasureString(timer), "us",
182 false);
183 }
184
185 void RunTogetherWithApm(std::string test_description,
186 int render_input_sample_rate_hz,
187 int render_output_sample_rate_hz,
188 int capture_input_sample_rate_hz,
189 int capture_output_sample_rate_hz,
190 size_t num_channels,
191 bool use_mobile_aec,
192 bool include_default_apm_processing) {
193 SimulatorBuffers buffers(
194 render_input_sample_rate_hz, capture_input_sample_rate_hz,
195 render_output_sample_rate_hz, capture_output_sample_rate_hz, num_channels,
196 num_channels, num_channels, num_channels);
197 SubmodulePerformanceTimer render_timer;
198 SubmodulePerformanceTimer capture_timer;
199 SubmodulePerformanceTimer total_timer;
200
201 Config config;
202 if (include_default_apm_processing) {
203 config.Set<DelayAgnostic>(new DelayAgnostic(true));
204 config.Set<ExtendedFilter>(new ExtendedFilter(true));
205 }
206 config.Set<LevelControl>(new LevelControl(true));
207
208 std::unique_ptr<AudioProcessing> apm;
209 apm.reset(AudioProcessing::Create(config));
210 ASSERT_TRUE(apm.get());
211
212 ASSERT_EQ(AudioProcessing::kNoError,
213 apm->gain_control()->Enable(include_default_apm_processing));
214 if (use_mobile_aec) {
215 ASSERT_EQ(AudioProcessing::kNoError,
216 apm->echo_cancellation()->Enable(false));
217 ASSERT_EQ(AudioProcessing::kNoError, apm->echo_control_mobile()->Enable(
218 include_default_apm_processing));
219 } else {
220 ASSERT_EQ(AudioProcessing::kNoError,
221 apm->echo_cancellation()->Enable(include_default_apm_processing));
222 ASSERT_EQ(AudioProcessing::kNoError,
223 apm->echo_control_mobile()->Enable(false));
224 }
225 ASSERT_EQ(AudioProcessing::kNoError,
226 apm->high_pass_filter()->Enable(include_default_apm_processing));
227 ASSERT_EQ(AudioProcessing::kNoError,
228 apm->noise_suppression()->Enable(include_default_apm_processing));
229 ASSERT_EQ(AudioProcessing::kNoError,
230 apm->voice_detection()->Enable(include_default_apm_processing));
231 ASSERT_EQ(AudioProcessing::kNoError,
232 apm->level_estimator()->Enable(include_default_apm_processing));
233
234 StreamConfig render_input_config(render_input_sample_rate_hz, num_channels,
235 false);
236 StreamConfig render_output_config(render_output_sample_rate_hz, num_channels,
237 false);
238 StreamConfig capture_input_config(capture_input_sample_rate_hz, num_channels,
239 false);
240 StreamConfig capture_output_config(capture_output_sample_rate_hz,
241 num_channels, false);
242
243 for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
244 buffers.UpdateInputBuffers();
245
246 total_timer.StartTimer();
247 render_timer.StartTimer();
248 ASSERT_EQ(AudioProcessing::kNoError,
249 apm->ProcessReverseStream(
250 &buffers.render_input[0], render_input_config,
251 render_output_config, &buffers.render_output[0]));
252
253 render_timer.StopTimer();
254
255 capture_timer.StartTimer();
256 ASSERT_EQ(AudioProcessing::kNoError, apm->set_stream_delay_ms(0));
257 ASSERT_EQ(
258 AudioProcessing::kNoError,
259 apm->ProcessStream(&buffers.capture_input[0], capture_input_config,
260 capture_output_config, &buffers.capture_output[0]));
261
262 capture_timer.StopTimer();
263 total_timer.StopTimer();
264 }
265
266 webrtc::test::PrintResultMeanAndError(
267 "level_controller_call_durations",
268 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
269 std::to_string(render_output_sample_rate_hz) + "_" +
270 std::to_string(capture_input_sample_rate_hz) + "_" +
271 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
272 std::to_string(num_channels) + "_channels" + "_render",
273 test_description, FormPerformanceMeasureString(render_timer), "us",
274 false);
275 webrtc::test::PrintResultMeanAndError(
276 "level_controller_call_durations",
277 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
278 std::to_string(render_output_sample_rate_hz) + "_" +
279 std::to_string(capture_input_sample_rate_hz) + "_" +
280 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
281 std::to_string(num_channels) + "_channels" + "_capture",
282 test_description, FormPerformanceMeasureString(capture_timer), "us",
283 false);
284 webrtc::test::PrintResultMeanAndError(
285 "level_controller_call_durations",
286 "_" + std::to_string(render_input_sample_rate_hz) + "_" +
287 std::to_string(render_output_sample_rate_hz) + "_" +
288 std::to_string(capture_input_sample_rate_hz) + "_" +
289 std::to_string(capture_output_sample_rate_hz) + "Hz_" +
290 std::to_string(num_channels) + "_channels" + "_total",
291 test_description, FormPerformanceMeasureString(total_timer), "us", false);
292 }
293
294 } // namespace
295
296 TEST(LevelControllerPerformanceTest, StandaloneProcessing) {
297 int sample_rates_to_test[] = {
298 AudioProcessing::kSampleRate8kHz, AudioProcessing::kSampleRate16kHz,
299 AudioProcessing::kSampleRate32kHz, AudioProcessing::kSampleRate48kHz};
300 for (auto sample_rate : sample_rates_to_test) {
301 for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
302 RunStandaloneSubmodule(sample_rate, num_channels);
303 }
304 }
305 }
306
307 TEST(LevelControllerPerformanceTest, ProcessingViaApm) {
308 int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
309 AudioProcessing::kSampleRate16kHz,
310 AudioProcessing::kSampleRate32kHz,
311 AudioProcessing::kSampleRate48kHz, 44100};
312 for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
313 for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
314 for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
315 RunTogetherWithApm("SimpleLevelControlViaApm", 48000, 48000,
316 capture_input_sample_rate_hz,
317 capture_output_sample_rate_hz, num_channels, false,
318 false);
319 }
320 }
321 }
322 }
323
324 TEST(LevelControllerPerformanceTest, InteractionWithDefaultApm) {
325 int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
326 AudioProcessing::kSampleRate16kHz,
327 AudioProcessing::kSampleRate32kHz,
328 AudioProcessing::kSampleRate48kHz, 44100};
329 for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
330 for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
331 for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
332 RunTogetherWithApm("LevelControlAndDefaultDesktopApm", 48000, 48000,
333 capture_input_sample_rate_hz,
334 capture_output_sample_rate_hz, num_channels, false,
335 true);
336 RunTogetherWithApm("LevelControlAndDefaultMobileApm", 48000, 48000,
337 capture_input_sample_rate_hz,
338 capture_output_sample_rate_hz, num_channels, true,
339 true);
340 }
341 }
342 }
343 }
344
345 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698