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

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

Powered by Google App Engine
This is Rietveld 408576698