Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2681)

Unified Diff: webrtc/common_audio/smoothing_filter_unittest.cc

Issue 2551363002: Update common_audio/smoothing_filter. (Closed)
Patch Set: improving numerical stability Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/common_audio/smoothing_filter_unittest.cc
diff --git a/webrtc/common_audio/smoothing_filter_unittest.cc b/webrtc/common_audio/smoothing_filter_unittest.cc
index c80ffb672cb71b3286e3408d3aaec38fe77b6006..a31047fbb5d707c7073692ec33af376d8d771ab0 100644
--- a/webrtc/common_audio/smoothing_filter_unittest.cc
+++ b/webrtc/common_audio/smoothing_filter_unittest.cc
@@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include <cmath>
#include <memory>
#include "webrtc/common_audio/smoothing_filter.h"
@@ -17,29 +18,34 @@ namespace webrtc {
namespace {
-constexpr int kTimeConstantMs = 1000;
-constexpr float kMaxAbsError = 0.0001f;
+constexpr int kInitTimeMs = 795;
+constexpr float kMaxAbsError = 1e-5f;
constexpr int64_t kClockInitialTime = 123456;
struct SmoothingFilterStates {
std::unique_ptr<SimulatedClock> simulated_clock;
- std::unique_ptr<SmoothingFilter> smoothing_filter;
+ std::unique_ptr<SmoothingFilterImpl> smoothing_filter;
};
SmoothingFilterStates CreateSmoothingFilter() {
SmoothingFilterStates states;
states.simulated_clock.reset(new SimulatedClock(kClockInitialTime));
states.smoothing_filter.reset(
- new SmoothingFilterImpl(kTimeConstantMs, states.simulated_clock.get()));
+ new SmoothingFilterImpl(kInitTimeMs, states.simulated_clock.get()));
return states;
}
+// This function does the following:
+// 1. Add a sample to filter at current clock,
+// 2. Advance the clock by |advance_time_ms|,
+// 3. Get the output of both SmoothingFilter and verify that it equals to an
+// expected value.
void CheckOutput(SmoothingFilterStates* states,
- int advance_time_ms,
float sample,
+ int advance_time_ms,
float expected_ouput) {
- states->simulated_clock->AdvanceTimeMilliseconds(advance_time_ms);
states->smoothing_filter->AddSample(sample);
+ states->simulated_clock->AdvanceTimeMilliseconds(advance_time_ms);
auto output = states->smoothing_filter->GetAverage();
EXPECT_TRUE(output);
EXPECT_NEAR(expected_ouput, *output, kMaxAbsError);
@@ -56,53 +62,86 @@ TEST(SmoothingFilterTest, NoOutputWhenNoSampleAdded) {
// 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
+// def add_sample(self, new_value):
+// self.state = self.state * self.alpha + (1.0 - self.alpha) * new_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;
+// init_time = 795
+// init_factor = (1.0 / init_time) ** (1.0 / init_time)
+//
+// filter.state = 1.0
+//
+// for time_now in range(1, 500):
+// filter.alpha = math.exp(-init_factor ** time_now)
+// filter.add_sample(1.0)
+// print filter.state
+//
+// for time_now in range(500, 600):
+// filter.alpha = math.exp(-init_factor ** time_now)
+// filter.add_sample(0.5)
+// print filter.state
+//
+// for time_now in range(600, 700):
+// filter.alpha = math.exp(-init_factor ** time_now)
+// filter.add_sample(1.0)
+// print filter.state
+//
+// for time_now in range(700, init_time):
+// filter.alpha = math.exp(-init_factor ** time_now)
+// filter.add_sample(1.0)
+//
+// filter.alpha = math.exp(-1.0 / init_time)
+// for time_now in range(init_time, 800):
+// filter.add_sample(1.0)
+// print filter.state
+//
+// for i in range(800, 900):
+// filter.add_sample(0.5)
+// print filter.state
+//
+// for i in range(900, 1000):
+// filter.add_sample(1.0)
+// print filter.state
+TEST(SmoothingFilterTest, CheckBehaviorAroundInitTime) {
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);
+ CheckOutput(&states, 1.0, 500, 1.0);
+ CheckOutput(&states, 0.5, 100, 0.680562264029);
+ CheckOutput(&states, 1.0, 100, 0.794207139813);
+ // Next step will go across initialization time.
+ CheckOutput(&states, 1.0, 100, 0.829803409752);
+ CheckOutput(&states, 0.5, 100, 0.790821764210);
+ CheckOutput(&states, 1.0, 100, 0.815545922911);
}
-// 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;
+TEST(SmoothingFilterTest, GetAverageOutputsEmptyBeforeFirstSample) {
+ auto states = CreateSmoothingFilter();
+ EXPECT_FALSE(states.smoothing_filter->GetAverage());
+ constexpr float kFirstSample = 1.2345f;
+ states.smoothing_filter->AddSample(kFirstSample);
+ EXPECT_EQ(rtc::Optional<float>(kFirstSample),
+ states.smoothing_filter->GetAverage());
+}
+
+TEST(SmoothingFilterTest, CannotChangeTimeConstantDuringInitialization) {
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);
+
+ // During initialization, |SetTimeConstantMs| does not take effect.
+ states.simulated_clock->AdvanceTimeMilliseconds(kInitTimeMs - 1);
+ states.smoothing_filter->AddSample(0.0);
+
+ states.smoothing_filter->SetTimeConstantMs(kInitTimeMs * 2);
+ EXPECT_NE(exp(-1.0f / (kInitTimeMs * 2)), states.smoothing_filter->alpha());
+
+ states.simulated_clock->AdvanceTimeMilliseconds(1);
+ states.smoothing_filter->AddSample(0.0);
+ // When initialization finishes, the time constant should be come
+ // |kInitTimeConstantMs|.
+ EXPECT_EQ(exp(-1.0f / kInitTimeMs), states.smoothing_filter->alpha());
+
+ // After initialization, |SetTimeConstantMs| takes effect.
+ states.smoothing_filter->SetTimeConstantMs(kInitTimeMs * 2);
+ EXPECT_EQ(exp(-1.0f / (kInitTimeMs * 2)), states.smoothing_filter->alpha());
}
} // namespace webrtc
« webrtc/common_audio/smoothing_filter.cc ('K') | « webrtc/common_audio/smoothing_filter.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698