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