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 #ifndef MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_
12 #define MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_
13 
14 #include <algorithm>
15 #include <fstream>
16 #include <limits>
17 #include <memory>
18 #include <string>
19 
20 #include "absl/types/optional.h"
21 #include "common_audio/channel_buffer.h"
22 #include "common_audio/include/audio_util.h"
23 #include "modules/audio_processing/include/audio_processing.h"
24 #include "modules/audio_processing/test/api_call_statistics.h"
25 #include "modules/audio_processing/test/fake_recording_device.h"
26 #include "modules/audio_processing/test/test_utils.h"
27 #include "rtc_base/constructor_magic.h"
28 #include "rtc_base/task_queue_for_test.h"
29 #include "rtc_base/time_utils.h"
30 
31 namespace webrtc {
32 namespace test {
33 
34 static const int kChunksPerSecond = 1000 / AudioProcessing::kChunkSizeMs;
35 
36 struct Int16Frame {
SetFormatInt16Frame37   void SetFormat(int sample_rate_hz, int num_channels) {
38     this->sample_rate_hz = sample_rate_hz;
39     samples_per_channel =
40         rtc::CheckedDivExact(sample_rate_hz, kChunksPerSecond);
41     this->num_channels = num_channels;
42     config = StreamConfig(sample_rate_hz, num_channels, /*has_keyboard=*/false);
43     data.resize(num_channels * samples_per_channel);
44   }
45 
CopyToInt16Frame46   void CopyTo(ChannelBuffer<float>* dest) {
47     RTC_DCHECK(dest);
48     RTC_CHECK_EQ(num_channels, dest->num_channels());
49     RTC_CHECK_EQ(samples_per_channel, dest->num_frames());
50     // Copy the data from the input buffer.
51     std::vector<float> tmp(samples_per_channel * num_channels);
52     S16ToFloat(data.data(), tmp.size(), tmp.data());
53     Deinterleave(tmp.data(), samples_per_channel, num_channels,
54                  dest->channels());
55   }
56 
CopyFromInt16Frame57   void CopyFrom(const ChannelBuffer<float>& src) {
58     RTC_CHECK_EQ(src.num_channels(), num_channels);
59     RTC_CHECK_EQ(src.num_frames(), samples_per_channel);
60     data.resize(num_channels * samples_per_channel);
61     int16_t* dest_data = data.data();
62     for (int ch = 0; ch < num_channels; ++ch) {
63       for (int sample = 0; sample < samples_per_channel; ++sample) {
64         dest_data[sample * num_channels + ch] =
65             src.channels()[ch][sample] * 32767;
66       }
67     }
68   }
69 
70   int sample_rate_hz;
71   int samples_per_channel;
72   int num_channels;
73 
74   StreamConfig config;
75 
76   std::vector<int16_t> data;
77 };
78 
79 // Holds all the parameters available for controlling the simulation.
80 struct SimulationSettings {
81   SimulationSettings();
82   SimulationSettings(const SimulationSettings&);
83   ~SimulationSettings();
84   absl::optional<int> stream_delay;
85   absl::optional<bool> use_stream_delay;
86   absl::optional<int> output_sample_rate_hz;
87   absl::optional<int> output_num_channels;
88   absl::optional<int> reverse_output_sample_rate_hz;
89   absl::optional<int> reverse_output_num_channels;
90   absl::optional<std::string> output_filename;
91   absl::optional<std::string> reverse_output_filename;
92   absl::optional<std::string> input_filename;
93   absl::optional<std::string> reverse_input_filename;
94   absl::optional<std::string> artificial_nearend_filename;
95   absl::optional<std::string> linear_aec_output_filename;
96   absl::optional<bool> use_aec;
97   absl::optional<bool> use_aecm;
98   absl::optional<bool> use_ed;  // Residual Echo Detector.
99   absl::optional<std::string> ed_graph_output_filename;
100   absl::optional<bool> use_agc;
101   absl::optional<bool> use_agc2;
102   absl::optional<bool> use_pre_amplifier;
103   absl::optional<bool> use_hpf;
104   absl::optional<bool> use_ns;
105   absl::optional<bool> use_ts;
106   absl::optional<bool> use_analog_agc;
107   absl::optional<bool> use_vad;
108   absl::optional<bool> use_le;
109   absl::optional<bool> use_all;
110   absl::optional<bool> use_analog_agc_agc2_level_estimator;
111   absl::optional<bool> analog_agc_disable_digital_adaptive;
112   absl::optional<int> agc_mode;
113   absl::optional<int> agc_target_level;
114   absl::optional<bool> use_agc_limiter;
115   absl::optional<int> agc_compression_gain;
116   absl::optional<bool> agc2_use_adaptive_gain;
117   absl::optional<float> agc2_fixed_gain_db;
118   AudioProcessing::Config::GainController2::LevelEstimator
119       agc2_adaptive_level_estimator;
120   absl::optional<float> pre_amplifier_gain_factor;
121   absl::optional<int> ns_level;
122   absl::optional<bool> ns_analysis_on_linear_aec_output;
123   absl::optional<int> maximum_internal_processing_rate;
124   int initial_mic_level;
125   bool simulate_mic_gain = false;
126   absl::optional<bool> multi_channel_render;
127   absl::optional<bool> multi_channel_capture;
128   absl::optional<int> simulated_mic_kind;
129   bool report_performance = false;
130   absl::optional<std::string> performance_report_output_filename;
131   bool report_bitexactness = false;
132   bool use_verbose_logging = false;
133   bool use_quiet_output = false;
134   bool discard_all_settings_in_aecdump = true;
135   absl::optional<std::string> aec_dump_input_filename;
136   absl::optional<std::string> aec_dump_output_filename;
137   bool fixed_interface = false;
138   bool store_intermediate_output = false;
139   bool print_aec_parameter_values = false;
140   bool dump_internal_data = false;
141   WavFile::SampleFormat wav_output_format = WavFile::SampleFormat::kInt16;
142   absl::optional<std::string> dump_internal_data_output_dir;
143   absl::optional<std::string> call_order_input_filename;
144   absl::optional<std::string> call_order_output_filename;
145   absl::optional<std::string> aec_settings_filename;
146   absl::optional<absl::string_view> aec_dump_input_string;
147   std::vector<float>* processed_capture_samples = nullptr;
148 };
149 
150 // Provides common functionality for performing audioprocessing simulations.
151 class AudioProcessingSimulator {
152  public:
153   AudioProcessingSimulator(const SimulationSettings& settings,
154                            rtc::scoped_refptr<AudioProcessing> audio_processing,
155                            std::unique_ptr<AudioProcessingBuilder> ap_builder);
156   virtual ~AudioProcessingSimulator();
157 
158   // Processes the data in the input.
159   virtual void Process() = 0;
160 
161   // Returns the execution times of all AudioProcessing calls.
GetApiCallStatistics()162   const ApiCallStatistics& GetApiCallStatistics() const {
163     return api_call_statistics_;
164   }
165 
166   // Reports whether the processed recording was bitexact.
OutputWasBitexact()167   bool OutputWasBitexact() { return bitexact_output_; }
168 
get_num_process_stream_calls()169   size_t get_num_process_stream_calls() { return num_process_stream_calls_; }
get_num_reverse_process_stream_calls()170   size_t get_num_reverse_process_stream_calls() {
171     return num_reverse_process_stream_calls_;
172   }
173 
174  protected:
175   void ProcessStream(bool fixed_interface);
176   void ProcessReverseStream(bool fixed_interface);
177   void ConfigureAudioProcessor();
178   void DetachAecDump();
179   void SetupBuffersConfigsOutputs(int input_sample_rate_hz,
180                                   int output_sample_rate_hz,
181                                   int reverse_input_sample_rate_hz,
182                                   int reverse_output_sample_rate_hz,
183                                   int input_num_channels,
184                                   int output_num_channels,
185                                   int reverse_input_num_channels,
186                                   int reverse_output_num_channels);
187 
188   const SimulationSettings settings_;
189   rtc::scoped_refptr<AudioProcessing> ap_;
190 
191   std::unique_ptr<ChannelBuffer<float>> in_buf_;
192   std::unique_ptr<ChannelBuffer<float>> out_buf_;
193   std::unique_ptr<ChannelBuffer<float>> reverse_in_buf_;
194   std::unique_ptr<ChannelBuffer<float>> reverse_out_buf_;
195   std::vector<std::array<float, 160>> linear_aec_output_buf_;
196   StreamConfig in_config_;
197   StreamConfig out_config_;
198   StreamConfig reverse_in_config_;
199   StreamConfig reverse_out_config_;
200   std::unique_ptr<ChannelBufferWavReader> buffer_reader_;
201   std::unique_ptr<ChannelBufferWavReader> reverse_buffer_reader_;
202   Int16Frame rev_frame_;
203   Int16Frame fwd_frame_;
204   bool bitexact_output_ = true;
205   int aec_dump_mic_level_ = 0;
206 
207  protected:
208   size_t output_reset_counter_ = 0;
209 
210  private:
211   void SetupOutput();
212 
213   size_t num_process_stream_calls_ = 0;
214   size_t num_reverse_process_stream_calls_ = 0;
215   std::unique_ptr<ChannelBufferWavWriter> buffer_file_writer_;
216   std::unique_ptr<ChannelBufferWavWriter> reverse_buffer_file_writer_;
217   std::unique_ptr<ChannelBufferVectorWriter> buffer_memory_writer_;
218   std::unique_ptr<WavWriter> linear_aec_output_file_writer_;
219   ApiCallStatistics api_call_statistics_;
220   std::ofstream residual_echo_likelihood_graph_writer_;
221   int analog_mic_level_;
222   FakeRecordingDevice fake_recording_device_;
223 
224   TaskQueueForTest worker_queue_;
225 
226   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioProcessingSimulator);
227 };
228 
229 }  // namespace test
230 }  // namespace webrtc
231 
232 #endif  // MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_
233