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:

committed by
Commit Bot

parent
5256d8bc4b
commit
21021f022b
@ -469,6 +469,14 @@ void Expand::AnalyzeSignal(int16_t* random_vector) {
|
|||||||
|
|
||||||
for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
|
for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
|
||||||
ChannelParameters& parameters = channel_parameters_[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.
|
// Calculate suitable scaling.
|
||||||
int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
|
int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
|
||||||
&audio_history[signal_length - correlation_length - start_index -
|
&audio_history[signal_length - correlation_length - start_index -
|
||||||
|
@ -111,8 +111,7 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
|||||||
}
|
}
|
||||||
int next_send_time = rtp_generator_mono_.GetRtpHeader(
|
int next_send_time = rtp_generator_mono_.GetRtpHeader(
|
||||||
kPayloadTypeMono, frame_size_samples_, &rtp_header_mono_);
|
kPayloadTypeMono, frame_size_samples_, &rtp_header_mono_);
|
||||||
test::InputAudioFile::DuplicateInterleaved(
|
MakeMultiChannelInput();
|
||||||
input_, frame_size_samples_, num_channels_, input_multi_channel_);
|
|
||||||
multi_payload_size_bytes_ = WebRtcPcm16b_Encode(
|
multi_payload_size_bytes_ = WebRtcPcm16b_Encode(
|
||||||
input_multi_channel_, frame_size_samples_ * num_channels_,
|
input_multi_channel_, frame_size_samples_ * num_channels_,
|
||||||
encoded_multi_channel_);
|
encoded_multi_channel_);
|
||||||
@ -124,6 +123,11 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
|||||||
return next_send_time;
|
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) {
|
virtual void VerifyOutput(size_t num_samples) {
|
||||||
const int16_t* output_data = output_.data();
|
const int16_t* output_data = output_.data();
|
||||||
const int16_t* output_multi_channel_data = output_multi_channel_.data();
|
const int16_t* output_multi_channel_data = output_multi_channel_.data();
|
||||||
@ -330,6 +334,36 @@ TEST_P(NetEqStereoTestLosses, RunTest) {
|
|||||||
RunTest(100);
|
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.
|
// Creates a list of parameter sets.
|
||||||
std::list<TestParameters> GetTestParameters() {
|
std::list<TestParameters> GetTestParameters() {
|
||||||
std::list<TestParameters> l;
|
std::list<TestParameters> l;
|
||||||
@ -384,4 +418,7 @@ INSTANTIATE_TEST_SUITE_P(MultiChannel,
|
|||||||
NetEqStereoTestLosses,
|
NetEqStereoTestLosses,
|
||||||
::testing::ValuesIn(GetTestParameters()));
|
::testing::ValuesIn(GetTestParameters()));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(MultiChannel,
|
||||||
|
NetEqStereoTestSingleActiveChannelPlc,
|
||||||
|
::testing::ValuesIn(GetTestParameters()));
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Reference in New Issue
Block a user