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/task_queue_for_test.h" 28 #include "rtc_base/time_utils.h" 29 30 namespace webrtc { 31 namespace test { 32 33 static const int kChunksPerSecond = 1000 / AudioProcessing::kChunkSizeMs; 34 35 struct Int16Frame { SetFormatInt16Frame36 void SetFormat(int sample_rate_hz, int num_channels) { 37 this->sample_rate_hz = sample_rate_hz; 38 samples_per_channel = 39 rtc::CheckedDivExact(sample_rate_hz, kChunksPerSecond); 40 this->num_channels = num_channels; 41 config = StreamConfig(sample_rate_hz, num_channels); 42 data.resize(num_channels * samples_per_channel); 43 } 44 CopyToInt16Frame45 void CopyTo(ChannelBuffer<float>* dest) { 46 RTC_DCHECK(dest); 47 RTC_CHECK_EQ(num_channels, dest->num_channels()); 48 RTC_CHECK_EQ(samples_per_channel, dest->num_frames()); 49 // Copy the data from the input buffer. 50 std::vector<float> tmp(samples_per_channel * num_channels); 51 S16ToFloat(data.data(), tmp.size(), tmp.data()); 52 Deinterleave(tmp.data(), samples_per_channel, num_channels, 53 dest->channels()); 54 } 55 CopyFromInt16Frame56 void CopyFrom(const ChannelBuffer<float>& src) { 57 RTC_CHECK_EQ(src.num_channels(), num_channels); 58 RTC_CHECK_EQ(src.num_frames(), samples_per_channel); 59 data.resize(num_channels * samples_per_channel); 60 int16_t* dest_data = data.data(); 61 for (int ch = 0; ch < num_channels; ++ch) { 62 for (int sample = 0; sample < samples_per_channel; ++sample) { 63 dest_data[sample * num_channels + ch] = 64 src.channels()[ch][sample] * 32767; 65 } 66 } 67 } 68 69 int sample_rate_hz; 70 int samples_per_channel; 71 int num_channels; 72 73 StreamConfig config; 74 75 std::vector<int16_t> data; 76 }; 77 78 // Holds all the parameters available for controlling the simulation. 79 struct SimulationSettings { 80 SimulationSettings(); 81 SimulationSettings(const SimulationSettings&); 82 ~SimulationSettings(); 83 absl::optional<int> stream_delay; 84 absl::optional<bool> use_stream_delay; 85 absl::optional<int> output_sample_rate_hz; 86 absl::optional<int> output_num_channels; 87 absl::optional<int> reverse_output_sample_rate_hz; 88 absl::optional<int> reverse_output_num_channels; 89 absl::optional<std::string> output_filename; 90 absl::optional<std::string> reverse_output_filename; 91 absl::optional<std::string> input_filename; 92 absl::optional<std::string> reverse_input_filename; 93 absl::optional<std::string> artificial_nearend_filename; 94 absl::optional<std::string> linear_aec_output_filename; 95 absl::optional<bool> use_aec; 96 absl::optional<bool> use_aecm; 97 absl::optional<bool> use_ed; // Residual Echo Detector. 98 absl::optional<std::string> ed_graph_output_filename; 99 absl::optional<bool> use_agc; 100 absl::optional<bool> use_agc2; 101 absl::optional<bool> use_pre_amplifier; 102 absl::optional<bool> use_capture_level_adjustment; 103 absl::optional<bool> use_analog_mic_gain_emulation; 104 absl::optional<bool> use_hpf; 105 absl::optional<bool> use_ns; 106 absl::optional<int> use_ts; 107 absl::optional<bool> use_analog_agc; 108 absl::optional<bool> use_all; 109 absl::optional<bool> analog_agc_use_digital_adaptive_controller; 110 absl::optional<int> agc_mode; 111 absl::optional<int> agc_target_level; 112 absl::optional<bool> use_agc_limiter; 113 absl::optional<int> agc_compression_gain; 114 absl::optional<bool> agc2_use_adaptive_gain; 115 absl::optional<float> agc2_fixed_gain_db; 116 absl::optional<float> pre_amplifier_gain_factor; 117 absl::optional<float> pre_gain_factor; 118 absl::optional<float> post_gain_factor; 119 absl::optional<float> analog_mic_gain_emulation_initial_level; 120 absl::optional<int> ns_level; 121 absl::optional<bool> ns_analysis_on_linear_aec_output; 122 absl::optional<bool> override_key_pressed; 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 absl::optional<int> frame_for_sending_capture_output_used_false; 130 absl::optional<int> frame_for_sending_capture_output_used_true; 131 bool report_performance = false; 132 absl::optional<std::string> performance_report_output_filename; 133 bool report_bitexactness = false; 134 bool use_verbose_logging = false; 135 bool use_quiet_output = false; 136 bool discard_all_settings_in_aecdump = true; 137 absl::optional<std::string> aec_dump_input_filename; 138 absl::optional<std::string> aec_dump_output_filename; 139 bool fixed_interface = false; 140 bool store_intermediate_output = false; 141 bool print_aec_parameter_values = false; 142 bool dump_internal_data = false; 143 WavFile::SampleFormat wav_output_format = WavFile::SampleFormat::kInt16; 144 absl::optional<std::string> dump_internal_data_output_dir; 145 absl::optional<int> dump_set_to_use; 146 absl::optional<std::string> call_order_input_filename; 147 absl::optional<std::string> call_order_output_filename; 148 absl::optional<std::string> aec_settings_filename; 149 absl::optional<absl::string_view> aec_dump_input_string; 150 std::vector<float>* processed_capture_samples = nullptr; 151 bool analysis_only = false; 152 absl::optional<int> dump_start_frame; 153 absl::optional<int> dump_end_frame; 154 absl::optional<int> init_to_process; 155 }; 156 157 // Provides common functionality for performing audioprocessing simulations. 158 class AudioProcessingSimulator { 159 public: 160 AudioProcessingSimulator(const SimulationSettings& settings, 161 rtc::scoped_refptr<AudioProcessing> audio_processing, 162 std::unique_ptr<AudioProcessingBuilder> ap_builder); 163 164 AudioProcessingSimulator() = delete; 165 AudioProcessingSimulator(const AudioProcessingSimulator&) = delete; 166 AudioProcessingSimulator& operator=(const AudioProcessingSimulator&) = delete; 167 168 virtual ~AudioProcessingSimulator(); 169 170 // Processes the data in the input. 171 virtual void Process() = 0; 172 173 // Returns the execution times of all AudioProcessing calls. GetApiCallStatistics()174 const ApiCallStatistics& GetApiCallStatistics() const { 175 return api_call_statistics_; 176 } 177 178 // Analyzes the data in the input and reports the resulting statistics. 179 virtual void Analyze() = 0; 180 181 // Reports whether the processed recording was bitexact. OutputWasBitexact()182 bool OutputWasBitexact() { return bitexact_output_; } 183 get_num_process_stream_calls()184 size_t get_num_process_stream_calls() { return num_process_stream_calls_; } get_num_reverse_process_stream_calls()185 size_t get_num_reverse_process_stream_calls() { 186 return num_reverse_process_stream_calls_; 187 } 188 189 protected: 190 void ProcessStream(bool fixed_interface); 191 void ProcessReverseStream(bool fixed_interface); 192 void ConfigureAudioProcessor(); 193 void DetachAecDump(); 194 void SetupBuffersConfigsOutputs(int input_sample_rate_hz, 195 int output_sample_rate_hz, 196 int reverse_input_sample_rate_hz, 197 int reverse_output_sample_rate_hz, 198 int input_num_channels, 199 int output_num_channels, 200 int reverse_input_num_channels, 201 int reverse_output_num_channels); 202 void SelectivelyToggleDataDumping(int init_index, 203 int capture_frames_since_init) const; 204 205 const SimulationSettings settings_; 206 rtc::scoped_refptr<AudioProcessing> ap_; 207 208 std::unique_ptr<ChannelBuffer<float>> in_buf_; 209 std::unique_ptr<ChannelBuffer<float>> out_buf_; 210 std::unique_ptr<ChannelBuffer<float>> reverse_in_buf_; 211 std::unique_ptr<ChannelBuffer<float>> reverse_out_buf_; 212 std::vector<std::array<float, 160>> linear_aec_output_buf_; 213 StreamConfig in_config_; 214 StreamConfig out_config_; 215 StreamConfig reverse_in_config_; 216 StreamConfig reverse_out_config_; 217 std::unique_ptr<ChannelBufferWavReader> buffer_reader_; 218 std::unique_ptr<ChannelBufferWavReader> reverse_buffer_reader_; 219 Int16Frame rev_frame_; 220 Int16Frame fwd_frame_; 221 bool bitexact_output_ = true; 222 absl::optional<int> aec_dump_applied_input_level_ = 0; 223 224 protected: 225 size_t output_reset_counter_ = 0; 226 227 private: 228 void SetupOutput(); 229 230 size_t num_process_stream_calls_ = 0; 231 size_t num_reverse_process_stream_calls_ = 0; 232 std::unique_ptr<ChannelBufferWavWriter> buffer_file_writer_; 233 std::unique_ptr<ChannelBufferWavWriter> reverse_buffer_file_writer_; 234 std::unique_ptr<ChannelBufferVectorWriter> buffer_memory_writer_; 235 std::unique_ptr<WavWriter> linear_aec_output_file_writer_; 236 ApiCallStatistics api_call_statistics_; 237 std::ofstream residual_echo_likelihood_graph_writer_; 238 int applied_input_volume_; 239 FakeRecordingDevice fake_recording_device_; 240 241 TaskQueueForTest worker_queue_; 242 }; 243 244 } // namespace test 245 } // namespace webrtc 246 247 #endif // MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_ 248