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

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

Powered by Google App Engine
This is Rietveld 408576698