diff --git a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc index 694f2cd90c..b117dbbebe 100644 --- a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc +++ b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc @@ -62,6 +62,11 @@ bool VerifyFloatBitExactness(const webrtc::audioproc::Stream& msg, } // namespace +AecDumpBasedSimulator::AecDumpBasedSimulator(const SimulationSettings& settings) + : AudioProcessingSimulator(settings) {} + +AecDumpBasedSimulator::~AecDumpBasedSimulator() = default; + void AecDumpBasedSimulator::PrepareProcessStreamCall( const webrtc::audioproc::Stream& msg, bool* set_stream_analog_level_called) { @@ -96,6 +101,34 @@ void AecDumpBasedSimulator::PrepareProcessStreamCall( } } + if (artificial_nearend_buffer_reader_) { + if (artificial_nearend_buffer_reader_->Read( + artificial_nearend_buf_.get())) { + if (msg.has_input_data()) { + for (size_t k = 0; k < in_buf_->num_frames(); ++k) { + fwd_frame_.data_[k] = rtc::saturated_cast( + fwd_frame_.data_[k] + + static_cast(32767 * + artificial_nearend_buf_->channels()[0][k])); + } + } else { + for (int i = 0; i < msg.input_channel_size(); ++i) { + for (size_t k = 0; k < in_buf_->num_frames(); ++k) { + in_buf_->channels()[i][k] += + artificial_nearend_buf_->channels()[0][k]; + in_buf_->channels()[i][k] = std::min( + 32767.f, std::max(-32768.f, in_buf_->channels()[i][k])); + } + } + } + } else { + if (!artificial_nearend_eof_reported_) { + std::cout << "The artificial nearend file ended before the recording."; + artificial_nearend_eof_reported_ = true; + } + } + } + if (!settings_.stream_delay) { if (msg.has_delay()) { RTC_CHECK_EQ(AudioProcessing::kNoError, @@ -189,6 +222,22 @@ void AecDumpBasedSimulator::Process() { CreateAudioProcessor(); dump_input_file_ = OpenFile(settings_.aec_dump_input_filename->c_str(), "rb"); + if (settings_.artificial_nearend_filename) { + std::unique_ptr artificial_nearend_file( + new WavReader(settings_.artificial_nearend_filename->c_str())); + + RTC_CHECK_EQ(1, artificial_nearend_file->num_channels()) + << "Only mono files for the artificial nearend are supported, " + "reverted to not using the artificial nearend file"; + + artificial_nearend_buffer_reader_.reset( + new ChannelBufferWavReader(std::move(artificial_nearend_file))); + artificial_nearend_buf_.reset(new ChannelBuffer( + rtc::CheckedDivExact(artificial_nearend_file->sample_rate(), + kChunksPerSecond), + 1)); + } + webrtc::audioproc::Event event_msg; int num_forward_chunks_processed = 0; const float kOneBykChunksPerSecond = diff --git a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h index 7f98f43b66..5f7d138aa4 100644 --- a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h +++ b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h @@ -30,9 +30,8 @@ namespace test { // Used to perform an audio processing simulation from an aec dump. class AecDumpBasedSimulator final : public AudioProcessingSimulator { public: - explicit AecDumpBasedSimulator(const SimulationSettings& settings) - : AudioProcessingSimulator(settings) {} - ~AecDumpBasedSimulator() override {} + explicit AecDumpBasedSimulator(const SimulationSettings& settings); + ~AecDumpBasedSimulator() override; // Processes the messages in the aecdump file. void Process() override; @@ -55,6 +54,9 @@ class AecDumpBasedSimulator final : public AudioProcessingSimulator { }; FILE* dump_input_file_; + std::unique_ptr> artificial_nearend_buf_; + std::unique_ptr artificial_nearend_buffer_reader_; + bool artificial_nearend_eof_reported_ = false; InterfaceType interface_used_ = InterfaceType::kNotSpecified; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecDumpBasedSimulator); diff --git a/webrtc/modules/audio_processing/test/audio_processing_simulator.h b/webrtc/modules/audio_processing/test/audio_processing_simulator.h index 7becdb9a6b..2564dc4bf2 100644 --- a/webrtc/modules/audio_processing/test/audio_processing_simulator.h +++ b/webrtc/modules/audio_processing/test/audio_processing_simulator.h @@ -44,6 +44,7 @@ struct SimulationSettings { rtc::Optional reverse_output_filename; rtc::Optional input_filename; rtc::Optional reverse_input_filename; + rtc::Optional artificial_nearend_filename; rtc::Optional use_aec; rtc::Optional use_aecm; rtc::Optional use_ed; // Residual Echo Detector. diff --git a/webrtc/modules/audio_processing/test/audioproc_float.cc b/webrtc/modules/audio_processing/test/audioproc_float.cc index a91480d265..edc775986f 100644 --- a/webrtc/modules/audio_processing/test/audioproc_float.cc +++ b/webrtc/modules/audio_processing/test/audioproc_float.cc @@ -40,6 +40,7 @@ DEFINE_string(i, "", "Forward stream input wav filename"); DEFINE_string(o, "", "Forward stream output wav filename"); DEFINE_string(ri, "", "Reverse stream input wav filename"); DEFINE_string(ro, "", "Reverse stream output wav filename"); +DEFINE_string(artificial_nearend, "", "Artificial nearend wav filename"); DEFINE_int32(output_num_channels, kParameterNotSpecifiedValue, "Number of forward stream output channels"); @@ -208,6 +209,8 @@ SimulationSettings CreateSettings() { SetSettingIfSpecified(FLAGS_o, &settings.output_filename); SetSettingIfSpecified(FLAGS_ri, &settings.reverse_input_filename); SetSettingIfSpecified(FLAGS_ro, &settings.reverse_output_filename); + SetSettingIfSpecified(FLAGS_artificial_nearend, + &settings.artificial_nearend_filename); SetSettingIfSpecified(FLAGS_output_num_channels, &settings.output_num_channels); SetSettingIfSpecified(FLAGS_reverse_output_num_channels, @@ -277,6 +280,10 @@ void PerformBasicParameterSanityChecks(const SimulationSettings& settings) { "Error: The aec dump cannot be specified " "together with input wav files!\n"); + ReportConditionalErrorAndExit(!!settings.artificial_nearend_filename, + "Error: The artificial nearend cannot be " + "specified together with input wav files!\n"); + ReportConditionalErrorAndExit(!settings.input_filename, "Error: When operating at wav files, the " "input wav filename must be " @@ -389,6 +396,11 @@ void PerformBasicParameterSanityChecks(const SimulationSettings& settings) { settings.reverse_output_filename && (!valid_wav_name(*settings.reverse_output_filename)), "Error: --ro must be a valid .wav file name.\n"); + + ReportConditionalErrorAndExit( + settings.artificial_nearend_filename && + !valid_wav_name(*settings.artificial_nearend_filename), + "Error: --artifical_nearend must be a valid .wav file name.\n"); } } // namespace