NetEq: Fix bug in PLC for multi-channel audio

There is currently a bug in NetEq that causes audio to leak from the
first channel to all others during loss concealment. This CL fixes the
problem and also adds a unit test to verify.

Bug: webrtc:11145
Change-Id: Ia6c4a234ff7f78e9a6080f1cb17eb80af671c3dc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161091
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29974}
This commit is contained in:
Henrik Lundin
2019-12-02 15:46:00 +01:00
committed by Commit Bot
parent 5256d8bc4b
commit 21021f022b
2 changed files with 47 additions and 2 deletions

View File

@ -469,6 +469,14 @@ void Expand::AnalyzeSignal(int16_t* random_vector) {
for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
ChannelParameters& parameters = channel_parameters_[channel_ix];
if (channel_ix > 0) {
// When channel_ix == 0, audio_history contains the correct audio. For the
// other cases, we will have to copy the correct channel into
// audio_history.
(*sync_buffer_)[channel_ix].CopyTo(signal_length, audio_history_position,
audio_history.get());
}
// Calculate suitable scaling.
int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
&audio_history[signal_length - correlation_length - start_index -

View File

@ -111,8 +111,7 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
}
int next_send_time = rtp_generator_mono_.GetRtpHeader(
kPayloadTypeMono, frame_size_samples_, &rtp_header_mono_);
test::InputAudioFile::DuplicateInterleaved(
input_, frame_size_samples_, num_channels_, input_multi_channel_);
MakeMultiChannelInput();
multi_payload_size_bytes_ = WebRtcPcm16b_Encode(
input_multi_channel_, frame_size_samples_ * num_channels_,
encoded_multi_channel_);
@ -124,6 +123,11 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
return next_send_time;
}
virtual void MakeMultiChannelInput() {
test::InputAudioFile::DuplicateInterleaved(
input_, frame_size_samples_, num_channels_, input_multi_channel_);
}
virtual void VerifyOutput(size_t num_samples) {
const int16_t* output_data = output_.data();
const int16_t* output_multi_channel_data = output_multi_channel_.data();
@ -330,6 +334,36 @@ TEST_P(NetEqStereoTestLosses, RunTest) {
RunTest(100);
}
class NetEqStereoTestSingleActiveChannelPlc : public NetEqStereoTestLosses {
protected:
NetEqStereoTestSingleActiveChannelPlc() : NetEqStereoTestLosses() {}
virtual void MakeMultiChannelInput() override {
// Create a multi-channel input by copying the mono channel from file to the
// first channel, and setting the others to zero.
memset(input_multi_channel_, 0,
frame_size_samples_ * num_channels_ * sizeof(int16_t));
for (size_t i = 0; i < frame_size_samples_; ++i) {
input_multi_channel_[i * num_channels_] = input_[i];
}
}
virtual void VerifyOutput(size_t num_samples) override {
// Simply verify that all samples in channels other than the first are zero.
const int16_t* output_multi_channel_data = output_multi_channel_.data();
for (size_t i = 0; i < num_samples; ++i) {
for (size_t j = 1; j < num_channels_; ++j) {
EXPECT_EQ(0, output_multi_channel_data[i * num_channels_ + j])
<< "Sample " << i << ", channel " << j << " is non-zero.";
}
}
}
};
TEST_P(NetEqStereoTestSingleActiveChannelPlc, RunTest) {
RunTest(100);
}
// Creates a list of parameter sets.
std::list<TestParameters> GetTestParameters() {
std::list<TestParameters> l;
@ -384,4 +418,7 @@ INSTANTIATE_TEST_SUITE_P(MultiChannel,
NetEqStereoTestLosses,
::testing::ValuesIn(GetTestParameters()));
INSTANTIATE_TEST_SUITE_P(MultiChannel,
NetEqStereoTestSingleActiveChannelPlc,
::testing::ValuesIn(GetTestParameters()));
} // namespace webrtc