xref: /aosp_15_r20/external/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 "modules/audio_processing/test/aec_dump_based_simulator.h"
12 
13 #include <iostream>
14 #include <memory>
15 
16 #include "modules/audio_processing/echo_control_mobile_impl.h"
17 #include "modules/audio_processing/logging/apm_data_dumper.h"
18 #include "modules/audio_processing/test/aec_dump_based_simulator.h"
19 #include "modules/audio_processing/test/protobuf_utils.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/logging.h"
22 #include "rtc_base/numerics/safe_conversions.h"
23 
24 namespace webrtc {
25 namespace test {
26 namespace {
27 
28 // Verify output bitexactness for the fixed interface.
29 // TODO(peah): Check whether it would make sense to add a threshold
30 // to use for checking the bitexactness in a soft manner.
VerifyFixedBitExactness(const webrtc::audioproc::Stream & msg,const Int16Frame & frame)31 bool VerifyFixedBitExactness(const webrtc::audioproc::Stream& msg,
32                              const Int16Frame& frame) {
33   if (sizeof(frame.data[0]) * frame.data.size() != msg.output_data().size()) {
34     return false;
35   } else {
36     const int16_t* frame_data = frame.data.data();
37     for (int k = 0; k < frame.num_channels * frame.samples_per_channel; ++k) {
38       if (msg.output_data().data()[k] != frame_data[k]) {
39         return false;
40       }
41     }
42   }
43   return true;
44 }
45 
46 // Verify output bitexactness for the float interface.
VerifyFloatBitExactness(const webrtc::audioproc::Stream & msg,const StreamConfig & out_config,const ChannelBuffer<float> & out_buf)47 bool VerifyFloatBitExactness(const webrtc::audioproc::Stream& msg,
48                              const StreamConfig& out_config,
49                              const ChannelBuffer<float>& out_buf) {
50   if (static_cast<size_t>(msg.output_channel_size()) !=
51           out_config.num_channels() ||
52       msg.output_channel(0).size() != out_config.num_frames()) {
53     return false;
54   } else {
55     for (int ch = 0; ch < msg.output_channel_size(); ++ch) {
56       for (size_t sample = 0; sample < out_config.num_frames(); ++sample) {
57         if (msg.output_channel(ch).data()[sample] !=
58             out_buf.channels()[ch][sample]) {
59           return false;
60         }
61       }
62     }
63   }
64   return true;
65 }
66 
67 // Selectively reads the next proto-buf message from dump-file or string input.
68 // Returns a bool indicating whether a new message was available.
ReadNextMessage(bool use_dump_file,FILE * dump_input_file,std::stringstream & input,webrtc::audioproc::Event & event_msg)69 bool ReadNextMessage(bool use_dump_file,
70                      FILE* dump_input_file,
71                      std::stringstream& input,
72                      webrtc::audioproc::Event& event_msg) {
73   if (use_dump_file) {
74     return ReadMessageFromFile(dump_input_file, &event_msg);
75   }
76   return ReadMessageFromString(&input, &event_msg);
77 }
78 
79 }  // namespace
80 
AecDumpBasedSimulator(const SimulationSettings & settings,rtc::scoped_refptr<AudioProcessing> audio_processing,std::unique_ptr<AudioProcessingBuilder> ap_builder)81 AecDumpBasedSimulator::AecDumpBasedSimulator(
82     const SimulationSettings& settings,
83     rtc::scoped_refptr<AudioProcessing> audio_processing,
84     std::unique_ptr<AudioProcessingBuilder> ap_builder)
85     : AudioProcessingSimulator(settings,
86                                std::move(audio_processing),
87                                std::move(ap_builder)) {
88   MaybeOpenCallOrderFile();
89 }
90 
91 AecDumpBasedSimulator::~AecDumpBasedSimulator() = default;
92 
PrepareProcessStreamCall(const webrtc::audioproc::Stream & msg)93 void AecDumpBasedSimulator::PrepareProcessStreamCall(
94     const webrtc::audioproc::Stream& msg) {
95   if (msg.has_input_data()) {
96     // Fixed interface processing.
97     // Verify interface invariance.
98     RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface ||
99               interface_used_ == InterfaceType::kNotSpecified);
100     interface_used_ = InterfaceType::kFixedInterface;
101 
102     // Populate input buffer.
103     RTC_CHECK_EQ(sizeof(fwd_frame_.data[0]) * fwd_frame_.data.size(),
104                  msg.input_data().size());
105     memcpy(fwd_frame_.data.data(), msg.input_data().data(),
106            msg.input_data().size());
107   } else {
108     // Float interface processing.
109     // Verify interface invariance.
110     RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface ||
111               interface_used_ == InterfaceType::kNotSpecified);
112     interface_used_ = InterfaceType::kFloatInterface;
113 
114     RTC_CHECK_EQ(in_buf_->num_channels(),
115                  static_cast<size_t>(msg.input_channel_size()));
116 
117     // Populate input buffer.
118     for (size_t i = 0; i < in_buf_->num_channels(); ++i) {
119       RTC_CHECK_EQ(in_buf_->num_frames() * sizeof(*in_buf_->channels()[i]),
120                    msg.input_channel(i).size());
121       std::memcpy(in_buf_->channels()[i], msg.input_channel(i).data(),
122                   msg.input_channel(i).size());
123     }
124   }
125 
126   if (artificial_nearend_buffer_reader_) {
127     if (artificial_nearend_buffer_reader_->Read(
128             artificial_nearend_buf_.get())) {
129       if (msg.has_input_data()) {
130         int16_t* fwd_frame_data = fwd_frame_.data.data();
131         for (size_t k = 0; k < in_buf_->num_frames(); ++k) {
132           fwd_frame_data[k] = rtc::saturated_cast<int16_t>(
133               fwd_frame_data[k] +
134               static_cast<int16_t>(32767 *
135                                    artificial_nearend_buf_->channels()[0][k]));
136         }
137       } else {
138         for (int i = 0; i < msg.input_channel_size(); ++i) {
139           for (size_t k = 0; k < in_buf_->num_frames(); ++k) {
140             in_buf_->channels()[i][k] +=
141                 artificial_nearend_buf_->channels()[0][k];
142             in_buf_->channels()[i][k] = std::min(
143                 32767.f, std::max(-32768.f, in_buf_->channels()[i][k]));
144           }
145         }
146       }
147     } else {
148       if (!artificial_nearend_eof_reported_) {
149         std::cout << "The artificial nearend file ended before the recording.";
150         artificial_nearend_eof_reported_ = true;
151       }
152     }
153   }
154 
155   if (!settings_.use_stream_delay || *settings_.use_stream_delay) {
156     if (!settings_.stream_delay) {
157       if (msg.has_delay()) {
158         RTC_CHECK_EQ(AudioProcessing::kNoError,
159                      ap_->set_stream_delay_ms(msg.delay()));
160       }
161     } else {
162       RTC_CHECK_EQ(AudioProcessing::kNoError,
163                    ap_->set_stream_delay_ms(*settings_.stream_delay));
164     }
165   }
166 
167   if (settings_.override_key_pressed.has_value()) {
168     // Key pressed state overridden.
169     ap_->set_stream_key_pressed(*settings_.override_key_pressed);
170   } else {
171     // Set the recorded key pressed state.
172     if (msg.has_keypress()) {
173       ap_->set_stream_key_pressed(msg.keypress());
174     }
175   }
176 
177   // Set the applied input level if available.
178   aec_dump_applied_input_level_ =
179       msg.has_applied_input_volume()
180           ? absl::optional<int>(msg.applied_input_volume())
181           : absl::nullopt;
182 }
183 
VerifyProcessStreamBitExactness(const webrtc::audioproc::Stream & msg)184 void AecDumpBasedSimulator::VerifyProcessStreamBitExactness(
185     const webrtc::audioproc::Stream& msg) {
186   if (bitexact_output_) {
187     if (interface_used_ == InterfaceType::kFixedInterface) {
188       bitexact_output_ = VerifyFixedBitExactness(msg, fwd_frame_);
189     } else {
190       bitexact_output_ = VerifyFloatBitExactness(msg, out_config_, *out_buf_);
191     }
192   }
193 }
194 
PrepareReverseProcessStreamCall(const webrtc::audioproc::ReverseStream & msg)195 void AecDumpBasedSimulator::PrepareReverseProcessStreamCall(
196     const webrtc::audioproc::ReverseStream& msg) {
197   if (msg.has_data()) {
198     // Fixed interface processing.
199     // Verify interface invariance.
200     RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface ||
201               interface_used_ == InterfaceType::kNotSpecified);
202     interface_used_ = InterfaceType::kFixedInterface;
203 
204     // Populate input buffer.
205     RTC_CHECK_EQ(sizeof(rev_frame_.data[0]) * rev_frame_.data.size(),
206                  msg.data().size());
207     memcpy(rev_frame_.data.data(), msg.data().data(), msg.data().size());
208   } else {
209     // Float interface processing.
210     // Verify interface invariance.
211     RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface ||
212               interface_used_ == InterfaceType::kNotSpecified);
213     interface_used_ = InterfaceType::kFloatInterface;
214 
215     RTC_CHECK_EQ(reverse_in_buf_->num_channels(),
216                  static_cast<size_t>(msg.channel_size()));
217 
218     // Populate input buffer.
219     for (int i = 0; i < msg.channel_size(); ++i) {
220       RTC_CHECK_EQ(reverse_in_buf_->num_frames() *
221                        sizeof(*reverse_in_buf_->channels()[i]),
222                    msg.channel(i).size());
223       std::memcpy(reverse_in_buf_->channels()[i], msg.channel(i).data(),
224                   msg.channel(i).size());
225     }
226   }
227 }
228 
Process()229 void AecDumpBasedSimulator::Process() {
230   ConfigureAudioProcessor();
231 
232   if (settings_.artificial_nearend_filename) {
233     std::unique_ptr<WavReader> artificial_nearend_file(
234         new WavReader(settings_.artificial_nearend_filename->c_str()));
235 
236     RTC_CHECK_EQ(1, artificial_nearend_file->num_channels())
237         << "Only mono files for the artificial nearend are supported, "
238            "reverted to not using the artificial nearend file";
239 
240     const int sample_rate_hz = artificial_nearend_file->sample_rate();
241     artificial_nearend_buffer_reader_.reset(
242         new ChannelBufferWavReader(std::move(artificial_nearend_file)));
243     artificial_nearend_buf_.reset(new ChannelBuffer<float>(
244         rtc::CheckedDivExact(sample_rate_hz, kChunksPerSecond), 1));
245   }
246 
247   const bool use_dump_file = !settings_.aec_dump_input_string.has_value();
248   std::stringstream input;
249   if (use_dump_file) {
250     dump_input_file_ =
251         OpenFile(settings_.aec_dump_input_filename->c_str(), "rb");
252   } else {
253     input << settings_.aec_dump_input_string.value();
254   }
255 
256   webrtc::audioproc::Event event_msg;
257   int capture_frames_since_init = 0;
258   int init_index = 0;
259   while (ReadNextMessage(use_dump_file, dump_input_file_, input, event_msg)) {
260     SelectivelyToggleDataDumping(init_index, capture_frames_since_init);
261     HandleEvent(event_msg, capture_frames_since_init, init_index);
262 
263     // Perfom an early exit if the init block to process has been fully
264     // processed
265     if (finished_processing_specified_init_block_) {
266       break;
267     }
268     RTC_CHECK(!settings_.init_to_process ||
269               *settings_.init_to_process >= init_index);
270   }
271 
272   if (use_dump_file) {
273     fclose(dump_input_file_);
274   }
275 
276   DetachAecDump();
277 }
278 
Analyze()279 void AecDumpBasedSimulator::Analyze() {
280   const bool use_dump_file = !settings_.aec_dump_input_string.has_value();
281   std::stringstream input;
282   if (use_dump_file) {
283     dump_input_file_ =
284         OpenFile(settings_.aec_dump_input_filename->c_str(), "rb");
285   } else {
286     input << settings_.aec_dump_input_string.value();
287   }
288 
289   webrtc::audioproc::Event event_msg;
290   int num_capture_frames = 0;
291   int num_render_frames = 0;
292   int init_index = 0;
293   while (ReadNextMessage(use_dump_file, dump_input_file_, input, event_msg)) {
294     if (event_msg.type() == webrtc::audioproc::Event::INIT) {
295       ++init_index;
296       constexpr float kNumFramesPerSecond = 100.f;
297       float capture_time_seconds = num_capture_frames / kNumFramesPerSecond;
298       float render_time_seconds = num_render_frames / kNumFramesPerSecond;
299 
300       std::cout << "Inits:" << std::endl;
301       std::cout << init_index << ": -->" << std::endl;
302       std::cout << " Time:" << std::endl;
303       std::cout << "  Capture: " << capture_time_seconds << " s ("
304                 << num_capture_frames << " frames) " << std::endl;
305       std::cout << "  Render: " << render_time_seconds << " s ("
306                 << num_render_frames << " frames) " << std::endl;
307     } else if (event_msg.type() == webrtc::audioproc::Event::STREAM) {
308       ++num_capture_frames;
309     } else if (event_msg.type() == webrtc::audioproc::Event::REVERSE_STREAM) {
310       ++num_render_frames;
311     }
312   }
313 
314   if (use_dump_file) {
315     fclose(dump_input_file_);
316   }
317 }
318 
HandleEvent(const webrtc::audioproc::Event & event_msg,int & capture_frames_since_init,int & init_index)319 void AecDumpBasedSimulator::HandleEvent(
320     const webrtc::audioproc::Event& event_msg,
321     int& capture_frames_since_init,
322     int& init_index) {
323   switch (event_msg.type()) {
324     case webrtc::audioproc::Event::INIT:
325       RTC_CHECK(event_msg.has_init());
326       ++init_index;
327       capture_frames_since_init = 0;
328       HandleMessage(event_msg.init(), init_index);
329       break;
330     case webrtc::audioproc::Event::STREAM:
331       RTC_CHECK(event_msg.has_stream());
332       ++capture_frames_since_init;
333       HandleMessage(event_msg.stream());
334       break;
335     case webrtc::audioproc::Event::REVERSE_STREAM:
336       RTC_CHECK(event_msg.has_reverse_stream());
337       HandleMessage(event_msg.reverse_stream());
338       break;
339     case webrtc::audioproc::Event::CONFIG:
340       RTC_CHECK(event_msg.has_config());
341       HandleMessage(event_msg.config());
342       break;
343     case webrtc::audioproc::Event::RUNTIME_SETTING:
344       HandleMessage(event_msg.runtime_setting());
345       break;
346     case webrtc::audioproc::Event::UNKNOWN_EVENT:
347       RTC_CHECK_NOTREACHED();
348   }
349 }
350 
HandleMessage(const webrtc::audioproc::Config & msg)351 void AecDumpBasedSimulator::HandleMessage(
352     const webrtc::audioproc::Config& msg) {
353   if (settings_.use_verbose_logging) {
354     std::cout << "Config at frame:" << std::endl;
355     std::cout << " Forward: " << get_num_process_stream_calls() << std::endl;
356     std::cout << " Reverse: " << get_num_reverse_process_stream_calls()
357               << std::endl;
358   }
359 
360   if (!settings_.discard_all_settings_in_aecdump) {
361     if (settings_.use_verbose_logging) {
362       std::cout << "Setting used in config:" << std::endl;
363     }
364     AudioProcessing::Config apm_config = ap_->GetConfig();
365 
366     if (msg.has_aec_enabled() || settings_.use_aec) {
367       bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled();
368       apm_config.echo_canceller.enabled = enable;
369       if (settings_.use_verbose_logging) {
370         std::cout << " aec_enabled: " << (enable ? "true" : "false")
371                   << std::endl;
372       }
373     }
374 
375     if (msg.has_aecm_enabled() || settings_.use_aecm) {
376       bool enable =
377           settings_.use_aecm ? *settings_.use_aecm : msg.aecm_enabled();
378       apm_config.echo_canceller.enabled |= enable;
379       apm_config.echo_canceller.mobile_mode = enable;
380       if (settings_.use_verbose_logging) {
381         std::cout << " aecm_enabled: " << (enable ? "true" : "false")
382                   << std::endl;
383       }
384     }
385 
386     if (msg.has_aecm_comfort_noise_enabled() &&
387         msg.aecm_comfort_noise_enabled()) {
388       RTC_LOG(LS_ERROR) << "Ignoring deprecated setting: AECM comfort noise";
389     }
390 
391     if (msg.has_aecm_routing_mode() &&
392         static_cast<webrtc::EchoControlMobileImpl::RoutingMode>(
393             msg.aecm_routing_mode()) != EchoControlMobileImpl::kSpeakerphone) {
394       RTC_LOG(LS_ERROR) << "Ignoring deprecated setting: AECM routing mode: "
395                         << msg.aecm_routing_mode();
396     }
397 
398     if (msg.has_agc_enabled() || settings_.use_agc) {
399       bool enable = settings_.use_agc ? *settings_.use_agc : msg.agc_enabled();
400       apm_config.gain_controller1.enabled = enable;
401       if (settings_.use_verbose_logging) {
402         std::cout << " agc_enabled: " << (enable ? "true" : "false")
403                   << std::endl;
404       }
405     }
406 
407     if (msg.has_agc_mode() || settings_.agc_mode) {
408       int mode = settings_.agc_mode ? *settings_.agc_mode : msg.agc_mode();
409       apm_config.gain_controller1.mode =
410           static_cast<webrtc::AudioProcessing::Config::GainController1::Mode>(
411               mode);
412       if (settings_.use_verbose_logging) {
413         std::cout << " agc_mode: " << mode << std::endl;
414       }
415     }
416 
417     if (msg.has_agc_limiter_enabled() || settings_.use_agc_limiter) {
418       bool enable = settings_.use_agc_limiter ? *settings_.use_agc_limiter
419                                               : msg.agc_limiter_enabled();
420       apm_config.gain_controller1.enable_limiter = enable;
421       if (settings_.use_verbose_logging) {
422         std::cout << " agc_limiter_enabled: " << (enable ? "true" : "false")
423                   << std::endl;
424       }
425     }
426 
427     if (settings_.use_agc2) {
428       bool enable = *settings_.use_agc2;
429       apm_config.gain_controller2.enabled = enable;
430       if (settings_.agc2_fixed_gain_db) {
431         apm_config.gain_controller2.fixed_digital.gain_db =
432             *settings_.agc2_fixed_gain_db;
433       }
434       if (settings_.use_verbose_logging) {
435         std::cout << " agc2_enabled: " << (enable ? "true" : "false")
436                   << std::endl;
437       }
438     }
439 
440     if (msg.has_noise_robust_agc_enabled()) {
441       apm_config.gain_controller1.analog_gain_controller.enabled =
442           settings_.use_analog_agc ? *settings_.use_analog_agc
443                                    : msg.noise_robust_agc_enabled();
444       if (settings_.use_verbose_logging) {
445         std::cout << " noise_robust_agc_enabled: "
446                   << (msg.noise_robust_agc_enabled() ? "true" : "false")
447                   << std::endl;
448       }
449     }
450 
451     if (msg.has_transient_suppression_enabled() || settings_.use_ts) {
452       bool enable = settings_.use_ts ? *settings_.use_ts
453                                      : msg.transient_suppression_enabled();
454       apm_config.transient_suppression.enabled = enable;
455       if (settings_.use_verbose_logging) {
456         std::cout << " transient_suppression_enabled: "
457                   << (enable ? "true" : "false") << std::endl;
458       }
459     }
460 
461     if (msg.has_hpf_enabled() || settings_.use_hpf) {
462       bool enable = settings_.use_hpf ? *settings_.use_hpf : msg.hpf_enabled();
463       apm_config.high_pass_filter.enabled = enable;
464       if (settings_.use_verbose_logging) {
465         std::cout << " hpf_enabled: " << (enable ? "true" : "false")
466                   << std::endl;
467       }
468     }
469 
470     if (msg.has_ns_enabled() || settings_.use_ns) {
471       bool enable = settings_.use_ns ? *settings_.use_ns : msg.ns_enabled();
472       apm_config.noise_suppression.enabled = enable;
473       if (settings_.use_verbose_logging) {
474         std::cout << " ns_enabled: " << (enable ? "true" : "false")
475                   << std::endl;
476       }
477     }
478 
479     if (msg.has_ns_level() || settings_.ns_level) {
480       int level = settings_.ns_level ? *settings_.ns_level : msg.ns_level();
481       apm_config.noise_suppression.level =
482           static_cast<AudioProcessing::Config::NoiseSuppression::Level>(level);
483       if (settings_.use_verbose_logging) {
484         std::cout << " ns_level: " << level << std::endl;
485       }
486     }
487 
488     if (msg.has_pre_amplifier_enabled() || settings_.use_pre_amplifier) {
489       const bool enable = settings_.use_pre_amplifier
490                               ? *settings_.use_pre_amplifier
491                               : msg.pre_amplifier_enabled();
492       apm_config.pre_amplifier.enabled = enable;
493     }
494 
495     if (msg.has_pre_amplifier_fixed_gain_factor() ||
496         settings_.pre_amplifier_gain_factor) {
497       const float gain = settings_.pre_amplifier_gain_factor
498                              ? *settings_.pre_amplifier_gain_factor
499                              : msg.pre_amplifier_fixed_gain_factor();
500       apm_config.pre_amplifier.fixed_gain_factor = gain;
501     }
502 
503     if (settings_.use_verbose_logging && msg.has_experiments_description() &&
504         !msg.experiments_description().empty()) {
505       std::cout << " experiments not included by default in the simulation: "
506                 << msg.experiments_description() << std::endl;
507     }
508 
509     ap_->ApplyConfig(apm_config);
510   }
511 }
512 
HandleMessage(const webrtc::audioproc::Init & msg,int init_index)513 void AecDumpBasedSimulator::HandleMessage(const webrtc::audioproc::Init& msg,
514                                           int init_index) {
515   RTC_CHECK(msg.has_sample_rate());
516   RTC_CHECK(msg.has_num_input_channels());
517   RTC_CHECK(msg.has_num_reverse_channels());
518   RTC_CHECK(msg.has_reverse_sample_rate());
519 
520   // Do not perform the init if the init block to process is fully processed
521   if (settings_.init_to_process && *settings_.init_to_process < init_index) {
522     finished_processing_specified_init_block_ = true;
523   }
524 
525   MaybeOpenCallOrderFile();
526 
527   if (settings_.use_verbose_logging) {
528     std::cout << "Init at frame:" << std::endl;
529     std::cout << " Forward: " << get_num_process_stream_calls() << std::endl;
530     std::cout << " Reverse: " << get_num_reverse_process_stream_calls()
531               << std::endl;
532   }
533 
534   int num_output_channels;
535   if (settings_.output_num_channels) {
536     num_output_channels = *settings_.output_num_channels;
537   } else {
538     num_output_channels = msg.has_num_output_channels()
539                               ? msg.num_output_channels()
540                               : msg.num_input_channels();
541   }
542 
543   int output_sample_rate;
544   if (settings_.output_sample_rate_hz) {
545     output_sample_rate = *settings_.output_sample_rate_hz;
546   } else {
547     output_sample_rate = msg.has_output_sample_rate() ? msg.output_sample_rate()
548                                                       : msg.sample_rate();
549   }
550 
551   int num_reverse_output_channels;
552   if (settings_.reverse_output_num_channels) {
553     num_reverse_output_channels = *settings_.reverse_output_num_channels;
554   } else {
555     num_reverse_output_channels = msg.has_num_reverse_output_channels()
556                                       ? msg.num_reverse_output_channels()
557                                       : msg.num_reverse_channels();
558   }
559 
560   int reverse_output_sample_rate;
561   if (settings_.reverse_output_sample_rate_hz) {
562     reverse_output_sample_rate = *settings_.reverse_output_sample_rate_hz;
563   } else {
564     reverse_output_sample_rate = msg.has_reverse_output_sample_rate()
565                                      ? msg.reverse_output_sample_rate()
566                                      : msg.reverse_sample_rate();
567   }
568 
569   SetupBuffersConfigsOutputs(
570       msg.sample_rate(), output_sample_rate, msg.reverse_sample_rate(),
571       reverse_output_sample_rate, msg.num_input_channels(), num_output_channels,
572       msg.num_reverse_channels(), num_reverse_output_channels);
573 }
574 
HandleMessage(const webrtc::audioproc::Stream & msg)575 void AecDumpBasedSimulator::HandleMessage(
576     const webrtc::audioproc::Stream& msg) {
577   if (call_order_output_file_) {
578     *call_order_output_file_ << "c";
579   }
580   PrepareProcessStreamCall(msg);
581   ProcessStream(interface_used_ == InterfaceType::kFixedInterface);
582   VerifyProcessStreamBitExactness(msg);
583 }
584 
HandleMessage(const webrtc::audioproc::ReverseStream & msg)585 void AecDumpBasedSimulator::HandleMessage(
586     const webrtc::audioproc::ReverseStream& msg) {
587   if (call_order_output_file_) {
588     *call_order_output_file_ << "r";
589   }
590   PrepareReverseProcessStreamCall(msg);
591   ProcessReverseStream(interface_used_ == InterfaceType::kFixedInterface);
592 }
593 
HandleMessage(const webrtc::audioproc::RuntimeSetting & msg)594 void AecDumpBasedSimulator::HandleMessage(
595     const webrtc::audioproc::RuntimeSetting& msg) {
596   RTC_CHECK(ap_.get());
597   if (msg.has_capture_pre_gain()) {
598     // Handle capture pre-gain runtime setting only if not overridden.
599     const bool pre_amplifier_overridden =
600         (!settings_.use_pre_amplifier || *settings_.use_pre_amplifier) &&
601         !settings_.pre_amplifier_gain_factor;
602     const bool capture_level_adjustment_overridden =
603         (!settings_.use_capture_level_adjustment ||
604          *settings_.use_capture_level_adjustment) &&
605         !settings_.pre_gain_factor;
606     if (pre_amplifier_overridden || capture_level_adjustment_overridden) {
607       ap_->SetRuntimeSetting(
608           AudioProcessing::RuntimeSetting::CreateCapturePreGain(
609               msg.capture_pre_gain()));
610     }
611   } else if (msg.has_capture_post_gain()) {
612     // Handle capture post-gain runtime setting only if not overridden.
613     if ((!settings_.use_capture_level_adjustment ||
614          *settings_.use_capture_level_adjustment) &&
615         !settings_.post_gain_factor) {
616       ap_->SetRuntimeSetting(
617           AudioProcessing::RuntimeSetting::CreateCapturePreGain(
618               msg.capture_pre_gain()));
619     }
620   } else if (msg.has_capture_fixed_post_gain()) {
621     // Handle capture fixed-post-gain runtime setting only if not overridden.
622     if ((!settings_.use_agc2 || *settings_.use_agc2) &&
623         !settings_.agc2_fixed_gain_db) {
624       ap_->SetRuntimeSetting(
625           AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain(
626               msg.capture_fixed_post_gain()));
627     }
628   } else if (msg.has_playout_volume_change()) {
629     ap_->SetRuntimeSetting(
630         AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(
631             msg.playout_volume_change()));
632   } else if (msg.has_playout_audio_device_change()) {
633     ap_->SetRuntimeSetting(
634         AudioProcessing::RuntimeSetting::CreatePlayoutAudioDeviceChange(
635             {msg.playout_audio_device_change().id(),
636              msg.playout_audio_device_change().max_volume()}));
637   } else if (msg.has_capture_output_used()) {
638     ap_->SetRuntimeSetting(
639         AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
640             msg.capture_output_used()));
641   }
642 }
643 
MaybeOpenCallOrderFile()644 void AecDumpBasedSimulator::MaybeOpenCallOrderFile() {
645   if (settings_.call_order_output_filename.has_value()) {
646     const std::string filename = settings_.store_intermediate_output
647                                      ? *settings_.call_order_output_filename +
648                                            "_" +
649                                            std::to_string(output_reset_counter_)
650                                      : *settings_.call_order_output_filename;
651     call_order_output_file_ = std::make_unique<std::ofstream>(filename);
652   }
653 }
654 
655 }  // namespace test
656 }  // namespace webrtc
657