diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc index f40250f2d..0c7e6c721 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc @@ -210,29 +210,25 @@ int AcmReceiver::current_sample_rate_hz() const { // TODO(turajs): use one set of enumerators, e.g. the one defined in // common_types.h +// TODO(henrik.lundin): This method is not used any longer. The call hierarchy +// stops in voe::Channel::SetNetEQPlayoutMode(). Remove it. void AcmReceiver::SetPlayoutMode(AudioPlayoutMode mode) { enum NetEqPlayoutMode playout_mode = kPlayoutOn; - enum NetEqBackgroundNoiseMode bgn_mode = kBgnOn; switch (mode) { case voice: playout_mode = kPlayoutOn; - bgn_mode = kBgnOn; break; case fax: // No change to background noise mode. playout_mode = kPlayoutFax; - bgn_mode = neteq_->BackgroundNoiseMode(); break; case streaming: playout_mode = kPlayoutStreaming; - bgn_mode = kBgnOff; break; case off: playout_mode = kPlayoutOff; - bgn_mode = kBgnOff; break; } neteq_->SetPlayoutMode(playout_mode); - neteq_->SetBackgroundNoiseMode(bgn_mode); } AudioPlayoutMode AcmReceiver::PlayoutMode() const { @@ -800,10 +796,6 @@ bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) { return true; } -NetEqBackgroundNoiseMode AcmReceiver::BackgroundNoiseModeForTest() const { - return neteq_->BackgroundNoiseMode(); -} - int AcmReceiver::RtpHeaderToCodecIndex( const RTPHeader &rtp_header, const uint8_t* payload) const { uint8_t payload_type = rtp_header.payloadType; diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h index dd6de528f..180b4ba6b 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h @@ -307,12 +307,6 @@ class AcmReceiver { // std::vector GetNackList(int round_trip_time_ms) const; - // - // Returns the background noise mode. This is only for testing and ACM is not - // calling this function. Used in acm_receiver_unittest.cc. - // - NetEqBackgroundNoiseMode BackgroundNoiseModeForTest() const; - // // Get statistics of calls to GetAudio(). void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const; diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc index 4234f1464..81c97e5e1 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc @@ -247,34 +247,19 @@ TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(SampleRate)) { } } -// Changing playout mode to FAX should not change the background noise mode. -TEST_F(AcmReceiverTest, - DISABLED_ON_ANDROID(PlayoutModeAndBackgroundNoiseMode)) { - EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest()); // Default - +// Verify that the playout mode is set correctly. +TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PlayoutMode)) { receiver_->SetPlayoutMode(voice); EXPECT_EQ(voice, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest()); receiver_->SetPlayoutMode(streaming); EXPECT_EQ(streaming, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest()); receiver_->SetPlayoutMode(fax); EXPECT_EQ(fax, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest()); receiver_->SetPlayoutMode(off); EXPECT_EQ(off, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest()); - - // Change to voice then to FAX. - receiver_->SetPlayoutMode(voice); - EXPECT_EQ(voice, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest()); - receiver_->SetPlayoutMode(fax); - EXPECT_EQ(fax, receiver_->PlayoutMode()); - EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest()); } TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PostdecodingVad)) { diff --git a/webrtc/modules/audio_coding/neteq/background_noise.cc b/webrtc/modules/audio_coding/neteq/background_noise.cc index e00c4f65e..8d5a293b8 100644 --- a/webrtc/modules/audio_coding/neteq/background_noise.cc +++ b/webrtc/modules/audio_coding/neteq/background_noise.cc @@ -24,7 +24,7 @@ namespace webrtc { BackgroundNoise::BackgroundNoise(size_t num_channels) : num_channels_(num_channels), channel_parameters_(new ChannelParameters[num_channels_]), - mode_(kBgnOn) { + mode_(NetEq::kBgnOn) { Reset(); } diff --git a/webrtc/modules/audio_coding/neteq/background_noise.h b/webrtc/modules/audio_coding/neteq/background_noise.h index 8fb310ea8..5c9f39b63 100644 --- a/webrtc/modules/audio_coding/neteq/background_noise.h +++ b/webrtc/modules/audio_coding/neteq/background_noise.h @@ -68,11 +68,11 @@ class BackgroundNoise { // Accessors. bool initialized() const { return initialized_; } - NetEqBackgroundNoiseMode mode() const { return mode_; } + NetEq::BackgroundNoiseMode mode() const { return mode_; } // Sets the mode of the background noise playout for cases when there is long // duration of packet loss. - void set_mode(NetEqBackgroundNoiseMode mode) { mode_ = mode; } + void set_mode(NetEq::BackgroundNoiseMode mode) { mode_ = mode; } private: static const int kThresholdIncrement = 229; // 0.0035 in Q16. @@ -128,7 +128,7 @@ class BackgroundNoise { size_t num_channels_; scoped_ptr channel_parameters_; bool initialized_; - NetEqBackgroundNoiseMode mode_; + NetEq::BackgroundNoiseMode mode_; DISALLOW_COPY_AND_ASSIGN(BackgroundNoise); }; diff --git a/webrtc/modules/audio_coding/neteq/expand.cc b/webrtc/modules/audio_coding/neteq/expand.cc index 14a779822..3f7ed2414 100644 --- a/webrtc/modules/audio_coding/neteq/expand.cc +++ b/webrtc/modules/audio_coding/neteq/expand.cc @@ -806,7 +806,7 @@ void Expand::GenerateBackgroundNoise(int16_t* random_vector, int16_t* buffer) { static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder; int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125]; - assert(kMaxSampleRate / 8000 * 125 >= (int)num_noise_samples); + assert(static_cast(kMaxSampleRate / 8000 * 125) >= num_noise_samples); int16_t* noise_samples = &buffer[kNoiseLpcOrder]; if (background_noise_->initialized()) { // Use background noise parameters. @@ -838,8 +838,9 @@ void Expand::GenerateBackgroundNoise(int16_t* random_vector, // Unmute the background noise. int16_t bgn_mute_factor = background_noise_->MuteFactor(channel); - NetEqBackgroundNoiseMode bgn_mode = background_noise_->mode(); - if (bgn_mode == kBgnFade && too_many_expands && bgn_mute_factor > 0) { + NetEq::BackgroundNoiseMode bgn_mode = background_noise_->mode(); + if (bgn_mode == NetEq::kBgnFade && too_many_expands && + bgn_mute_factor > 0) { // Fade BGN to zero. // Calculate muting slope, approximately -2^18 / fs_hz. int16_t mute_slope; @@ -862,8 +863,8 @@ void Expand::GenerateBackgroundNoise(int16_t* random_vector, } else if (bgn_mute_factor < 16384) { // If mode is kBgnOff, or if kBgnFade has started fading, // Use regular |mute_slope|. - if (!stop_muting_ && bgn_mode != kBgnOff && - !(bgn_mode == kBgnFade && too_many_expands)) { + if (!stop_muting_ && bgn_mode != NetEq::kBgnOff && + !(bgn_mode == NetEq::kBgnFade && too_many_expands)) { DspHelper::UnmuteSignal(noise_samples, static_cast(num_noise_samples), &bgn_mute_factor, @@ -893,7 +894,7 @@ void Expand::GenerateRandomVector(int seed_increment, // just as good to generate all of the vector in one call. size_t samples_generated = 0; const size_t kMaxRandSamples = RandomVector::kRandomTableSize; - while(samples_generated < length) { + while (samples_generated < length) { size_t rand_length = std::min(length - samples_generated, kMaxRandSamples); random_vector_->IncreaseSeedIncrement(seed_increment); random_vector_->Generate(rand_length, &random_vector[samples_generated]); diff --git a/webrtc/modules/audio_coding/neteq/interface/neteq.h b/webrtc/modules/audio_coding/neteq/interface/neteq.h index c67ab12c6..fdd000aa5 100644 --- a/webrtc/modules/audio_coding/neteq/interface/neteq.h +++ b/webrtc/modules/audio_coding/neteq/interface/neteq.h @@ -58,27 +58,29 @@ enum NetEqPlayoutMode { kPlayoutStreaming }; -enum NetEqBackgroundNoiseMode { - kBgnOn, // Default behavior with eternal noise. - kBgnFade, // Noise fades to zero after some time. - kBgnOff // Background noise is always zero. -}; - // This is the interface class for NetEq. class NetEq { public: + enum BackgroundNoiseMode { + kBgnOn, // Default behavior with eternal noise. + kBgnFade, // Noise fades to zero after some time. + kBgnOff // Background noise is always zero. + }; + struct Config { Config() : sample_rate_hz(16000), enable_audio_classifier(false), max_packets_in_buffer(50), // |max_delay_ms| has the same effect as calling SetMaximumDelay(). - max_delay_ms(2000) {} + max_delay_ms(2000), + background_noise_mode(kBgnOn) {} int sample_rate_hz; // Initial vale. Will change with input data. bool enable_audio_classifier; int max_packets_in_buffer; int max_delay_ms; + BackgroundNoiseMode background_noise_mode; }; enum ReturnCodes { @@ -259,12 +261,6 @@ class NetEq { virtual int DecodedRtpInfo(int* sequence_number, uint32_t* timestamp) const = 0; - // Sets the background noise mode. - virtual void SetBackgroundNoiseMode(NetEqBackgroundNoiseMode mode) = 0; - - // Gets the background noise mode. - virtual NetEqBackgroundNoiseMode BackgroundNoiseMode() const = 0; - protected: NetEq() {} diff --git a/webrtc/modules/audio_coding/neteq/neteq.cc b/webrtc/modules/audio_coding/neteq/neteq.cc index 7edacde76..420165b3f 100644 --- a/webrtc/modules/audio_coding/neteq/neteq.cc +++ b/webrtc/modules/audio_coding/neteq/neteq.cc @@ -44,7 +44,7 @@ NetEq* NetEq::Create(const NetEq::Config& config) { ExpandFactory* expand_factory = new ExpandFactory; PreemptiveExpandFactory* preemptive_expand_factory = new PreemptiveExpandFactory; - return new NetEqImpl(config.sample_rate_hz, + return new NetEqImpl(config, buffer_level_filter, decoder_database, delay_manager, diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 64a866039..a184fc335 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -49,7 +49,7 @@ namespace webrtc { -NetEqImpl::NetEqImpl(int fs, +NetEqImpl::NetEqImpl(const NetEq::Config& config, BufferLevelFilter* buffer_level_filter, DecoderDatabase* decoder_database, DelayManager* delay_manager, @@ -90,8 +90,10 @@ NetEqImpl::NetEqImpl(int fs, first_packet_(true), error_code_(0), decoder_error_code_(0), + background_noise_mode_(config.background_noise_mode), decoded_packet_sequence_number_(-1), decoded_packet_timestamp_(0) { + int fs = config.sample_rate_hz; if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) { LOG(LS_ERROR) << "Sample rate " << fs << " Hz not supported. " << "Changing to 8000 Hz."; @@ -384,18 +386,6 @@ int NetEqImpl::DecodedRtpInfo(int* sequence_number, uint32_t* timestamp) const { return 0; } -void NetEqImpl::SetBackgroundNoiseMode(NetEqBackgroundNoiseMode mode) { - CriticalSectionScoped lock(crit_sect_.get()); - assert(background_noise_.get()); - background_noise_->set_mode(mode); -} - -NetEqBackgroundNoiseMode NetEqImpl::BackgroundNoiseMode() const { - CriticalSectionScoped lock(crit_sect_.get()); - assert(background_noise_.get()); - return background_noise_->mode(); -} - const SyncBuffer* NetEqImpl::sync_buffer_for_test() const { CriticalSectionScoped lock(crit_sect_.get()); return sync_buffer_.get(); @@ -1873,14 +1863,9 @@ void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) { // Delete sync buffer and create a new one. sync_buffer_.reset(new SyncBuffer(channels, kSyncBufferSize * fs_mult_)); - - // Delete BackgroundNoise object and create a new one, while preserving its - // mode. - NetEqBackgroundNoiseMode current_mode = kBgnOn; - if (background_noise_.get()) - current_mode = background_noise_->mode(); + // Delete BackgroundNoise object and create a new one. background_noise_.reset(new BackgroundNoise(channels)); - background_noise_->set_mode(current_mode); + background_noise_->set_mode(background_noise_mode_); // Reset random vector. random_vector_.Reset(); diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index e92babd8e..bc7734b46 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -58,7 +58,7 @@ class NetEqImpl : public webrtc::NetEq { public: // Creates a new NetEqImpl object. The object will assume ownership of all // injected dependencies, and will delete them when done. - NetEqImpl(int fs, + NetEqImpl(const NetEq::Config& config, BufferLevelFilter* buffer_level_filter, DecoderDatabase* decoder_database, DelayManager* delay_manager, @@ -191,12 +191,6 @@ class NetEqImpl : public webrtc::NetEq { // This method is to facilitate NACK. virtual int DecodedRtpInfo(int* sequence_number, uint32_t* timestamp) const; - // Sets background noise mode. - virtual void SetBackgroundNoiseMode(NetEqBackgroundNoiseMode mode); - - // Gets background noise mode. - virtual NetEqBackgroundNoiseMode BackgroundNoiseMode() const; - // This accessor method is only intended for testing purposes. virtual const SyncBuffer* sync_buffer_for_test() const; @@ -387,6 +381,7 @@ class NetEqImpl : public webrtc::NetEq { bool first_packet_ GUARDED_BY(crit_sect_); int error_code_ GUARDED_BY(crit_sect_); // Store last error code. int decoder_error_code_ GUARDED_BY(crit_sect_); + const BackgroundNoiseMode background_noise_mode_ GUARDED_BY(crit_sect_); // These values are used by NACK module to estimate time-to-play of // a missing packet. Occasionally, NetEq might decide to decode more diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index 2e66487fa..402d79db8 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -140,7 +140,7 @@ class NetEqImplTest : public ::testing::Test { PreemptiveExpandFactory* preemptive_expand_factory = new PreemptiveExpandFactory; - neteq_ = new NetEqImpl(config_.sample_rate_hz, + neteq_ = new NetEqImpl(config_, buffer_level_filter_, decoder_database_, delay_manager_, diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc index 0233e1950..317c7b575 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc @@ -214,8 +214,6 @@ class NetEqDecodingTest : public ::testing::Test { uint8_t* payload, int* payload_len); - void CheckBgnOff(int sampling_rate, NetEqBackgroundNoiseMode bgn_mode); - void WrapTest(uint16_t start_seq_no, uint32_t start_timestamp, const std::set& drop_seq_numbers, bool expect_seq_no_wrap, bool expect_timestamp_wrap); @@ -231,6 +229,7 @@ class NetEqDecodingTest : public ::testing::Test { uint32_t PlayoutTimestamp(); NetEq* neteq_; + NetEq::Config config_; FILE* rtp_fp_; unsigned int sim_clock_; int16_t out_data_[kMaxBlockSize]; @@ -248,17 +247,17 @@ const int NetEqDecodingTest::kInitSampleRateHz; NetEqDecodingTest::NetEqDecodingTest() : neteq_(NULL), + config_(), rtp_fp_(NULL), sim_clock_(0), output_sample_rate_(kInitSampleRateHz), algorithmic_delay_ms_(0) { + config_.sample_rate_hz = kInitSampleRateHz; memset(out_data_, 0, sizeof(out_data_)); } void NetEqDecodingTest::SetUp() { - NetEq::Config config; - config.sample_rate_hz = kInitSampleRateHz; - neteq_ = NetEq::Create(config); + neteq_ = NetEq::Create(config_); NetEqNetworkStatistics stat; ASSERT_EQ(0, neteq_->NetworkStatistics(&stat)); algorithmic_delay_ms_ = stat.current_buffer_size_ms; @@ -425,107 +424,6 @@ void NetEqDecodingTest::PopulateCng(int frame_index, *payload_len = 1; // Only noise level, no spectral parameters. } -void NetEqDecodingTest::CheckBgnOff(int sampling_rate_hz, - NetEqBackgroundNoiseMode bgn_mode) { - int expected_samples_per_channel = 0; - uint8_t payload_type = 0xFF; // Invalid. - if (sampling_rate_hz == 8000) { - expected_samples_per_channel = kBlockSize8kHz; - payload_type = 93; // PCM 16, 8 kHz. - } else if (sampling_rate_hz == 16000) { - expected_samples_per_channel = kBlockSize16kHz; - payload_type = 94; // PCM 16, 16 kHZ. - } else if (sampling_rate_hz == 32000) { - expected_samples_per_channel = kBlockSize32kHz; - payload_type = 95; // PCM 16, 32 kHz. - } else { - ASSERT_TRUE(false); // Unsupported test case. - } - - NetEqOutputType type; - int16_t output[kBlockSize32kHz]; // Maximum size is chosen. - int16_t input[kBlockSize32kHz]; // Maximum size is chosen. - - // Payload of 10 ms of PCM16 32 kHz. - uint8_t payload[kBlockSize32kHz * sizeof(int16_t)]; - - // Random payload. - for (int n = 0; n < expected_samples_per_channel; ++n) { - input[n] = (rand() & ((1 << 10) - 1)) - ((1 << 5) - 1); - } - int enc_len_bytes = WebRtcPcm16b_EncodeW16( - input, expected_samples_per_channel, reinterpret_cast(payload)); - ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2); - - WebRtcRTPHeader rtp_info; - PopulateRtpInfo(0, 0, &rtp_info); - rtp_info.header.payloadType = payload_type; - - int number_channels = 0; - int samples_per_channel = 0; - - uint32_t receive_timestamp = 0; - for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. - number_channels = 0; - samples_per_channel = 0; - ASSERT_EQ(0, neteq_->InsertPacket( - rtp_info, payload, enc_len_bytes, receive_timestamp)); - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel, - &number_channels, &type)); - ASSERT_EQ(1, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); - ASSERT_EQ(kOutputNormal, type); - - // Next packet. - rtp_info.header.timestamp += expected_samples_per_channel; - rtp_info.header.sequenceNumber++; - receive_timestamp += expected_samples_per_channel; - } - - number_channels = 0; - samples_per_channel = 0; - - // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull one - // frame without checking speech-type. This is the first frame pulled without - // inserting any packet, and might not be labeled as PCL. - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel, - &number_channels, &type)); - ASSERT_EQ(1, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); - - // To be able to test the fading of background noise we need at lease to pull - // 611 frames. - const int kFadingThreshold = 611; - - // Test several CNG-to-PLC packet for the expected behavior. The number 20 is - // arbitrary, but sufficiently large to test enough number of frames. - const int kNumPlcToCngTestFrames = 20; - bool plc_to_cng = false; - for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) { - number_channels = 0; - samples_per_channel = 0; - memset(output, 1, sizeof(output)); // Set to non-zero. - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel, - &number_channels, &type)); - ASSERT_EQ(1, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); - if (type == kOutputPLCtoCNG) { - plc_to_cng = true; - double sum_squared = 0; - for (int k = 0; k < number_channels * samples_per_channel; ++k) - sum_squared += output[k] * output[k]; - if (bgn_mode == kBgnOn) { - EXPECT_NE(0, sum_squared); - } else if (bgn_mode == kBgnOff || n > kFadingThreshold) { - EXPECT_EQ(0, sum_squared); - } - } else { - EXPECT_EQ(kOutputPLC, type); - } - } - EXPECT_TRUE(plc_to_cng); // Just to be sure that PLC-to-CNG has occurred. -} - TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(TestBitExactness)) { const std::string input_rtp_file = webrtc::test::ProjectRootPath() + "resources/audio_coding/neteq_universal_new.rtp"; @@ -993,26 +891,143 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { } } -TEST_F(NetEqDecodingTest, BackgroundNoise) { - neteq_->SetBackgroundNoiseMode(kBgnOn); - CheckBgnOff(8000, kBgnOn); - CheckBgnOff(16000, kBgnOn); - CheckBgnOff(32000, kBgnOn); - EXPECT_EQ(kBgnOn, neteq_->BackgroundNoiseMode()); +class NetEqBgnTest + : public NetEqDecodingTest, + public ::testing::WithParamInterface { + protected: + NetEqBgnTest() : NetEqDecodingTest() { + config_.background_noise_mode = GetParam(); + } - neteq_->SetBackgroundNoiseMode(kBgnOff); - CheckBgnOff(8000, kBgnOff); - CheckBgnOff(16000, kBgnOff); - CheckBgnOff(32000, kBgnOff); - EXPECT_EQ(kBgnOff, neteq_->BackgroundNoiseMode()); + void CheckBgnOff(int sampling_rate_hz) { + int expected_samples_per_channel = 0; + uint8_t payload_type = 0xFF; // Invalid. + if (sampling_rate_hz == 8000) { + expected_samples_per_channel = kBlockSize8kHz; + payload_type = 93; // PCM 16, 8 kHz. + } else if (sampling_rate_hz == 16000) { + expected_samples_per_channel = kBlockSize16kHz; + payload_type = 94; // PCM 16, 16 kHZ. + } else if (sampling_rate_hz == 32000) { + expected_samples_per_channel = kBlockSize32kHz; + payload_type = 95; // PCM 16, 32 kHz. + } else { + ASSERT_TRUE(false); // Unsupported test case. + } - neteq_->SetBackgroundNoiseMode(kBgnFade); - CheckBgnOff(8000, kBgnFade); - CheckBgnOff(16000, kBgnFade); - CheckBgnOff(32000, kBgnFade); - EXPECT_EQ(kBgnFade, neteq_->BackgroundNoiseMode()); + NetEqOutputType type; + int16_t output[kBlockSize32kHz]; // Maximum size is chosen. + int16_t input[kBlockSize32kHz]; // Maximum size is chosen. + + // Payload of 10 ms of PCM16 32 kHz. + uint8_t payload[kBlockSize32kHz * sizeof(int16_t)]; + + // Random payload. + for (int n = 0; n < expected_samples_per_channel; ++n) { + input[n] = (rand() & ((1 << 10) - 1)) - ((1 << 5) - 1); + } + int enc_len_bytes = + WebRtcPcm16b_EncodeW16(input, + expected_samples_per_channel, + reinterpret_cast(payload)); + ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2); + + WebRtcRTPHeader rtp_info; + PopulateRtpInfo(0, 0, &rtp_info); + rtp_info.header.payloadType = payload_type; + + int number_channels = 0; + int samples_per_channel = 0; + + uint32_t receive_timestamp = 0; + for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. + number_channels = 0; + samples_per_channel = 0; + ASSERT_EQ(0, + neteq_->InsertPacket( + rtp_info, payload, enc_len_bytes, receive_timestamp)); + ASSERT_EQ(0, + neteq_->GetAudio(kBlockSize32kHz, + output, + &samples_per_channel, + &number_channels, + &type)); + ASSERT_EQ(1, number_channels); + ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + ASSERT_EQ(kOutputNormal, type); + + // Next packet. + rtp_info.header.timestamp += expected_samples_per_channel; + rtp_info.header.sequenceNumber++; + receive_timestamp += expected_samples_per_channel; + } + + number_channels = 0; + samples_per_channel = 0; + + // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull + // one frame without checking speech-type. This is the first frame pulled + // without inserting any packet, and might not be labeled as PLC. + ASSERT_EQ(0, + neteq_->GetAudio(kBlockSize32kHz, + output, + &samples_per_channel, + &number_channels, + &type)); + ASSERT_EQ(1, number_channels); + ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + + // To be able to test the fading of background noise we need at lease to + // pull 611 frames. + const int kFadingThreshold = 611; + + // Test several CNG-to-PLC packet for the expected behavior. The number 20 + // is arbitrary, but sufficiently large to test enough number of frames. + const int kNumPlcToCngTestFrames = 20; + bool plc_to_cng = false; + for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) { + number_channels = 0; + samples_per_channel = 0; + memset(output, 1, sizeof(output)); // Set to non-zero. + ASSERT_EQ(0, + neteq_->GetAudio(kBlockSize32kHz, + output, + &samples_per_channel, + &number_channels, + &type)); + ASSERT_EQ(1, number_channels); + ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + if (type == kOutputPLCtoCNG) { + plc_to_cng = true; + double sum_squared = 0; + for (int k = 0; k < number_channels * samples_per_channel; ++k) + sum_squared += output[k] * output[k]; + if (config_.background_noise_mode == NetEq::kBgnOn) { + EXPECT_NE(0, sum_squared); + } else if (config_.background_noise_mode == NetEq::kBgnOff || + n > kFadingThreshold) { + EXPECT_EQ(0, sum_squared); + } + } else { + EXPECT_EQ(kOutputPLC, type); + } + } + EXPECT_TRUE(plc_to_cng); // Just to be sure that PLC-to-CNG has occurred. + } +}; + +TEST_P(NetEqBgnTest, BackgroundNoise) { + CheckBgnOff(8000); + CheckBgnOff(16000); + CheckBgnOff(32000); } +INSTANTIATE_TEST_CASE_P(BgnModes, + NetEqBgnTest, + ::testing::Values(NetEq::kBgnOn, + NetEq::kBgnOff, + NetEq::kBgnFade)); + TEST_F(NetEqDecodingTest, SyncPacketInsert) { WebRtcRTPHeader rtp_info; uint32_t receive_timestamp = 0;