| Index: webrtc/common_audio/smoothing_filter.cc
|
| diff --git a/webrtc/common_audio/smoothing_filter.cc b/webrtc/common_audio/smoothing_filter.cc
|
| index d2dde9d8542751d644157bd34e4c671cee177cad..2ab25981f1e3af4b4777026f212591094f75a78c 100644
|
| --- a/webrtc/common_audio/smoothing_filter.cc
|
| +++ b/webrtc/common_audio/smoothing_filter.cc
|
| @@ -14,17 +14,20 @@
|
|
|
| namespace webrtc {
|
|
|
| -SmoothingFilterImpl::SmoothingFilterImpl(int init_time_ms_, const Clock* clock)
|
| - : init_time_ms_(init_time_ms_),
|
| +SmoothingFilterImpl::SmoothingFilterImpl(int init_time_ms, const Clock* clock)
|
| + : init_time_ms_(init_time_ms),
|
| // Duing the initalization time, we use an increasing alpha. Specifically,
|
| - // alpha(n) = exp(pow(init_factor_, n)),
|
| + // alpha(n) = exp(-powf(init_factor_, n)),
|
| // where |init_factor_| is chosen such that
|
| // alpha(init_time_ms_) = exp(-1.0f / init_time_ms_),
|
| - init_factor_(pow(init_time_ms_, 1.0f / init_time_ms_)),
|
| + init_factor_(init_time_ms_ == 0 ? 0.0f : powf(init_time_ms_,
|
| + -1.0f / init_time_ms_)),
|
| // |init_const_| is to a factor to help the calculation during
|
| // initialization phase.
|
| - init_const_(1.0f / (init_time_ms_ -
|
| - pow(init_time_ms_, 1.0f - 1.0f / init_time_ms_))),
|
| + init_const_(init_time_ms_ == 0
|
| + ? 0.0f
|
| + : init_time_ms_ -
|
| + powf(init_time_ms_, 1.0f - 1.0f / init_time_ms_)),
|
| clock_(clock) {
|
| UpdateAlpha(init_time_ms_);
|
| }
|
| @@ -34,11 +37,11 @@ SmoothingFilterImpl::~SmoothingFilterImpl() = default;
|
| void SmoothingFilterImpl::AddSample(float sample) {
|
| const int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
| - if (!first_sample_time_ms_) {
|
| + if (!init_end_time_ms_) {
|
| // This is equivalent to assuming the filter has been receiving the same
|
| // value as the first sample since time -infinity.
|
| state_ = last_sample_ = sample;
|
| - first_sample_time_ms_ = rtc::Optional<int64_t>(now_ms);
|
| + init_end_time_ms_ = rtc::Optional<int64_t>(now_ms + init_time_ms_);
|
| last_state_time_ms_ = now_ms;
|
| return;
|
| }
|
| @@ -48,15 +51,16 @@ void SmoothingFilterImpl::AddSample(float sample) {
|
| }
|
|
|
| rtc::Optional<float> SmoothingFilterImpl::GetAverage() {
|
| - if (!first_sample_time_ms_)
|
| + if (!init_end_time_ms_) {
|
| + // |init_end_time_ms_| undefined since we have not received any sample.
|
| return rtc::Optional<float>();
|
| + }
|
| ExtrapolateLastSample(clock_->TimeInMilliseconds());
|
| return rtc::Optional<float>(state_);
|
| }
|
|
|
| bool SmoothingFilterImpl::SetTimeConstantMs(int time_constant_ms) {
|
| - if (!first_sample_time_ms_ ||
|
| - last_state_time_ms_ < *first_sample_time_ms_ + init_time_ms_) {
|
| + if (!init_end_time_ms_ || last_state_time_ms_ < *init_end_time_ms_) {
|
| return false;
|
| }
|
| UpdateAlpha(time_constant_ms);
|
| @@ -64,34 +68,43 @@ bool SmoothingFilterImpl::SetTimeConstantMs(int time_constant_ms) {
|
| }
|
|
|
| void SmoothingFilterImpl::UpdateAlpha(int time_constant_ms) {
|
| - alpha_ = exp(-1.0f / time_constant_ms);
|
| + alpha_ = time_constant_ms == 0 ? 0.0f : exp(-1.0f / time_constant_ms);
|
| }
|
|
|
| void SmoothingFilterImpl::ExtrapolateLastSample(int64_t time_ms) {
|
| RTC_DCHECK_GE(time_ms, last_state_time_ms_);
|
| - RTC_DCHECK(first_sample_time_ms_);
|
| + RTC_DCHECK(init_end_time_ms_);
|
|
|
| float multiplier = 0.0f;
|
| - if (time_ms <= *first_sample_time_ms_ + init_time_ms_) {
|
| +
|
| + if (time_ms <= *init_end_time_ms_) {
|
| // Current update is to be made during initialization phase.
|
| // We update the state as if the |alpha| has been increased according
|
| - // alpha(n) = exp(pow(init_factor_, n)),
|
| + // alpha(n) = exp(-powf(init_factor_, n)),
|
| // where n is the time (in millisecond) since the first sample received.
|
| // With algebraic derivation as shown in the Appendix, we can find that the
|
| // state can be updated in a similar manner as if alpha is a constant,
|
| // except for a different multiplier.
|
| - multiplier = exp(-init_const_ *
|
| - (pow(init_factor_,
|
| - *first_sample_time_ms_ + init_time_ms_ - last_state_time_ms_) -
|
| - pow(init_factor_, *first_sample_time_ms_ + init_time_ms_ - time_ms)));
|
| + if (init_time_ms_ == 0) {
|
| + // This means |init_factor_| = 0.
|
| + multiplier = 0.0f;
|
| + } else if (init_time_ms_ == 1) {
|
| + // This means |init_factor_| = 1.
|
| + multiplier = exp(last_state_time_ms_ - time_ms);
|
| + } else {
|
| + multiplier =
|
| + exp(-(powf(init_factor_, last_state_time_ms_ - *init_end_time_ms_) -
|
| + powf(init_factor_, time_ms - *init_end_time_ms_)) /
|
| + init_const_);
|
| + }
|
| } else {
|
| - if (last_state_time_ms_ < *first_sample_time_ms_ + init_time_ms_) {
|
| + if (last_state_time_ms_ < *init_end_time_ms_) {
|
| // The latest state update was made during initialization phase.
|
| // We first extrapolate to the initialization time.
|
| - ExtrapolateLastSample(*first_sample_time_ms_ + init_time_ms_);
|
| + ExtrapolateLastSample(*init_end_time_ms_);
|
| // Then extrapolate the rest by the following.
|
| }
|
| - multiplier = pow(alpha_, time_ms - last_state_time_ms_);
|
| + multiplier = powf(alpha_, time_ms - last_state_time_ms_);
|
| }
|
|
|
| state_ = multiplier * state_ + (1.0f - multiplier) * last_sample_;
|
| @@ -108,17 +121,21 @@ void SmoothingFilterImpl::ExtrapolateLastSample(int64_t time_ms) {
|
| // &= \left(\prod_{i=m}^{n-1} \alpha_i\right) y(m) +
|
| // \left(1 - \prod_{i=m}^{n-1} \alpha_i \right) x(m)
|
| // \end{align}
|
| -// Taking $\alpha_{n} = \exp{\gamma^n}$, $\gamma$ denotes init\_factor\_, the
|
| +// Taking $\alpha_{n} = \exp(-\gamma^n)$, $\gamma$ denotes init\_factor\_, the
|
| // multiplier becomes
|
| // \begin{align}
|
| // \prod_{i=m}^{n-1} \alpha_i
|
| -// &= \exp\left(\prod_{i=m}^{n-1} \gamma^i \right) \\*
|
| -// &= \exp\left(\frac{\gamma^m - \gamma^n}{1 - \gamma} \right)
|
| +// &= \exp\left(-\sum_{i=m}^{n-1} \gamma^i \right) \\*
|
| +// &= \begin{cases}
|
| +// \exp\left(-\frac{\gamma^m - \gamma^n}{1 - \gamma} \right)
|
| +// & \gamma \neq 1 \\*
|
| +// m-n & \gamma = 1
|
| +// \end{cases}
|
| // \end{align}
|
| -// We know $\gamma = T^\frac{1}{T}$, where $T$ denotes init\_time\_ms\_. Then
|
| +// We know $\gamma = T^{-\frac{1}{T}}$, where $T$ denotes init\_time\_ms\_. Then
|
| // $1 - \gamma$ approaches zero when $T$ increases. This can cause numerical
|
| -// difficulties. We multiply $T$ to both numerator and denominator in the
|
| -// fraction. See.
|
| +// difficulties. We multiply $T$ (if $T > 0$) to both numerator and denominator
|
| +// in the fraction. See.
|
| // \begin{align}
|
| // \frac{\gamma^m - \gamma^n}{1 - \gamma}
|
| // &= \frac{T^\frac{T-m}{T} - T^\frac{T-n}{T}}{T - T^{1-\frac{1}{T}}}
|
|
|