| Index: webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
 | 
| diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
 | 
| index 145cc0872866db4effc4715000b979e54d5e723e..d67d200689f1613391c18c138b55f504a18ffde4 100644
 | 
| --- a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
 | 
| +++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
 | 
| @@ -14,36 +14,32 @@
 | 
|  
 | 
|  #include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h"
 | 
|  
 | 
| +#include <math.h>
 | 
| +#include <string.h>
 | 
|  #include <algorithm>
 | 
| -#include <cmath>
 | 
| -#include <cstring>
 | 
|  
 | 
|  using std::complex;
 | 
| +using std::min;
 | 
| +
 | 
| +namespace webrtc {
 | 
|  
 | 
| -namespace {
 | 
| +namespace intelligibility {
 | 
|  
 | 
| -// Return |current| changed towards |target|, with the change being at most
 | 
| -// |limit|.
 | 
| -inline float UpdateFactor(float target, float current, float limit) {
 | 
| +float UpdateFactor(float target, float current, float limit) {
 | 
|    float delta = fabsf(target - current);
 | 
|    float sign = copysign(1.0f, target - current);
 | 
|    return current + sign * fminf(delta, limit);
 | 
|  }
 | 
|  
 | 
| -// std::isfinite for complex numbers.
 | 
| -inline bool cplxfinite(complex<float> c) {
 | 
| +bool cplxfinite(complex<float> c) {
 | 
|    return std::isfinite(c.real()) && std::isfinite(c.imag());
 | 
|  }
 | 
|  
 | 
| -// std::isnormal for complex numbers.
 | 
| -inline bool cplxnormal(complex<float> c) {
 | 
| +bool cplxnormal(complex<float> c) {
 | 
|    return std::isnormal(c.real()) && std::isnormal(c.imag());
 | 
|  }
 | 
|  
 | 
| -// Apply a small fudge to degenerate complex values. The numbers in the array
 | 
| -// were chosen randomly, so that even a series of all zeroes has some small
 | 
| -// variability.
 | 
| -inline complex<float> zerofudge(complex<float> c) {
 | 
| +complex<float> zerofudge(complex<float> c) {
 | 
|    const static complex<float> fudge[7] = {{0.001f, 0.002f},
 | 
|                                            {0.008f, 0.001f},
 | 
|                                            {0.003f, 0.008f},
 | 
| @@ -59,25 +55,14 @@ inline complex<float> zerofudge(complex<float> c) {
 | 
|    return c;
 | 
|  }
 | 
|  
 | 
| -// Incremental mean computation. Return the mean of the series with the
 | 
| -// mean |mean| with added |data|.
 | 
| -inline complex<float> NewMean(complex<float> mean,
 | 
| -                              complex<float> data,
 | 
| -                              int count) {
 | 
| +complex<float> NewMean(complex<float> mean, complex<float> data, int count) {
 | 
|    return mean + (data - mean) / static_cast<float>(count);
 | 
|  }
 | 
|  
 | 
| -inline void AddToMean(complex<float> data, int count, complex<float>* mean) {
 | 
| +void AddToMean(complex<float> data, int count, complex<float>* mean) {
 | 
|    (*mean) = NewMean(*mean, data, count);
 | 
|  }
 | 
|  
 | 
| -}  // namespace
 | 
| -
 | 
| -using std::min;
 | 
| -
 | 
| -namespace webrtc {
 | 
| -
 | 
| -namespace intelligibility {
 | 
|  
 | 
|  static const int kWindowBlockSize = 10;
 | 
|  
 | 
| @@ -96,7 +81,8 @@ VarianceArray::VarianceArray(int freqs,
 | 
|        decay_(decay),
 | 
|        history_cursor_(0),
 | 
|        count_(0),
 | 
| -      array_mean_(0.0f) {
 | 
| +      array_mean_(0.0f),
 | 
| +      buffer_full_(false) {
 | 
|    history_.reset(new rtc::scoped_ptr<complex<float>[]>[freqs_]());
 | 
|    for (int i = 0; i < freqs_; ++i) {
 | 
|      history_[i].reset(new complex<float>[window_size_]());
 | 
| @@ -122,6 +108,9 @@ VarianceArray::VarianceArray(int freqs,
 | 
|      case kStepBlocked:
 | 
|        step_func_ = &VarianceArray::BlockedStep;
 | 
|        break;
 | 
| +    case kStepBlockBasedMovingAverage:
 | 
| +      step_func_ = &VarianceArray::BlockBasedMovingAverage;
 | 
| +      break;
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -223,7 +212,7 @@ void VarianceArray::WindowedStep(const complex<float>* data, bool /*dummy*/) {
 | 
|  // history window and a new block is started. The variances for the window
 | 
|  // are recomputed from scratch at each of these transitions.
 | 
|  void VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) {
 | 
| -  int blocks = min(window_size_, history_cursor_);
 | 
| +  int blocks = min(window_size_, history_cursor_ + 1);
 | 
|    for (int i = 0; i < freqs_; ++i) {
 | 
|      AddToMean(data[i], count_ + 1, &sub_running_mean_[i]);
 | 
|      AddToMean(data[i] * std::conj(data[i]), count_ + 1,
 | 
| @@ -242,8 +231,8 @@ void VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) {
 | 
|        running_mean_[i] = complex<float>(0.0f, 0.0f);
 | 
|        running_mean_sq_[i] = complex<float>(0.0f, 0.0f);
 | 
|        for (int j = 0; j < min(window_size_, history_cursor_); ++j) {
 | 
| -        AddToMean(subhistory_[i][j], j, &running_mean_[i]);
 | 
| -        AddToMean(subhistory_sq_[i][j], j, &running_mean_sq_[i]);
 | 
| +        AddToMean(subhistory_[i][j], j + 1, &running_mean_[i]);
 | 
| +        AddToMean(subhistory_sq_[i][j], j + 1, &running_mean_sq_[i]);
 | 
|        }
 | 
|        ++history_cursor_;
 | 
|      }
 | 
| @@ -254,6 +243,51 @@ void VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +// Recomputes variances for each window from scratch based on previous window.
 | 
| +void VarianceArray::BlockBasedMovingAverage(const std::complex<float>* data,
 | 
| +                                            bool /*dummy*/) {
 | 
| +  // TODO(ekmeyerson) To mitigate potential divergence, add counter so that
 | 
| +  // after every so often sums are computed scratch by summing over all
 | 
| +  // elements instead of subtracting oldest and adding newest.
 | 
| +  for (int i = 0; i < freqs_; ++i) {
 | 
| +    sub_running_mean_[i] += data[i];
 | 
| +    sub_running_mean_sq_[i] += data[i] * std::conj(data[i]);
 | 
| +  }
 | 
| +  ++count_;
 | 
| +
 | 
| +  // TODO(ekmeyerson) Make kWindowBlockSize nonconstant to allow
 | 
| +  // experimentation with different block size,window size pairs.
 | 
| +  if (count_ >= kWindowBlockSize) {
 | 
| +    count_ = 0;
 | 
| +
 | 
| +    for (int i = 0; i < freqs_; ++i) {
 | 
| +      running_mean_[i] -= subhistory_[i][history_cursor_];
 | 
| +      running_mean_sq_[i] -= subhistory_sq_[i][history_cursor_];
 | 
| +
 | 
| +      float scale = 1.f / kWindowBlockSize;
 | 
| +      subhistory_[i][history_cursor_] = sub_running_mean_[i] * scale;
 | 
| +      subhistory_sq_[i][history_cursor_] = sub_running_mean_sq_[i] * scale;
 | 
| +
 | 
| +      sub_running_mean_[i] = std::complex<float>(0.0f, 0.0f);
 | 
| +      sub_running_mean_sq_[i] = std::complex<float>(0.0f, 0.0f);
 | 
| +
 | 
| +      running_mean_[i] += subhistory_[i][history_cursor_];
 | 
| +      running_mean_sq_[i] += subhistory_sq_[i][history_cursor_];
 | 
| +
 | 
| +      scale = 1.f / (buffer_full_ ? window_size_ : history_cursor_ + 1);
 | 
| +      variance_[i] = std::real(running_mean_sq_[i] * scale -
 | 
| +                               running_mean_[i] * scale *
 | 
| +                                   std::conj(running_mean_[i]) * scale);
 | 
| +    }
 | 
| +
 | 
| +    ++history_cursor_;
 | 
| +    if (history_cursor_ >= window_size_) {
 | 
| +      buffer_full_ = true;
 | 
| +      history_cursor_ = 0;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  void VarianceArray::Clear() {
 | 
|    memset(running_mean_.get(), 0, sizeof(*running_mean_.get()) * freqs_);
 | 
|    memset(running_mean_sq_.get(), 0, sizeof(*running_mean_sq_.get()) * freqs_);
 | 
| 
 |