| /* |
| * 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 <math.h> // 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(1); // 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 */, |
| 160 /* packet_len_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<int>(expected_value_double); |
| // filtered_current_level() returns the value in Q8. |
| // 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() >> 8, 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(3); // Makes filter coefficient 252/256. |
| for (int i = 0; i < kTimes; ++i) { |
| filter.Update(kValue, 0 /* time_stretched_samples */, |
| 160 /* packet_len_samples */); |
| } |
| // Expect the filtered value to be |
| // (1 - (252/256) ^ |kTimes|) * |kValue|. |
| int expected_value = 14; |
| // filtered_current_level() returns the value in Q8. |
| EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8); |
| |
| filter.Reset(); |
| filter.SetTargetBufferLevel(7); // Makes filter coefficient 253/256. |
| for (int i = 0; i < kTimes; ++i) { |
| filter.Update(kValue, 0 /* time_stretched_samples */, |
| 160 /* packet_len_samples */); |
| } |
| // Expect the filtered value to be |
| // (1 - (253/256) ^ |kTimes|) * |kValue|. |
| expected_value = 11; |
| // filtered_current_level() returns the value in Q8. |
| EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8); |
| |
| filter.Reset(); |
| filter.SetTargetBufferLevel(8); // Makes filter coefficient 254/256. |
| for (int i = 0; i < kTimes; ++i) { |
| filter.Update(kValue, 0 /* time_stretched_samples */, |
| 160 /* packet_len_samples */); |
| } |
| // Expect the filtered value to be |
| // (1 - (254/256) ^ |kTimes|) * |kValue|. |
| expected_value = 7; |
| // filtered_current_level() returns the value in Q8. |
| EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8); |
| } |
| |
| TEST(BufferLevelFilter, TimeStretchedSamples) { |
| BufferLevelFilter filter; |
| filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256. |
| // Update 10 times with value 100. |
| const int kTimes = 10; |
| const int kValue = 100; |
| const int kPacketSizeSamples = 160; |
| const int kNumPacketsStretched = 2; |
| const int kTimeStretchedSamples = kNumPacketsStretched * kPacketSizeSamples; |
| for (int i = 0; i < kTimes; ++i) { |
| // Packet size set to 0. Do not expect the parameter |
| // |kTimeStretchedSamples| to have any effect. |
| filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */); |
| } |
| // Expect the filtered value to be |
| // (1 - (251/256) ^ |kTimes|) * |kValue|. |
| const int kExpectedValue = 17; |
| // filtered_current_level() returns the value in Q8. |
| EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8); |
| |
| // 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() >> 8, kTimeStretchedSamples, |
| kPacketSizeSamples); |
| EXPECT_EQ(kExpectedValue - kNumPacketsStretched, |
| filter.filtered_current_level() >> 8); |
| // Try negative value and verify that we come back to the previous result. |
| filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples, |
| kPacketSizeSamples); |
| EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8); |
| } |
| |
| TEST(BufferLevelFilter, TimeStretchedSamplesNegativeUnevenFrames) { |
| BufferLevelFilter filter; |
| filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256. |
| // Update 10 times with value 100. |
| const int kTimes = 10; |
| const int kValue = 100; |
| const int kPacketSizeSamples = 160; |
| const int kTimeStretchedSamples = -3.1415 * kPacketSizeSamples; |
| for (int i = 0; i < kTimes; ++i) { |
| // Packet size set to 0. Do not expect the parameter |
| // |kTimeStretchedSamples| to have any effect. |
| filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */); |
| } |
| // Expect the filtered value to be |
| // (1 - (251/256) ^ |kTimes|) * |kValue|. |
| const int kExpectedValue = 17; |
| // filtered_current_level() returns the value in Q8. |
| EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8); |
| |
| // 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() >> 8, kTimeStretchedSamples, |
| kPacketSizeSamples); |
| EXPECT_EQ(21, filter.filtered_current_level() >> 8); |
| // Try negative value and verify that we come back to the previous result. |
| filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples, |
| kPacketSizeSamples); |
| EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8); |
| } |
| |
| } // namespace webrtc |