1030249dd247444687663c4969ff078dc0a4b24acekm/*
2030249dd247444687663c4969ff078dc0a4b24acekm *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3030249dd247444687663c4969ff078dc0a4b24acekm *
4030249dd247444687663c4969ff078dc0a4b24acekm *  Use of this source code is governed by a BSD-style license
5030249dd247444687663c4969ff078dc0a4b24acekm *  that can be found in the LICENSE file in the root of the source
6030249dd247444687663c4969ff078dc0a4b24acekm *  tree. An additional intellectual property rights grant can be found
7030249dd247444687663c4969ff078dc0a4b24acekm *  in the file PATENTS.  All contributing project authors may
8030249dd247444687663c4969ff078dc0a4b24acekm *  be found in the AUTHORS file in the root of the source tree.
9030249dd247444687663c4969ff078dc0a4b24acekm */
10030249dd247444687663c4969ff078dc0a4b24acekm
11db4fecfb01ac51e936e4b7496a4929e713080f07ekm//
12db4fecfb01ac51e936e4b7496a4929e713080f07ekm//  Implements helper functions and classes for intelligibility enhancement.
13db4fecfb01ac51e936e4b7496a4929e713080f07ekm//
14db4fecfb01ac51e936e4b7496a4929e713080f07ekm
15030249dd247444687663c4969ff078dc0a4b24acekm#include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h"
16030249dd247444687663c4969ff078dc0a4b24acekm
1735b72fbceb09031cbd6039e0dbbd44ed24296509ekm#include <math.h>
183ab2f14d56db91665002f36f899c0a97f926d91fekmeyerson#include <stdlib.h>
1935b72fbceb09031cbd6039e0dbbd44ed24296509ekm#include <string.h>
20030249dd247444687663c4969ff078dc0a4b24acekm#include <algorithm>
21030249dd247444687663c4969ff078dc0a4b24acekm
22030249dd247444687663c4969ff078dc0a4b24acekmusing std::complex;
2335b72fbceb09031cbd6039e0dbbd44ed24296509ekmusing std::min;
2435b72fbceb09031cbd6039e0dbbd44ed24296509ekm
2535b72fbceb09031cbd6039e0dbbd44ed24296509ekmnamespace webrtc {
26030249dd247444687663c4969ff078dc0a4b24acekm
2735b72fbceb09031cbd6039e0dbbd44ed24296509ekmnamespace intelligibility {
28030249dd247444687663c4969ff078dc0a4b24acekm
2935b72fbceb09031cbd6039e0dbbd44ed24296509ekmfloat UpdateFactor(float target, float current, float limit) {
30030249dd247444687663c4969ff078dc0a4b24acekm  float delta = fabsf(target - current);
31030249dd247444687663c4969ff078dc0a4b24acekm  float sign = copysign(1.0f, target - current);
32030249dd247444687663c4969ff078dc0a4b24acekm  return current + sign * fminf(delta, limit);
33030249dd247444687663c4969ff078dc0a4b24acekm}
34030249dd247444687663c4969ff078dc0a4b24acekm
353ab2f14d56db91665002f36f899c0a97f926d91fekmeyersonfloat AddDitherIfZero(float value) {
363ab2f14d56db91665002f36f899c0a97f926d91fekmeyerson  return value == 0.f ? std::rand() * 0.01f / RAND_MAX : value;
37030249dd247444687663c4969ff078dc0a4b24acekm}
38030249dd247444687663c4969ff078dc0a4b24acekm
3935b72fbceb09031cbd6039e0dbbd44ed24296509ekmcomplex<float> zerofudge(complex<float> c) {
403ab2f14d56db91665002f36f899c0a97f926d91fekmeyerson  return complex<float>(AddDitherIfZero(c.real()), AddDitherIfZero(c.imag()));
41030249dd247444687663c4969ff078dc0a4b24acekm}
42030249dd247444687663c4969ff078dc0a4b24acekm
43dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingcomplex<float> NewMean(complex<float> mean, complex<float> data, size_t count) {
44030249dd247444687663c4969ff078dc0a4b24acekm  return mean + (data - mean) / static_cast<float>(count);
45030249dd247444687663c4969ff078dc0a4b24acekm}
46030249dd247444687663c4969ff078dc0a4b24acekm
47dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingvoid AddToMean(complex<float> data, size_t count, complex<float>* mean) {
48030249dd247444687663c4969ff078dc0a4b24acekm  (*mean) = NewMean(*mean, data, count);
49030249dd247444687663c4969ff078dc0a4b24acekm}
50030249dd247444687663c4969ff078dc0a4b24acekm
51030249dd247444687663c4969ff078dc0a4b24acekm
52dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kWindowBlockSize = 10;
53030249dd247444687663c4969ff078dc0a4b24acekm
54dce40cf804019a9898b6ab8d8262466b697c56e0Peter KastingVarianceArray::VarianceArray(size_t num_freqs,
55db4fecfb01ac51e936e4b7496a4929e713080f07ekm                             StepType type,
56dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                             size_t window_size,
57030249dd247444687663c4969ff078dc0a4b24acekm                             float decay)
5860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    : running_mean_(new complex<float>[num_freqs]()),
5960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      running_mean_sq_(new complex<float>[num_freqs]()),
6060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      sub_running_mean_(new complex<float>[num_freqs]()),
6160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      sub_running_mean_sq_(new complex<float>[num_freqs]()),
6260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      variance_(new float[num_freqs]()),
6360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      conj_sum_(new float[num_freqs]()),
6460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      num_freqs_(num_freqs),
65030249dd247444687663c4969ff078dc0a4b24acekm      window_size_(window_size),
66030249dd247444687663c4969ff078dc0a4b24acekm      decay_(decay),
67030249dd247444687663c4969ff078dc0a4b24acekm      history_cursor_(0),
68030249dd247444687663c4969ff078dc0a4b24acekm      count_(0),
6935b72fbceb09031cbd6039e0dbbd44ed24296509ekm      array_mean_(0.0f),
7035b72fbceb09031cbd6039e0dbbd44ed24296509ekm      buffer_full_(false) {
7160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  history_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
72dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
73030249dd247444687663c4969ff078dc0a4b24acekm    history_[i].reset(new complex<float>[window_size_]());
74030249dd247444687663c4969ff078dc0a4b24acekm  }
7560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  subhistory_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
76dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
77030249dd247444687663c4969ff078dc0a4b24acekm    subhistory_[i].reset(new complex<float>[window_size_]());
78030249dd247444687663c4969ff078dc0a4b24acekm  }
7960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  subhistory_sq_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
80dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
81030249dd247444687663c4969ff078dc0a4b24acekm    subhistory_sq_[i].reset(new complex<float>[window_size_]());
82030249dd247444687663c4969ff078dc0a4b24acekm  }
83030249dd247444687663c4969ff078dc0a4b24acekm  switch (type) {
84030249dd247444687663c4969ff078dc0a4b24acekm    case kStepInfinite:
85030249dd247444687663c4969ff078dc0a4b24acekm      step_func_ = &VarianceArray::InfiniteStep;
86030249dd247444687663c4969ff078dc0a4b24acekm      break;
87030249dd247444687663c4969ff078dc0a4b24acekm    case kStepDecaying:
88030249dd247444687663c4969ff078dc0a4b24acekm      step_func_ = &VarianceArray::DecayStep;
89030249dd247444687663c4969ff078dc0a4b24acekm      break;
90030249dd247444687663c4969ff078dc0a4b24acekm    case kStepWindowed:
91030249dd247444687663c4969ff078dc0a4b24acekm      step_func_ = &VarianceArray::WindowedStep;
92030249dd247444687663c4969ff078dc0a4b24acekm      break;
93030249dd247444687663c4969ff078dc0a4b24acekm    case kStepBlocked:
94030249dd247444687663c4969ff078dc0a4b24acekm      step_func_ = &VarianceArray::BlockedStep;
95030249dd247444687663c4969ff078dc0a4b24acekm      break;
9635b72fbceb09031cbd6039e0dbbd44ed24296509ekm    case kStepBlockBasedMovingAverage:
9735b72fbceb09031cbd6039e0dbbd44ed24296509ekm      step_func_ = &VarianceArray::BlockBasedMovingAverage;
9835b72fbceb09031cbd6039e0dbbd44ed24296509ekm      break;
99030249dd247444687663c4969ff078dc0a4b24acekm  }
100030249dd247444687663c4969ff078dc0a4b24acekm}
101030249dd247444687663c4969ff078dc0a4b24acekm
102030249dd247444687663c4969ff078dc0a4b24acekm// Compute the variance with Welford's algorithm, adding some fudge to
103030249dd247444687663c4969ff078dc0a4b24acekm// the input in case of all-zeroes.
104030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::InfiniteStep(const complex<float>* data, bool skip_fudge) {
105030249dd247444687663c4969ff078dc0a4b24acekm  array_mean_ = 0.0f;
106030249dd247444687663c4969ff078dc0a4b24acekm  ++count_;
107dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
108030249dd247444687663c4969ff078dc0a4b24acekm    complex<float> sample = data[i];
109030249dd247444687663c4969ff078dc0a4b24acekm    if (!skip_fudge) {
110030249dd247444687663c4969ff078dc0a4b24acekm      sample = zerofudge(sample);
111030249dd247444687663c4969ff078dc0a4b24acekm    }
112030249dd247444687663c4969ff078dc0a4b24acekm    if (count_ == 1) {
113030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_[i] = sample;
114030249dd247444687663c4969ff078dc0a4b24acekm      variance_[i] = 0.0f;
115030249dd247444687663c4969ff078dc0a4b24acekm    } else {
116030249dd247444687663c4969ff078dc0a4b24acekm      float old_sum = conj_sum_[i];
117030249dd247444687663c4969ff078dc0a4b24acekm      complex<float> old_mean = running_mean_[i];
118db4fecfb01ac51e936e4b7496a4929e713080f07ekm      running_mean_[i] =
119db4fecfb01ac51e936e4b7496a4929e713080f07ekm          old_mean + (sample - old_mean) / static_cast<float>(count_);
120db4fecfb01ac51e936e4b7496a4929e713080f07ekm      conj_sum_[i] =
121db4fecfb01ac51e936e4b7496a4929e713080f07ekm          (old_sum + std::conj(sample - old_mean) * (sample - running_mean_[i]))
122db4fecfb01ac51e936e4b7496a4929e713080f07ekm              .real();
123db4fecfb01ac51e936e4b7496a4929e713080f07ekm      variance_[i] =
1243ab2f14d56db91665002f36f899c0a97f926d91fekmeyerson          conj_sum_[i] / (count_ - 1);
125030249dd247444687663c4969ff078dc0a4b24acekm    }
126030249dd247444687663c4969ff078dc0a4b24acekm    array_mean_ += (variance_[i] - array_mean_) / (i + 1);
127030249dd247444687663c4969ff078dc0a4b24acekm  }
128030249dd247444687663c4969ff078dc0a4b24acekm}
129030249dd247444687663c4969ff078dc0a4b24acekm
130030249dd247444687663c4969ff078dc0a4b24acekm// Compute the variance from the beginning, with exponential decaying of the
131030249dd247444687663c4969ff078dc0a4b24acekm// series data.
132030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::DecayStep(const complex<float>* data, bool /*dummy*/) {
133030249dd247444687663c4969ff078dc0a4b24acekm  array_mean_ = 0.0f;
134030249dd247444687663c4969ff078dc0a4b24acekm  ++count_;
135dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
136030249dd247444687663c4969ff078dc0a4b24acekm    complex<float> sample = data[i];
137030249dd247444687663c4969ff078dc0a4b24acekm    sample = zerofudge(sample);
138030249dd247444687663c4969ff078dc0a4b24acekm
139030249dd247444687663c4969ff078dc0a4b24acekm    if (count_ == 1) {
140030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_[i] = sample;
141030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_sq_[i] = sample * std::conj(sample);
142030249dd247444687663c4969ff078dc0a4b24acekm      variance_[i] = 0.0f;
143030249dd247444687663c4969ff078dc0a4b24acekm    } else {
144030249dd247444687663c4969ff078dc0a4b24acekm      complex<float> prev = running_mean_[i];
145030249dd247444687663c4969ff078dc0a4b24acekm      complex<float> prev2 = running_mean_sq_[i];
146030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_[i] = decay_ * prev + (1.0f - decay_) * sample;
147db4fecfb01ac51e936e4b7496a4929e713080f07ekm      running_mean_sq_[i] =
148db4fecfb01ac51e936e4b7496a4929e713080f07ekm          decay_ * prev2 + (1.0f - decay_) * sample * std::conj(sample);
149db4fecfb01ac51e936e4b7496a4929e713080f07ekm      variance_[i] = (running_mean_sq_[i] -
150db4fecfb01ac51e936e4b7496a4929e713080f07ekm                      running_mean_[i] * std::conj(running_mean_[i])).real();
151030249dd247444687663c4969ff078dc0a4b24acekm    }
152030249dd247444687663c4969ff078dc0a4b24acekm
153030249dd247444687663c4969ff078dc0a4b24acekm    array_mean_ += (variance_[i] - array_mean_) / (i + 1);
154030249dd247444687663c4969ff078dc0a4b24acekm  }
155030249dd247444687663c4969ff078dc0a4b24acekm}
156030249dd247444687663c4969ff078dc0a4b24acekm
157030249dd247444687663c4969ff078dc0a4b24acekm// Windowed variance computation. On each step, the variances for the
158030249dd247444687663c4969ff078dc0a4b24acekm// window are recomputed from scratch, using Welford's algorithm.
159030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::WindowedStep(const complex<float>* data, bool /*dummy*/) {
160dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num = min(count_ + 1, window_size_);
161030249dd247444687663c4969ff078dc0a4b24acekm  array_mean_ = 0.0f;
162dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
163030249dd247444687663c4969ff078dc0a4b24acekm    complex<float> mean;
164030249dd247444687663c4969ff078dc0a4b24acekm    float conj_sum = 0.0f;
165030249dd247444687663c4969ff078dc0a4b24acekm
166030249dd247444687663c4969ff078dc0a4b24acekm    history_[i][history_cursor_] = data[i];
167030249dd247444687663c4969ff078dc0a4b24acekm
168030249dd247444687663c4969ff078dc0a4b24acekm    mean = history_[i][history_cursor_];
169030249dd247444687663c4969ff078dc0a4b24acekm    variance_[i] = 0.0f;
170dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t j = 1; j < num; ++j) {
171db4fecfb01ac51e936e4b7496a4929e713080f07ekm      complex<float> sample =
172db4fecfb01ac51e936e4b7496a4929e713080f07ekm          zerofudge(history_[i][(history_cursor_ + j) % window_size_]);
173030249dd247444687663c4969ff078dc0a4b24acekm      sample = history_[i][(history_cursor_ + j) % window_size_];
174030249dd247444687663c4969ff078dc0a4b24acekm      float old_sum = conj_sum;
175030249dd247444687663c4969ff078dc0a4b24acekm      complex<float> old_mean = mean;
176030249dd247444687663c4969ff078dc0a4b24acekm
177030249dd247444687663c4969ff078dc0a4b24acekm      mean = old_mean + (sample - old_mean) / static_cast<float>(j + 1);
178db4fecfb01ac51e936e4b7496a4929e713080f07ekm      conj_sum =
179db4fecfb01ac51e936e4b7496a4929e713080f07ekm          (old_sum + std::conj(sample - old_mean) * (sample - mean)).real();
180030249dd247444687663c4969ff078dc0a4b24acekm      variance_[i] = conj_sum / (j);
181030249dd247444687663c4969ff078dc0a4b24acekm    }
182030249dd247444687663c4969ff078dc0a4b24acekm    array_mean_ += (variance_[i] - array_mean_) / (i + 1);
183030249dd247444687663c4969ff078dc0a4b24acekm  }
184030249dd247444687663c4969ff078dc0a4b24acekm  history_cursor_ = (history_cursor_ + 1) % window_size_;
185030249dd247444687663c4969ff078dc0a4b24acekm  ++count_;
186030249dd247444687663c4969ff078dc0a4b24acekm}
187030249dd247444687663c4969ff078dc0a4b24acekm
188030249dd247444687663c4969ff078dc0a4b24acekm// Variance with a window of blocks. Within each block, the variances are
189030249dd247444687663c4969ff078dc0a4b24acekm// recomputed from scratch at every stp, using |Var(X) = E(X^2) - E^2(X)|.
190030249dd247444687663c4969ff078dc0a4b24acekm// Once a block is filled with kWindowBlockSize samples, it is added to the
191030249dd247444687663c4969ff078dc0a4b24acekm// history window and a new block is started. The variances for the window
192030249dd247444687663c4969ff078dc0a4b24acekm// are recomputed from scratch at each of these transitions.
193030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) {
194dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t blocks = min(window_size_, history_cursor_ + 1);
195dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
196030249dd247444687663c4969ff078dc0a4b24acekm    AddToMean(data[i], count_ + 1, &sub_running_mean_[i]);
197030249dd247444687663c4969ff078dc0a4b24acekm    AddToMean(data[i] * std::conj(data[i]), count_ + 1,
198030249dd247444687663c4969ff078dc0a4b24acekm              &sub_running_mean_sq_[i]);
199030249dd247444687663c4969ff078dc0a4b24acekm    subhistory_[i][history_cursor_ % window_size_] = sub_running_mean_[i];
200030249dd247444687663c4969ff078dc0a4b24acekm    subhistory_sq_[i][history_cursor_ % window_size_] = sub_running_mean_sq_[i];
201030249dd247444687663c4969ff078dc0a4b24acekm
202db4fecfb01ac51e936e4b7496a4929e713080f07ekm    variance_[i] =
203db4fecfb01ac51e936e4b7496a4929e713080f07ekm        (NewMean(running_mean_sq_[i], sub_running_mean_sq_[i], blocks) -
204db4fecfb01ac51e936e4b7496a4929e713080f07ekm         NewMean(running_mean_[i], sub_running_mean_[i], blocks) *
205db4fecfb01ac51e936e4b7496a4929e713080f07ekm             std::conj(NewMean(running_mean_[i], sub_running_mean_[i], blocks)))
206db4fecfb01ac51e936e4b7496a4929e713080f07ekm            .real();
207030249dd247444687663c4969ff078dc0a4b24acekm    if (count_ == kWindowBlockSize - 1) {
208030249dd247444687663c4969ff078dc0a4b24acekm      sub_running_mean_[i] = complex<float>(0.0f, 0.0f);
209030249dd247444687663c4969ff078dc0a4b24acekm      sub_running_mean_sq_[i] = complex<float>(0.0f, 0.0f);
210030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_[i] = complex<float>(0.0f, 0.0f);
211030249dd247444687663c4969ff078dc0a4b24acekm      running_mean_sq_[i] = complex<float>(0.0f, 0.0f);
212dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      for (size_t j = 0; j < min(window_size_, history_cursor_); ++j) {
21335b72fbceb09031cbd6039e0dbbd44ed24296509ekm        AddToMean(subhistory_[i][j], j + 1, &running_mean_[i]);
21435b72fbceb09031cbd6039e0dbbd44ed24296509ekm        AddToMean(subhistory_sq_[i][j], j + 1, &running_mean_sq_[i]);
215030249dd247444687663c4969ff078dc0a4b24acekm      }
216030249dd247444687663c4969ff078dc0a4b24acekm      ++history_cursor_;
217030249dd247444687663c4969ff078dc0a4b24acekm    }
218030249dd247444687663c4969ff078dc0a4b24acekm  }
219030249dd247444687663c4969ff078dc0a4b24acekm  ++count_;
220030249dd247444687663c4969ff078dc0a4b24acekm  if (count_ == kWindowBlockSize) {
221030249dd247444687663c4969ff078dc0a4b24acekm    count_ = 0;
222030249dd247444687663c4969ff078dc0a4b24acekm  }
223030249dd247444687663c4969ff078dc0a4b24acekm}
224030249dd247444687663c4969ff078dc0a4b24acekm
22535b72fbceb09031cbd6039e0dbbd44ed24296509ekm// Recomputes variances for each window from scratch based on previous window.
22635b72fbceb09031cbd6039e0dbbd44ed24296509ekmvoid VarianceArray::BlockBasedMovingAverage(const std::complex<float>* data,
22735b72fbceb09031cbd6039e0dbbd44ed24296509ekm                                            bool /*dummy*/) {
22835b72fbceb09031cbd6039e0dbbd44ed24296509ekm  // TODO(ekmeyerson) To mitigate potential divergence, add counter so that
22935b72fbceb09031cbd6039e0dbbd44ed24296509ekm  // after every so often sums are computed scratch by summing over all
23035b72fbceb09031cbd6039e0dbbd44ed24296509ekm  // elements instead of subtracting oldest and adding newest.
231dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
23235b72fbceb09031cbd6039e0dbbd44ed24296509ekm    sub_running_mean_[i] += data[i];
23335b72fbceb09031cbd6039e0dbbd44ed24296509ekm    sub_running_mean_sq_[i] += data[i] * std::conj(data[i]);
23435b72fbceb09031cbd6039e0dbbd44ed24296509ekm  }
23535b72fbceb09031cbd6039e0dbbd44ed24296509ekm  ++count_;
23635b72fbceb09031cbd6039e0dbbd44ed24296509ekm
23735b72fbceb09031cbd6039e0dbbd44ed24296509ekm  // TODO(ekmeyerson) Make kWindowBlockSize nonconstant to allow
23835b72fbceb09031cbd6039e0dbbd44ed24296509ekm  // experimentation with different block size,window size pairs.
23935b72fbceb09031cbd6039e0dbbd44ed24296509ekm  if (count_ >= kWindowBlockSize) {
24035b72fbceb09031cbd6039e0dbbd44ed24296509ekm    count_ = 0;
24135b72fbceb09031cbd6039e0dbbd44ed24296509ekm
242dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t i = 0; i < num_freqs_; ++i) {
24335b72fbceb09031cbd6039e0dbbd44ed24296509ekm      running_mean_[i] -= subhistory_[i][history_cursor_];
24435b72fbceb09031cbd6039e0dbbd44ed24296509ekm      running_mean_sq_[i] -= subhistory_sq_[i][history_cursor_];
24535b72fbceb09031cbd6039e0dbbd44ed24296509ekm
24635b72fbceb09031cbd6039e0dbbd44ed24296509ekm      float scale = 1.f / kWindowBlockSize;
24735b72fbceb09031cbd6039e0dbbd44ed24296509ekm      subhistory_[i][history_cursor_] = sub_running_mean_[i] * scale;
24835b72fbceb09031cbd6039e0dbbd44ed24296509ekm      subhistory_sq_[i][history_cursor_] = sub_running_mean_sq_[i] * scale;
24935b72fbceb09031cbd6039e0dbbd44ed24296509ekm
25035b72fbceb09031cbd6039e0dbbd44ed24296509ekm      sub_running_mean_[i] = std::complex<float>(0.0f, 0.0f);
25135b72fbceb09031cbd6039e0dbbd44ed24296509ekm      sub_running_mean_sq_[i] = std::complex<float>(0.0f, 0.0f);
25235b72fbceb09031cbd6039e0dbbd44ed24296509ekm
25335b72fbceb09031cbd6039e0dbbd44ed24296509ekm      running_mean_[i] += subhistory_[i][history_cursor_];
25435b72fbceb09031cbd6039e0dbbd44ed24296509ekm      running_mean_sq_[i] += subhistory_sq_[i][history_cursor_];
25535b72fbceb09031cbd6039e0dbbd44ed24296509ekm
25635b72fbceb09031cbd6039e0dbbd44ed24296509ekm      scale = 1.f / (buffer_full_ ? window_size_ : history_cursor_ + 1);
25735b72fbceb09031cbd6039e0dbbd44ed24296509ekm      variance_[i] = std::real(running_mean_sq_[i] * scale -
25835b72fbceb09031cbd6039e0dbbd44ed24296509ekm                               running_mean_[i] * scale *
25935b72fbceb09031cbd6039e0dbbd44ed24296509ekm                                   std::conj(running_mean_[i]) * scale);
26035b72fbceb09031cbd6039e0dbbd44ed24296509ekm    }
26135b72fbceb09031cbd6039e0dbbd44ed24296509ekm
26235b72fbceb09031cbd6039e0dbbd44ed24296509ekm    ++history_cursor_;
26335b72fbceb09031cbd6039e0dbbd44ed24296509ekm    if (history_cursor_ >= window_size_) {
26435b72fbceb09031cbd6039e0dbbd44ed24296509ekm      buffer_full_ = true;
26535b72fbceb09031cbd6039e0dbbd44ed24296509ekm      history_cursor_ = 0;
26635b72fbceb09031cbd6039e0dbbd44ed24296509ekm    }
26735b72fbceb09031cbd6039e0dbbd44ed24296509ekm  }
26835b72fbceb09031cbd6039e0dbbd44ed24296509ekm}
26935b72fbceb09031cbd6039e0dbbd44ed24296509ekm
270030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::Clear() {
27160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  memset(running_mean_.get(), 0, sizeof(*running_mean_.get()) * num_freqs_);
27260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  memset(running_mean_sq_.get(), 0,
27360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson         sizeof(*running_mean_sq_.get()) * num_freqs_);
27460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  memset(variance_.get(), 0, sizeof(*variance_.get()) * num_freqs_);
27560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  memset(conj_sum_.get(), 0, sizeof(*conj_sum_.get()) * num_freqs_);
276030249dd247444687663c4969ff078dc0a4b24acekm  history_cursor_ = 0;
277030249dd247444687663c4969ff078dc0a4b24acekm  count_ = 0;
278030249dd247444687663c4969ff078dc0a4b24acekm  array_mean_ = 0.0f;
279030249dd247444687663c4969ff078dc0a4b24acekm}
280030249dd247444687663c4969ff078dc0a4b24acekm
281030249dd247444687663c4969ff078dc0a4b24acekmvoid VarianceArray::ApplyScale(float scale) {
282030249dd247444687663c4969ff078dc0a4b24acekm  array_mean_ = 0.0f;
283dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
284030249dd247444687663c4969ff078dc0a4b24acekm    variance_[i] *= scale * scale;
285030249dd247444687663c4969ff078dc0a4b24acekm    array_mean_ += (variance_[i] - array_mean_) / (i + 1);
286030249dd247444687663c4969ff078dc0a4b24acekm  }
287030249dd247444687663c4969ff078dc0a4b24acekm}
288030249dd247444687663c4969ff078dc0a4b24acekm
289dce40cf804019a9898b6ab8d8262466b697c56e0Peter KastingGainApplier::GainApplier(size_t freqs, float change_limit)
29060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    : num_freqs_(freqs),
291030249dd247444687663c4969ff078dc0a4b24acekm      change_limit_(change_limit),
292030249dd247444687663c4969ff078dc0a4b24acekm      target_(new float[freqs]()),
293030249dd247444687663c4969ff078dc0a4b24acekm      current_(new float[freqs]()) {
294dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < freqs; ++i) {
295030249dd247444687663c4969ff078dc0a4b24acekm    target_[i] = 1.0f;
296030249dd247444687663c4969ff078dc0a4b24acekm    current_[i] = 1.0f;
297030249dd247444687663c4969ff078dc0a4b24acekm  }
298030249dd247444687663c4969ff078dc0a4b24acekm}
299030249dd247444687663c4969ff078dc0a4b24acekm
300030249dd247444687663c4969ff078dc0a4b24acekmvoid GainApplier::Apply(const complex<float>* in_block,
301030249dd247444687663c4969ff078dc0a4b24acekm                        complex<float>* out_block) {
302dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < num_freqs_; ++i) {
303030249dd247444687663c4969ff078dc0a4b24acekm    float factor = sqrtf(fabsf(current_[i]));
304030249dd247444687663c4969ff078dc0a4b24acekm    if (!std::isnormal(factor)) {
305030249dd247444687663c4969ff078dc0a4b24acekm      factor = 1.0f;
306030249dd247444687663c4969ff078dc0a4b24acekm    }
307030249dd247444687663c4969ff078dc0a4b24acekm    out_block[i] = factor * in_block[i];
308030249dd247444687663c4969ff078dc0a4b24acekm    current_[i] = UpdateFactor(target_[i], current_[i], change_limit_);
309030249dd247444687663c4969ff078dc0a4b24acekm  }
310030249dd247444687663c4969ff078dc0a4b24acekm}
311030249dd247444687663c4969ff078dc0a4b24acekm
312030249dd247444687663c4969ff078dc0a4b24acekm}  // namespace intelligibility
313030249dd247444687663c4969ff078dc0a4b24acekm
314030249dd247444687663c4969ff078dc0a4b24acekm}  // namespace webrtc
315