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