/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // Unit tests for BufferLevelFilter class. #include "modules/audio_coding/neteq/buffer_level_filter.h" #include // Access to pow function. #include "rtc_base/strings/string_builder.h" #include "test/gtest.h" namespace webrtc { TEST(BufferLevelFilter, CreateAndDestroy) { BufferLevelFilter* filter = new BufferLevelFilter(); EXPECT_EQ(0, filter->filtered_current_level()); delete filter; } TEST(BufferLevelFilter, ConvergenceTest) { BufferLevelFilter filter; for (int times = 10; times <= 50; times += 10) { for (int value = 100; value <= 200; value += 10) { filter.Reset(); filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256. rtc::StringBuilder ss; ss << "times = " << times << ", value = " << value; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. for (int i = 0; i < times; ++i) { filter.Update(value, 0 /* time_stretched_samples */); } // Expect the filtered value to be (theoretically) // (1 - (251/256) ^ `times`) * `value`. double expected_value_double = (1 - pow(251.0 / 256.0, times)) * value; int expected_value = static_cast(expected_value_double); // The actual value may differ slightly from the expected value due to // intermediate-stage rounding errors in the filter implementation. // This is why we have to use EXPECT_NEAR with a tolerance of +/-1. EXPECT_NEAR(expected_value, filter.filtered_current_level(), 1); } } } // Verify that target buffer level impacts on the filter convergence. TEST(BufferLevelFilter, FilterFactor) { BufferLevelFilter filter; // Update 10 times with value 100. const int kTimes = 10; const int kValue = 100; filter.SetTargetBufferLevel(60); // Makes filter coefficient 252/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be // (1 - (252/256) ^ `kTimes`) * `kValue`. int expected_value = 15; EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); filter.SetTargetBufferLevel(140); // Makes filter coefficient 253/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be // (1 - (253/256) ^ `kTimes`) * `kValue`. expected_value = 11; EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); filter.SetTargetBufferLevel(160); // Makes filter coefficient 254/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be // (1 - (254/256) ^ `kTimes`) * `kValue`. expected_value = 8; EXPECT_EQ(expected_value, filter.filtered_current_level()); } TEST(BufferLevelFilter, TimeStretchedSamples) { BufferLevelFilter filter; filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256. // Update 10 times with value 100. const int kTimes = 10; const int kValue = 100; const int kTimeStretchedSamples = 3; for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0); } // Expect the filtered value to be // (1 - (251/256) ^ `kTimes`) * `kValue`. const int kExpectedValue = 18; EXPECT_EQ(kExpectedValue, filter.filtered_current_level()); // Update filter again, now with non-zero value for packet length. // Set the current filtered value to be the input, in order to isolate the // impact of `kTimeStretchedSamples`. filter.Update(filter.filtered_current_level(), kTimeStretchedSamples); EXPECT_EQ(kExpectedValue - kTimeStretchedSamples, filter.filtered_current_level()); // Try negative value and verify that we come back to the previous result. filter.Update(filter.filtered_current_level(), -kTimeStretchedSamples); EXPECT_EQ(kExpectedValue, filter.filtered_current_level()); } } // namespace webrtc