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

Side by Side Diff: webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc

Issue 1907223003: Extension and refactoring of the audioproc_f tool to be a fully fledged tool for audio processing m… (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Changes in response to reviewer comments Created 4 years, 7 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 "webrtc/modules/audio_processing/test/aec_dump_based_simulator.h"
12
13 #include "webrtc/base/checks.h"
14 #include "webrtc/modules/audio_processing/test/protobuf_utils.h"
15 #include "webrtc/test/testsupport/trace_to_stderr.h"
16
17 namespace webrtc {
18 namespace test {
19 namespace {
20
21 // Verify output bitexactness for the fixed interface.
22 bool VerifyFixedBitExactness(const webrtc::audioproc::Stream& msg,
23 const AudioFrame& frame) {
24 if ((sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_) !=
25 msg.output_data().size()) {
26 return false;
27 } else {
28 for (size_t k = 0; k < frame.num_channels_ * frame.samples_per_channel_;
29 ++k) {
30 if (msg.output_data().data()[k] != frame.data_[k]) {
31 return false;
32 }
33 }
34 }
35 return true;
36 }
37
38 // Verify output bitexactness for the float interface.
39 bool VerifyFloatBitExactness(const webrtc::audioproc::Stream& msg,
40 const StreamConfig& out_config,
41 const ChannelBuffer<float>& out_buf) {
42 if (static_cast<size_t>(msg.output_channel_size()) !=
43 out_config.num_channels() ||
44 msg.output_channel(0).size() != out_config.num_frames()) {
45 return false;
46 } else {
47 for (int ch = 0; ch < msg.output_channel_size(); ++ch) {
48 for (size_t sample = 0; sample < out_config.num_frames(); ++sample) {
49 if (msg.output_channel(ch).data()[sample] !=
50 out_buf.channels()[ch][sample]) {
51 return false;
52 }
53 }
54 }
55 }
56 return true;
57 }
58
59 } // namespace
60
61 void AecDumpBasedSimulator::PrepareProcessStreamCall(
62 const webrtc::audioproc::Stream& msg) {
63 if (msg.has_input_data()) {
64 // Fixed interface processing.
65 // Verify interface invariance.
66 RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface ||
67 interface_used_ == InterfaceType::kNotSpecified);
68 interface_used_ = InterfaceType::kFixedInterface;
69
70 // ProcessStream could have changed this for the output frame.
71 fwd_frame_.num_channels_ = ap_->num_input_channels();
72
73 // Populate input buffer.
74 RTC_CHECK_EQ(sizeof(fwd_frame_.data_[0]) * fwd_frame_.samples_per_channel_ *
75 fwd_frame_.num_channels_,
76 msg.input_data().size());
77 memcpy(fwd_frame_.data_, msg.input_data().data(), msg.input_data().size());
78 } else {
79 // Float interface processing.
80 // Verify interface invariance.
81 RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface ||
82 interface_used_ == InterfaceType::kNotSpecified);
83 interface_used_ = InterfaceType::kFloatInterface;
84
85 RTC_CHECK_EQ(in_buf_->num_channels(),
86 static_cast<size_t>(msg.input_channel_size()));
87
88 // Populate input buffer.
89 for (int i = 0; i < msg.input_channel_size(); ++i) {
90 RTC_CHECK_EQ(in_buf_->num_frames() * sizeof(*in_buf_->channels()[i]),
91 msg.input_channel(i).size());
92 std::memcpy(in_buf_->channels()[i], msg.input_channel(i).data(),
93 msg.input_channel(i).size());
94 }
95 }
96
97 if (!settings_.stream_delay) {
98 if (msg.has_delay()) {
99 RTC_CHECK_EQ(AudioProcessing::kNoError,
100 ap_->set_stream_delay_ms(msg.delay()));
101 }
102 } else {
103 RTC_CHECK_EQ(AudioProcessing::kNoError,
104 ap_->set_stream_delay_ms(*settings_.stream_delay));
105 }
106
107 if (!settings_.stream_drift_samples) {
108 if (msg.has_drift()) {
109 ap_->echo_cancellation()->set_stream_drift_samples(msg.drift());
110 }
111 } else {
112 ap_->echo_cancellation()->set_stream_drift_samples(
113 *settings_.stream_drift_samples);
114 }
115
116 if (!settings_.use_ts) {
117 if (msg.has_keypress()) {
118 ap_->set_stream_key_pressed(msg.keypress());
119 }
120 } else {
121 ap_->set_stream_key_pressed(*settings_.use_ts);
122 }
123
124 // TODO(peah): Add support for controlling the analog level via the
125 // command-line.
126 if (msg.has_level()) {
127 RTC_CHECK_EQ(AudioProcessing::kNoError,
128 ap_->gain_control()->set_stream_analog_level(msg.level()));
129 }
130 }
131
132 void AecDumpBasedSimulator::VerifyProcessStreamBitExactness(
133 const webrtc::audioproc::Stream& msg) {
134 if (bitexact_output_) {
135 if (interface_used_ == InterfaceType::kFixedInterface) {
136 bitexact_output_ = VerifyFixedBitExactness(msg, fwd_frame_);
137 } else {
138 bitexact_output_ = VerifyFloatBitExactness(msg, out_config_, *out_buf_);
139 }
140 }
141 }
142
143 void AecDumpBasedSimulator::PrepareReverseProcessStreamCall(
144 const webrtc::audioproc::ReverseStream& msg) {
145 if (msg.has_data()) {
146 // Fixed interface processing.
147 // Verify interface invariance.
148 RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface ||
149 interface_used_ == InterfaceType::kNotSpecified);
150 interface_used_ = InterfaceType::kFixedInterface;
151
152 // Populate input buffer.
153 RTC_CHECK_EQ(sizeof(int16_t) * rev_frame_.samples_per_channel_ *
154 rev_frame_.num_channels_,
155 msg.data().size());
156 memcpy(rev_frame_.data_, msg.data().data(), msg.data().size());
157 } else {
158 // Float interface processing.
159 // Verify interface invariance.
160 RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface ||
161 interface_used_ == InterfaceType::kNotSpecified);
162 interface_used_ = InterfaceType::kFloatInterface;
163
164 RTC_CHECK_EQ(reverse_in_buf_->num_channels(),
165 static_cast<size_t>(msg.channel_size()));
166
167 // Populate input buffer.
168 for (int i = 0; i < msg.channel_size(); ++i) {
169 RTC_CHECK_EQ(reverse_in_buf_->num_frames() *
170 sizeof(*reverse_in_buf_->channels()[i]),
171 msg.channel(i).size());
172 std::memcpy(reverse_in_buf_->channels()[i], msg.channel(i).data(),
173 msg.channel(i).size());
174 }
175 }
176 }
177
178 void AecDumpBasedSimulator::Process() {
179 std::unique_ptr<test::TraceToStderr> trace_to_stderr;
180 if (settings_.use_verbose_logging) {
181 trace_to_stderr.reset(new test::TraceToStderr(true));
182 }
183
184 CreateAudioProcessor();
185 dump_input_file_ = OpenFile(settings_.aec_dump_input_filename->c_str(), "rb");
186
187 webrtc::audioproc::Event event_msg;
188 int num_forward_chunks_processed = 0;
189 const int kOneBykChunksPerSecond =
aluebs-webrtc 2016/05/09 16:27:32 float
peah-webrtc 2016/05/11 12:19:27 Good find! Done.
190 1.f / AudioProcessingSimulator::kChunksPerSecond;
191 while (ReadMessageFromFile(dump_input_file_, &event_msg)) {
192 switch (event_msg.type()) {
193 case webrtc::audioproc::Event::INIT:
194 RTC_CHECK(event_msg.has_init());
195 HandleMessage(event_msg.init());
196 break;
197 case webrtc::audioproc::Event::STREAM:
198 RTC_CHECK(event_msg.has_stream());
199 HandleMessage(event_msg.stream());
200 ++num_forward_chunks_processed;
201 break;
202 case webrtc::audioproc::Event::REVERSE_STREAM:
203 RTC_CHECK(event_msg.has_reverse_stream());
204 HandleMessage(event_msg.reverse_stream());
205 break;
206 case webrtc::audioproc::Event::CONFIG:
207 RTC_CHECK(event_msg.has_config());
208 HandleMessage(event_msg.config());
209 break;
210 default:
211 RTC_CHECK(false);
212 }
213 if (trace_to_stderr) {
214 trace_to_stderr->SetTimeSeconds(num_forward_chunks_processed *
215 kOneBykChunksPerSecond);
216 }
217 }
218
219 fclose(dump_input_file_);
220
221 DestroyAudioProcessor();
222 }
223
224 void AecDumpBasedSimulator::HandleMessage(
225 const webrtc::audioproc::Config& msg) {
226 if (settings_.use_verbose_logging) {
227 printf("Config at frame:\n ");
228 printf(" Forward: %zu\n", get_num_process_stream_calls());
229 printf(" Reverse: %zu\n", get_num_reverse_process_stream_calls());
230 }
231
232 if (!settings_.discard_all_settings_in_aecdump) {
233 if (settings_.use_verbose_logging) {
234 printf("Setting used in config:\n");
235 }
236 Config config;
237
238 if (msg.has_aec_enabled() || settings_.use_aec) {
239 bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled();
240 RTC_CHECK_EQ(AudioProcessing::kNoError,
241 ap_->echo_cancellation()->Enable(enable));
242 if (settings_.use_verbose_logging) {
243 printf(" aec_enabled: %s\n", enable ? "true" : "false");
244 }
245 }
246
247 if (msg.has_aec_delay_agnostic_enabled() || settings_.use_delay_agnostic) {
248 bool enable = settings_.use_delay_agnostic
249 ? *settings_.use_delay_agnostic
250 : msg.aec_delay_agnostic_enabled();
251 config.Set<DelayAgnostic>(new DelayAgnostic(enable));
252 if (settings_.use_verbose_logging) {
253 printf(" aec_delay_agnostic_enabled: %s\n", enable ? "true" : "false");
254 }
255 }
256
257 if (msg.has_aec_drift_compensation_enabled() ||
258 settings_.use_drift_compensation) {
259 bool enable = settings_.use_drift_compensation
260 ? *settings_.use_drift_compensation
261 : msg.aec_drift_compensation_enabled();
262 RTC_CHECK_EQ(AudioProcessing::kNoError,
263 ap_->echo_cancellation()->enable_drift_compensation(enable));
264 if (settings_.use_verbose_logging) {
265 printf(" aec_drift_compensation_enabled: %s\n",
266 enable ? "true" : "false");
267 }
268 }
269
270 if (msg.has_aec_extended_filter_enabled() ||
271 settings_.use_extended_filter) {
272 bool enable = settings_.use_extended_filter
273 ? *settings_.use_extended_filter
274 : msg.aec_extended_filter_enabled();
275 config.Set<ExtendedFilter>(new ExtendedFilter(enable));
276 if (settings_.use_verbose_logging) {
277 printf(" aec_extended_filter_enabled: %s\n", enable ? "true" : "false");
278 }
279 }
280
281 if (msg.has_aec_suppression_level() || settings_.aec_suppression_level) {
282 int level = settings_.aec_suppression_level
283 ? *settings_.aec_suppression_level
284 : msg.aec_suppression_level();
285 RTC_CHECK_EQ(
286 AudioProcessing::kNoError,
287 ap_->echo_cancellation()->set_suppression_level(
288 static_cast<webrtc::EchoCancellation::SuppressionLevel>(level)));
289 if (settings_.use_verbose_logging) {
290 printf(" aec_suppression_level: %d\n", level);
291 }
292 }
293
294 if (msg.has_aecm_enabled() || settings_.use_aecm) {
295 bool enable =
296 settings_.use_aecm ? *settings_.use_aecm : msg.aecm_enabled();
297 RTC_CHECK_EQ(AudioProcessing::kNoError,
298 ap_->echo_control_mobile()->Enable(enable));
299 if (settings_.use_verbose_logging) {
300 printf(" aecm_enabled: %s\n", enable ? "true" : "false");
301 }
302 }
303
304 if (msg.has_aecm_comfort_noise_enabled() ||
305 settings_.use_aecm_comfort_noise) {
306 bool enable = settings_.use_aecm_comfort_noise
307 ? *settings_.use_aecm_comfort_noise
308 : msg.aecm_comfort_noise_enabled();
309 RTC_CHECK_EQ(AudioProcessing::kNoError,
310 ap_->echo_control_mobile()->enable_comfort_noise(enable));
311 if (settings_.use_verbose_logging) {
312 printf(" aecm_comfort_noise_enabled: %s\n", enable ? "true" : "false");
313 }
314 }
315
316 if (msg.has_aecm_routing_mode() || settings_.aecm_routing_mode) {
317 int routing_mode = settings_.aecm_routing_mode
318 ? *settings_.aecm_routing_mode
319 : msg.aecm_routing_mode();
320 RTC_CHECK_EQ(AudioProcessing::kNoError,
321 ap_->echo_control_mobile()->set_routing_mode(
322 static_cast<webrtc::EchoControlMobile::RoutingMode>(
323 routing_mode)));
324 if (settings_.use_verbose_logging) {
325 printf(" aecm_routing_mode: %d\n", routing_mode);
326 }
327 }
328
329 if (msg.has_agc_enabled() || settings_.use_agc) {
330 bool enable = settings_.use_agc ? *settings_.use_agc : msg.agc_enabled();
331 RTC_CHECK_EQ(AudioProcessing::kNoError,
332 ap_->gain_control()->Enable(enable));
333 if (settings_.use_verbose_logging) {
334 printf(" agc_enabled: %s\n", enable ? "true" : "false");
335 }
336 }
337
338 if (msg.has_agc_mode() || settings_.agc_mode) {
339 int mode = settings_.agc_mode ? *settings_.agc_mode : msg.agc_mode();
340 RTC_CHECK_EQ(AudioProcessing::kNoError,
341 ap_->gain_control()->set_mode(
342 static_cast<webrtc::GainControl::Mode>(mode)));
343 if (settings_.use_verbose_logging) {
344 printf(" agc_mode: %d\n", mode);
345 }
346 }
347
348 if (msg.has_agc_limiter_enabled() || settings_.use_agc_limiter) {
349 bool enable = settings_.use_agc_limiter ? *settings_.use_agc_limiter
350 : msg.agc_limiter_enabled();
351 RTC_CHECK_EQ(AudioProcessing::kNoError,
352 ap_->gain_control()->enable_limiter(enable));
353 if (settings_.use_verbose_logging) {
354 printf(" agc_limiter_enabled: %s\n", enable ? "true" : "false");
355 }
356 }
357
358 // TODO(peah): Add support for controlling the Experimental AGC from the
359 // command line.
360 if (msg.has_noise_robust_agc_enabled()) {
361 config.Set<ExperimentalAgc>(
362 new ExperimentalAgc(msg.noise_robust_agc_enabled()));
363 if (settings_.use_verbose_logging) {
364 printf(" noise_robust_agc_enabled: %s\n",
365 msg.noise_robust_agc_enabled() ? "true" : "false");
366 }
367 }
368
369 if (msg.has_transient_suppression_enabled() || settings_.use_ts) {
370 bool enable = settings_.use_ts ? *settings_.use_ts
371 : msg.transient_suppression_enabled();
372 config.Set<ExperimentalNs>(new ExperimentalNs(enable));
373 if (settings_.use_verbose_logging) {
374 printf(" transient_suppression_enabled: %s\n",
375 enable ? "true" : "false");
376 }
377 }
378
379 if (msg.has_hpf_enabled() || settings_.use_hpf) {
380 bool enable = settings_.use_hpf ? *settings_.use_hpf : msg.hpf_enabled();
381 RTC_CHECK_EQ(AudioProcessing::kNoError,
382 ap_->high_pass_filter()->Enable(enable));
383 if (settings_.use_verbose_logging) {
384 printf(" hpf_enabled: %s\n", enable ? "true" : "false");
385 }
386 }
387
388 if (msg.has_ns_enabled() || settings_.use_ns) {
389 bool enable = settings_.use_ns ? *settings_.use_ns : msg.ns_enabled();
390 RTC_CHECK_EQ(AudioProcessing::kNoError,
391 ap_->noise_suppression()->Enable(enable));
392 if (settings_.use_verbose_logging) {
393 printf(" ns_enabled: %s\n", enable ? "true" : "false");
394 }
395 }
396
397 if (msg.has_ns_level() || settings_.ns_level) {
398 int level = settings_.ns_level ? *settings_.ns_level : msg.ns_level();
399 RTC_CHECK_EQ(AudioProcessing::kNoError,
400 ap_->noise_suppression()->set_level(
401 static_cast<NoiseSuppression::Level>(level)));
402 if (settings_.use_verbose_logging) {
403 printf(" ns_level: %d\n", level);
404 }
405 }
406
407 if (settings_.use_verbose_logging && msg.has_experiments_description() &&
408 msg.experiments_description().size() > 0) {
409 printf(" experiments not included by default in the simulation: %s\n",
410 msg.experiments_description().c_str());
411 }
412
413 if (settings_.use_refined_adaptive_filter) {
414 config.Set<RefinedAdaptiveFilter>(
415 new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter));
416 }
417
418 if (settings_.use_aec3) {
419 config.Set<EchoCanceller3>(new EchoCanceller3(*settings_.use_aec3));
420 }
421
422 ap_->SetExtraOptions(config);
423 }
424 }
425
426 void AecDumpBasedSimulator::HandleMessage(const webrtc::audioproc::Init& msg) {
427 RTC_CHECK(msg.has_sample_rate());
428 RTC_CHECK(msg.has_num_input_channels());
429 RTC_CHECK(msg.has_num_reverse_channels());
430 RTC_CHECK(msg.has_reverse_sample_rate());
431
432 if (settings_.use_verbose_logging) {
433 printf("Init at frame:\n");
434 printf(" Forward: %zu\n", get_num_process_stream_calls());
435 printf(" Reverse: %zu\n", get_num_reverse_process_stream_calls());
436 }
437
438 int num_output_channels;
439 if (settings_.output_num_channels) {
440 num_output_channels = *settings_.output_num_channels;
441 } else {
442 num_output_channels = msg.has_num_output_channels()
443 ? msg.num_output_channels()
444 : msg.num_input_channels();
445 }
446
447 int output_sample_rate;
448 if (settings_.output_sample_rate_hz) {
449 output_sample_rate = *settings_.output_sample_rate_hz;
450 } else {
451 output_sample_rate = msg.has_output_sample_rate() ? msg.output_sample_rate()
452 : msg.sample_rate();
453 }
454
455 int num_reverse_output_channels;
456 if (settings_.reverse_output_num_channels) {
457 num_reverse_output_channels = *settings_.reverse_output_num_channels;
458 } else {
459 num_reverse_output_channels = msg.has_num_reverse_output_channels()
460 ? msg.num_reverse_output_channels()
461 : msg.num_reverse_channels();
462 }
463
464 int reverse_output_sample_rate;
465 if (settings_.reverse_output_sample_rate_hz) {
466 reverse_output_sample_rate = *settings_.reverse_output_sample_rate_hz;
467 } else {
468 reverse_output_sample_rate = msg.has_reverse_output_sample_rate()
469 ? msg.reverse_output_sample_rate()
470 : msg.reverse_sample_rate();
471 }
472
473 SetupBuffersConfigsOutputs(
474 msg.sample_rate(), output_sample_rate, msg.reverse_sample_rate(),
475 reverse_output_sample_rate, msg.num_input_channels(), num_output_channels,
476 msg.num_reverse_channels(), num_reverse_output_channels);
477 }
478
479 void AecDumpBasedSimulator::HandleMessage(
480 const webrtc::audioproc::Stream& msg) {
481 PrepareProcessStreamCall(msg);
482 ProcessStream(interface_used_ == InterfaceType::kFixedInterface);
483 VerifyProcessStreamBitExactness(msg);
484 }
485
486 void AecDumpBasedSimulator::HandleMessage(
487 const webrtc::audioproc::ReverseStream& msg) {
488 PrepareReverseProcessStreamCall(msg);
489 ProcessReverseStream(interface_used_ == InterfaceType::kFixedInterface);
490 }
491
492 } // namespace test
493 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698