When recreating a call based on an aecdump recording the nearend used
is the one stored in the aecdump. During AEC development, it is handy to be able to simulate different doubletalk scenarios. This CL adds the ability to add an artificial nearend on top of that present in the aecdump, which allows for the developer to artificially customize the scenario being tested BUG=webrtc:6018 Review-Url: https://codereview.webrtc.org/2562593003 Cr-Commit-Position: refs/heads/master@{#15502}
This commit is contained in:
@ -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<int16_t>(
|
||||
fwd_frame_.data_[k] +
|
||||
static_cast<int16_t>(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<WavReader> 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<float>(
|
||||
rtc::CheckedDivExact(artificial_nearend_file->sample_rate(),
|
||||
kChunksPerSecond),
|
||||
1));
|
||||
}
|
||||
|
||||
webrtc::audioproc::Event event_msg;
|
||||
int num_forward_chunks_processed = 0;
|
||||
const float kOneBykChunksPerSecond =
|
||||
|
||||
@ -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<ChannelBuffer<float>> artificial_nearend_buf_;
|
||||
std::unique_ptr<ChannelBufferWavReader> artificial_nearend_buffer_reader_;
|
||||
bool artificial_nearend_eof_reported_ = false;
|
||||
InterfaceType interface_used_ = InterfaceType::kNotSpecified;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecDumpBasedSimulator);
|
||||
|
||||
@ -44,6 +44,7 @@ struct SimulationSettings {
|
||||
rtc::Optional<std::string> reverse_output_filename;
|
||||
rtc::Optional<std::string> input_filename;
|
||||
rtc::Optional<std::string> reverse_input_filename;
|
||||
rtc::Optional<std::string> artificial_nearend_filename;
|
||||
rtc::Optional<bool> use_aec;
|
||||
rtc::Optional<bool> use_aecm;
|
||||
rtc::Optional<bool> use_ed; // Residual Echo Detector.
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user