blob: 388ae4f9998bf5b458b1c4b25998151dbe60919b [file] [log] [blame]
/*
* Copyright (c) 2016 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.
*/
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/smoothing_filter.h"
namespace webrtc {
namespace {
constexpr int kTimeConstantMs = 1000;
constexpr float kMaxAbsError = 0.0001f;
constexpr int64_t kClockInitialTime = 123456;
struct SmoothingFilterStates {
std::unique_ptr<SimulatedClock> simulated_clock;
std::unique_ptr<SmoothingFilter> smoothing_filter;
};
SmoothingFilterStates CreateSmoothingFilter() {
SmoothingFilterStates states;
states.simulated_clock.reset(new SimulatedClock(kClockInitialTime));
states.smoothing_filter.reset(
new SmoothingFilterImpl(kTimeConstantMs, states.simulated_clock.get()));
return states;
}
void CheckOutput(SmoothingFilterStates* states,
int advance_time_ms,
float sample,
float expected_ouput) {
states->simulated_clock->AdvanceTimeMilliseconds(advance_time_ms);
states->smoothing_filter->AddSample(sample);
auto output = states->smoothing_filter->GetAverage();
EXPECT_TRUE(output);
EXPECT_NEAR(expected_ouput, *output, kMaxAbsError);
}
} // namespace
TEST(SmoothingFilterTest, NoOutputWhenNoSampleAdded) {
auto states = CreateSmoothingFilter();
EXPECT_FALSE(states.smoothing_filter->GetAverage());
}
// Python script to calculate the reference values used in this test.
// import math
//
// class ExpFilter:
// alpha = 0.0
// old_value = 0.0
// def calc(self, new_value):
// self.old_value = self.old_value * self.alpha
// + (1.0 - self.alpha) * new_value
// return self.old_value
//
// delta_t = 100.0
// filter = ExpFilter()
// total_t = 100.0
// filter.alpha = math.exp(-delta_t/ total_t)
// print filter.calc(1.0)
// total_t = 200.0
// filter.alpha = math.exp(-delta_t/ total_t)
// print filter.calc(0.0)
// total_t = 300.0
// filter.alpha = math.exp(-delta_t/ total_t)
// print filter.calc(1.0)
TEST(SmoothingFilterTest, CheckBehaviorBeforeInitialized) {
// Adding three samples, all added before |kTimeConstantMs| is reached.
constexpr int kTimeIntervalMs = 100;
auto states = CreateSmoothingFilter();
states.smoothing_filter->AddSample(0.0);
CheckOutput(&states, kTimeIntervalMs, 1.0, 0.63212f);
CheckOutput(&states, kTimeIntervalMs, 0.0, 0.38340f);
CheckOutput(&states, kTimeIntervalMs, 1.0, 0.55818f);
}
// Python script to calculate the reference value used in this test.
// (after defining ExpFilter as for CheckBehaviorBeforeInitialized)
// time_constant_ms = 1000.0
// filter = ExpFilter()
// delta_t = 1100.0
// filter.alpha = math.exp(-delta_t/ time_constant_ms)
// print filter.calc(1.0)
// delta_t = 100.0
// filter.alpha = math.exp(-delta_t/ time_constant_ms)
// print filter.calc(0.0)
// print filter.calc(1.0)
TEST(SmoothingFilterTest, CheckBehaviorAfterInitialized) {
constexpr int kTimeIntervalMs = 100;
auto states = CreateSmoothingFilter();
states.smoothing_filter->AddSample(0.0);
states.simulated_clock->AdvanceTimeMilliseconds(kTimeConstantMs);
CheckOutput(&states, kTimeIntervalMs, 1.0, 0.66713f);
CheckOutput(&states, kTimeIntervalMs, 0.0, 0.60364f);
CheckOutput(&states, kTimeIntervalMs, 1.0, 0.64136f);
}
} // namespace webrtc