expand_unittest.cc (7561B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Unit tests for Expand class. 12 13 #include "modules/audio_coding/neteq/expand.h" 14 15 #include <cstddef> 16 #include <cstdint> 17 #include <memory> 18 19 #include "api/neteq/tick_timer.h" 20 #include "modules/audio_coding/neteq/background_noise.h" 21 #include "modules/audio_coding/neteq/random_vector.h" 22 #include "modules/audio_coding/neteq/statistics_calculator.h" 23 #include "modules/audio_coding/neteq/sync_buffer.h" 24 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h" 25 #include "rtc_base/numerics/safe_conversions.h" 26 #include "test/gtest.h" 27 #include "test/testsupport/file_utils.h" 28 29 namespace webrtc { 30 31 namespace { 32 class FakeStatisticsCalculator : public StatisticsCalculator { 33 public: 34 FakeStatisticsCalculator(TickTimer* tick_timer) 35 : StatisticsCalculator(tick_timer) {} 36 37 void LogDelayedPacketOutageEvent(int num_samples, int /* fs_hz */) override { 38 last_outage_duration_samples_ = num_samples; 39 } 40 41 int last_outage_duration_samples() const { 42 return last_outage_duration_samples_; 43 } 44 45 private: 46 int last_outage_duration_samples_ = 0; 47 }; 48 49 // This is the same size that is given to the SyncBuffer object in NetEq. 50 constexpr size_t kNetEqSyncBufferLengthMs = 720; 51 } // namespace 52 53 TEST(Expand, CreateAndDestroy) { 54 int fs = 8000; 55 size_t channels = 1; 56 BackgroundNoise bgn(channels); 57 SyncBuffer sync_buffer(1, 1000); 58 RandomVector random_vector; 59 TickTimer timer; 60 StatisticsCalculator statistics(&timer); 61 Expand expand(&bgn, &sync_buffer, &random_vector, &statistics, fs, channels); 62 } 63 64 TEST(Expand, CreateUsingFactory) { 65 int fs = 8000; 66 size_t channels = 1; 67 BackgroundNoise bgn(channels); 68 SyncBuffer sync_buffer(1, 1000); 69 RandomVector random_vector; 70 TickTimer timer; 71 StatisticsCalculator statistics(&timer); 72 ExpandFactory expand_factory; 73 Expand* expand = expand_factory.Create(&bgn, &sync_buffer, &random_vector, 74 &statistics, fs, channels); 75 EXPECT_TRUE(expand != nullptr); 76 delete expand; 77 } 78 79 class ExpandTest : public ::testing::Test { 80 protected: 81 ExpandTest() 82 : input_file_(test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 83 32000), 84 test_sample_rate_hz_(32000), 85 num_channels_(1), 86 background_noise_(num_channels_), 87 sync_buffer_(num_channels_, 88 kNetEqSyncBufferLengthMs * test_sample_rate_hz_ / 1000), 89 statistics_(&tick_timer_), 90 expand_(&background_noise_, 91 &sync_buffer_, 92 &random_vector_, 93 &statistics_, 94 test_sample_rate_hz_, 95 num_channels_) { 96 input_file_.set_output_rate_hz(test_sample_rate_hz_); 97 } 98 99 void SetUp() override { 100 // Fast-forward the input file until there is speech (about 1.1 second into 101 // the file). 102 const int speech_start_samples = 103 static_cast<int>(test_sample_rate_hz_ * 1.1f); 104 ASSERT_TRUE(input_file_.Seek(speech_start_samples)); 105 106 // Pre-load the sync buffer with speech data. 107 std::unique_ptr<int16_t[]> temp(new int16_t[sync_buffer_.Size()]); 108 ASSERT_TRUE(input_file_.Read(sync_buffer_.Size(), temp.get())); 109 sync_buffer_.Channel(0).OverwriteAt(temp.get(), sync_buffer_.Size(), 0); 110 ASSERT_EQ(1u, num_channels_) << "Fix: Must populate all channels."; 111 } 112 113 test::ResampleInputAudioFile input_file_; 114 int test_sample_rate_hz_; 115 size_t num_channels_; 116 BackgroundNoise background_noise_; 117 SyncBuffer sync_buffer_; 118 RandomVector random_vector_; 119 TickTimer tick_timer_; 120 FakeStatisticsCalculator statistics_; 121 Expand expand_; 122 }; 123 124 // This test calls the expand object to produce concealment data a few times, 125 // and then ends by calling SetParametersForNormalAfterExpand. This simulates 126 // the situation where the packet next up for decoding was just delayed, not 127 // lost. 128 TEST_F(ExpandTest, DelayedPacketOutage) { 129 AudioMultiVector output(num_channels_); 130 size_t sum_output_len_samples = 0; 131 for (int i = 0; i < 10; ++i) { 132 EXPECT_EQ(0, expand_.Process(&output)); 133 EXPECT_GT(output.Size(), 0u); 134 sum_output_len_samples += output.Size(); 135 EXPECT_EQ(0, statistics_.last_outage_duration_samples()); 136 } 137 expand_.SetParametersForNormalAfterExpand(); 138 // Convert `sum_output_len_samples` to milliseconds. 139 EXPECT_EQ(checked_cast<int>(sum_output_len_samples), 140 statistics_.last_outage_duration_samples()); 141 } 142 143 // This test is similar to DelayedPacketOutage, but ends by calling 144 // SetParametersForMergeAfterExpand. This simulates the situation where the 145 // packet next up for decoding was actually lost (or at least a later packet 146 // arrived before it). 147 TEST_F(ExpandTest, LostPacketOutage) { 148 AudioMultiVector output(num_channels_); 149 for (int i = 0; i < 10; ++i) { 150 EXPECT_EQ(0, expand_.Process(&output)); 151 EXPECT_GT(output.Size(), 0u); 152 EXPECT_EQ(0, statistics_.last_outage_duration_samples()); 153 } 154 expand_.SetParametersForMergeAfterExpand(); 155 EXPECT_EQ(0, statistics_.last_outage_duration_samples()); 156 } 157 158 // This test is similar to the DelayedPacketOutage test above, but with the 159 // difference that Expand::Reset() is called after 5 calls to Expand::Process(). 160 // This should reset the statistics, and will in the end lead to an outage of 161 // 5 periods instead of 10. 162 TEST_F(ExpandTest, CheckOutageStatsAfterReset) { 163 AudioMultiVector output(num_channels_); 164 size_t sum_output_len_samples = 0; 165 for (int i = 0; i < 10; ++i) { 166 EXPECT_EQ(0, expand_.Process(&output)); 167 EXPECT_GT(output.Size(), 0u); 168 sum_output_len_samples += output.Size(); 169 if (i == 5) { 170 expand_.Reset(); 171 sum_output_len_samples = 0; 172 } 173 EXPECT_EQ(0, statistics_.last_outage_duration_samples()); 174 } 175 expand_.SetParametersForNormalAfterExpand(); 176 // Convert `sum_output_len_samples` to milliseconds. 177 EXPECT_EQ(checked_cast<int>(sum_output_len_samples), 178 statistics_.last_outage_duration_samples()); 179 } 180 181 namespace { 182 // Runs expand until Muted() returns true. Times out after 1000 calls. 183 void ExpandUntilMuted(size_t num_channels, Expand* expand) { 184 EXPECT_FALSE(expand->Muted()) << "Instance is muted from the start"; 185 AudioMultiVector output(num_channels); 186 int num_calls = 0; 187 while (!expand->Muted()) { 188 ASSERT_LT(num_calls++, 1000) << "Test timed out"; 189 EXPECT_EQ(0, expand->Process(&output)); 190 } 191 } 192 } // namespace 193 194 // Verifies that Muted() returns true after a long expand period. Also verifies 195 // that Muted() is reset to false after calling Reset(), 196 // SetParametersForMergeAfterExpand() and SetParametersForNormalAfterExpand(). 197 TEST_F(ExpandTest, Muted) { 198 ExpandUntilMuted(num_channels_, &expand_); 199 expand_.Reset(); 200 EXPECT_FALSE(expand_.Muted()); // Should be back to unmuted. 201 202 ExpandUntilMuted(num_channels_, &expand_); 203 expand_.SetParametersForMergeAfterExpand(); 204 EXPECT_FALSE(expand_.Muted()); // Should be back to unmuted. 205 206 expand_.Reset(); // Must reset in order to start a new expand period. 207 ExpandUntilMuted(num_channels_, &expand_); 208 expand_.SetParametersForNormalAfterExpand(); 209 EXPECT_FALSE(expand_.Muted()); // Should be back to unmuted. 210 } 211 212 // TODO(hlundin): Write more tests. 213 214 } // namespace webrtc