debug_dump_replayer.cc (8293B)
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/debug_dump_replayer.h" 12 13 #include <cstddef> 14 #include <cstdio> 15 #include <cstring> 16 #include <memory> 17 #include <optional> 18 #include <string> 19 20 #include "absl/strings/string_view.h" 21 #include "api/audio/audio_processing.h" 22 #include "api/audio/builtin_audio_processing_builder.h" 23 #include "api/environment/environment_factory.h" 24 #include "common_audio/channel_buffer.h" 25 #include "modules/audio_processing/test/protobuf_utils.h" 26 #include "modules/audio_processing/test/runtime_setting_util.h" 27 #include "rtc_base/checks.h" 28 29 namespace webrtc { 30 namespace test { 31 32 namespace { 33 34 void MaybeResetBuffer(std::unique_ptr<ChannelBuffer<float>>* buffer, 35 const StreamConfig& config) { 36 auto& buffer_ref = *buffer; 37 if (!buffer_ref || buffer_ref->num_frames() != config.num_frames() || 38 buffer_ref->num_channels() != config.num_channels()) { 39 buffer_ref.reset( 40 new ChannelBuffer<float>(config.num_frames(), config.num_channels())); 41 } 42 } 43 44 } // namespace 45 46 DebugDumpReplayer::DebugDumpReplayer() 47 : input_(nullptr), // will be created upon usage. 48 reverse_(nullptr), 49 output_(nullptr), 50 apm_(nullptr), 51 debug_file_(nullptr) {} 52 53 DebugDumpReplayer::~DebugDumpReplayer() { 54 if (debug_file_) 55 fclose(debug_file_); 56 } 57 58 bool DebugDumpReplayer::SetDumpFile(absl::string_view filename) { 59 debug_file_ = fopen(std::string(filename).c_str(), "rb"); 60 LoadNextMessage(); 61 return debug_file_; 62 } 63 64 // Get next event that has not run. 65 std::optional<audioproc::Event> DebugDumpReplayer::GetNextEvent() const { 66 if (!has_next_event_) 67 return std::nullopt; 68 else 69 return next_event_; 70 } 71 72 // Run the next event. Returns the event type. 73 bool DebugDumpReplayer::RunNextEvent() { 74 if (!has_next_event_) 75 return false; 76 switch (next_event_.type()) { 77 case audioproc::Event::INIT: 78 OnInitEvent(next_event_.init()); 79 break; 80 case audioproc::Event::STREAM: 81 OnStreamEvent(next_event_.stream()); 82 break; 83 case audioproc::Event::REVERSE_STREAM: 84 OnReverseStreamEvent(next_event_.reverse_stream()); 85 break; 86 case audioproc::Event::CONFIG: 87 OnConfigEvent(next_event_.config()); 88 break; 89 case audioproc::Event::RUNTIME_SETTING: 90 OnRuntimeSettingEvent(next_event_.runtime_setting()); 91 break; 92 case audioproc::Event::UNKNOWN_EVENT: 93 // We do not expect to receive UNKNOWN event. 94 RTC_CHECK_NOTREACHED(); 95 } 96 LoadNextMessage(); 97 return true; 98 } 99 100 const ChannelBuffer<float>* DebugDumpReplayer::GetOutput() const { 101 return output_.get(); 102 } 103 104 StreamConfig DebugDumpReplayer::GetOutputConfig() const { 105 return output_config_; 106 } 107 108 // OnInitEvent reset the input/output/reserve channel format. 109 void DebugDumpReplayer::OnInitEvent(const audioproc::Init& msg) { 110 RTC_CHECK(msg.has_num_input_channels()); 111 RTC_CHECK(msg.has_output_sample_rate()); 112 RTC_CHECK(msg.has_num_output_channels()); 113 RTC_CHECK(msg.has_reverse_sample_rate()); 114 RTC_CHECK(msg.has_num_reverse_channels()); 115 116 input_config_ = StreamConfig(msg.sample_rate(), msg.num_input_channels()); 117 output_config_ = 118 StreamConfig(msg.output_sample_rate(), msg.num_output_channels()); 119 reverse_config_ = 120 StreamConfig(msg.reverse_sample_rate(), msg.num_reverse_channels()); 121 122 MaybeResetBuffer(&input_, input_config_); 123 MaybeResetBuffer(&output_, output_config_); 124 MaybeResetBuffer(&reverse_, reverse_config_); 125 } 126 127 // OnStreamEvent replays an input signal and verifies the output. 128 void DebugDumpReplayer::OnStreamEvent(const audioproc::Stream& msg) { 129 // APM should have been created. 130 RTC_CHECK(apm_.get()); 131 132 if (msg.has_applied_input_volume()) { 133 apm_->set_stream_analog_level(msg.applied_input_volume()); 134 } 135 RTC_CHECK_EQ(AudioProcessing::kNoError, 136 apm_->set_stream_delay_ms(msg.delay())); 137 138 if (msg.has_keypress()) { 139 apm_->set_stream_key_pressed(msg.keypress()); 140 } else { 141 apm_->set_stream_key_pressed(true); 142 } 143 144 RTC_CHECK_EQ(input_config_.num_channels(), 145 static_cast<size_t>(msg.input_channel_size())); 146 RTC_CHECK_EQ(input_config_.num_frames() * sizeof(float), 147 msg.input_channel(0).size()); 148 149 for (int i = 0; i < msg.input_channel_size(); ++i) { 150 memcpy(input_->channels()[i], msg.input_channel(i).data(), 151 msg.input_channel(i).size()); 152 } 153 154 RTC_CHECK_EQ(AudioProcessing::kNoError, 155 apm_->ProcessStream(input_->channels(), input_config_, 156 output_config_, output_->channels())); 157 } 158 159 void DebugDumpReplayer::OnReverseStreamEvent( 160 const audioproc::ReverseStream& msg) { 161 // APM should have been created. 162 RTC_CHECK(apm_.get()); 163 164 RTC_CHECK_GT(msg.channel_size(), 0); 165 RTC_CHECK_EQ(reverse_config_.num_channels(), 166 static_cast<size_t>(msg.channel_size())); 167 RTC_CHECK_EQ(reverse_config_.num_frames() * sizeof(float), 168 msg.channel(0).size()); 169 170 for (int i = 0; i < msg.channel_size(); ++i) { 171 memcpy(reverse_->channels()[i], msg.channel(i).data(), 172 msg.channel(i).size()); 173 } 174 175 RTC_CHECK_EQ( 176 AudioProcessing::kNoError, 177 apm_->ProcessReverseStream(reverse_->channels(), reverse_config_, 178 reverse_config_, reverse_->channels())); 179 } 180 181 void DebugDumpReplayer::OnConfigEvent(const audioproc::Config& msg) { 182 MaybeRecreateApm(msg); 183 ConfigureApm(msg); 184 } 185 186 void DebugDumpReplayer::OnRuntimeSettingEvent( 187 const audioproc::RuntimeSetting& msg) { 188 RTC_CHECK(apm_.get()); 189 ReplayRuntimeSetting(apm_.get(), msg); 190 } 191 192 void DebugDumpReplayer::MaybeRecreateApm(const audioproc::Config& msg) { 193 // These configurations cannot be changed on the fly. 194 RTC_CHECK(msg.has_aec_delay_agnostic_enabled()); 195 RTC_CHECK(msg.has_aec_extended_filter_enabled()); 196 197 // We only create APM once, since changes on these fields should not 198 // happen in current implementation. 199 if (apm_ == nullptr) { 200 apm_ = BuiltinAudioProcessingBuilder().Build(CreateEnvironment()); 201 } 202 } 203 204 void DebugDumpReplayer::ConfigureApm(const audioproc::Config& msg) { 205 AudioProcessing::Config apm_config; 206 207 // AEC2/AECM configs. 208 RTC_CHECK(msg.has_aec_enabled()); 209 RTC_CHECK(msg.has_aecm_enabled()); 210 apm_config.echo_canceller.enabled = msg.aec_enabled() || msg.aecm_enabled(); 211 apm_config.echo_canceller.mobile_mode = msg.aecm_enabled(); 212 213 // HPF configs. 214 RTC_CHECK(msg.has_hpf_enabled()); 215 apm_config.high_pass_filter.enabled = msg.hpf_enabled(); 216 217 // Preamp configs. 218 RTC_CHECK(msg.has_pre_amplifier_enabled()); 219 apm_config.pre_amplifier.enabled = msg.pre_amplifier_enabled(); 220 apm_config.pre_amplifier.fixed_gain_factor = 221 msg.pre_amplifier_fixed_gain_factor(); 222 223 // NS configs. 224 RTC_CHECK(msg.has_ns_enabled()); 225 RTC_CHECK(msg.has_ns_level()); 226 apm_config.noise_suppression.enabled = msg.ns_enabled(); 227 apm_config.noise_suppression.level = 228 static_cast<AudioProcessing::Config::NoiseSuppression::Level>( 229 msg.ns_level()); 230 231 // TS configs. 232 RTC_CHECK(msg.has_transient_suppression_enabled()); 233 apm_config.transient_suppression.enabled = 234 msg.transient_suppression_enabled(); 235 236 // AGC configs. 237 RTC_CHECK(msg.has_agc_enabled()); 238 RTC_CHECK(msg.has_agc_mode()); 239 RTC_CHECK(msg.has_agc_limiter_enabled()); 240 apm_config.gain_controller1.enabled = msg.agc_enabled(); 241 apm_config.gain_controller1.mode = 242 static_cast<AudioProcessing::Config::GainController1::Mode>( 243 msg.agc_mode()); 244 apm_config.gain_controller1.enable_limiter = msg.agc_limiter_enabled(); 245 RTC_CHECK(msg.has_noise_robust_agc_enabled()); 246 apm_config.gain_controller1.analog_gain_controller.enabled = 247 msg.noise_robust_agc_enabled(); 248 249 apm_->ApplyConfig(apm_config); 250 } 251 252 void DebugDumpReplayer::LoadNextMessage() { 253 has_next_event_ = 254 debug_file_ && ReadMessageFromFile(debug_file_, &next_event_); 255 } 256 257 } // namespace test 258 } // namespace webrtc