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

Side by Side Diff: webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc

Issue 1234463003: Integrate Intelligibility with APM (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addr. comments from aluebs (incl. support diff num fwd/rev channels) Created 5 years, 5 months 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 return mean + (data - mean) / static_cast<float>(count); 59 return mean + (data - mean) / static_cast<float>(count);
60 } 60 }
61 61
62 void AddToMean(complex<float> data, int count, complex<float>* mean) { 62 void AddToMean(complex<float> data, int count, complex<float>* mean) {
63 (*mean) = NewMean(*mean, data, count); 63 (*mean) = NewMean(*mean, data, count);
64 } 64 }
65 65
66 66
67 static const int kWindowBlockSize = 10; 67 static const int kWindowBlockSize = 10;
68 68
69 VarianceArray::VarianceArray(int freqs, 69 VarianceArray::VarianceArray(int num_freqs,
70 StepType type, 70 StepType type,
71 int window_size, 71 int window_size,
72 float decay) 72 float decay)
73 : running_mean_(new complex<float>[freqs]()), 73 : running_mean_(new complex<float>[num_freqs]()),
74 running_mean_sq_(new complex<float>[freqs]()), 74 running_mean_sq_(new complex<float>[num_freqs]()),
75 sub_running_mean_(new complex<float>[freqs]()), 75 sub_running_mean_(new complex<float>[num_freqs]()),
76 sub_running_mean_sq_(new complex<float>[freqs]()), 76 sub_running_mean_sq_(new complex<float>[num_freqs]()),
77 variance_(new float[freqs]()), 77 variance_(new float[num_freqs]()),
78 conj_sum_(new float[freqs]()), 78 conj_sum_(new float[num_freqs]()),
79 freqs_(freqs), 79 num_freqs_(num_freqs),
80 window_size_(window_size), 80 window_size_(window_size),
81 decay_(decay), 81 decay_(decay),
82 history_cursor_(0), 82 history_cursor_(0),
83 count_(0), 83 count_(0),
84 array_mean_(0.0f), 84 array_mean_(0.0f),
85 buffer_full_(false) { 85 buffer_full_(false) {
86 history_.reset(new rtc::scoped_ptr<complex<float>[]>[freqs_]()); 86 history_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
87 for (int i = 0; i < freqs_; ++i) { 87 for (int i = 0; i < num_freqs_; ++i) {
88 history_[i].reset(new complex<float>[window_size_]()); 88 history_[i].reset(new complex<float>[window_size_]());
89 } 89 }
90 subhistory_.reset(new rtc::scoped_ptr<complex<float>[]>[freqs_]()); 90 subhistory_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
91 for (int i = 0; i < freqs_; ++i) { 91 for (int i = 0; i < num_freqs_; ++i) {
92 subhistory_[i].reset(new complex<float>[window_size_]()); 92 subhistory_[i].reset(new complex<float>[window_size_]());
93 } 93 }
94 subhistory_sq_.reset(new rtc::scoped_ptr<complex<float>[]>[freqs_]()); 94 subhistory_sq_.reset(new rtc::scoped_ptr<complex<float>[]>[num_freqs_]());
95 for (int i = 0; i < freqs_; ++i) { 95 for (int i = 0; i < num_freqs_; ++i) {
96 subhistory_sq_[i].reset(new complex<float>[window_size_]()); 96 subhistory_sq_[i].reset(new complex<float>[window_size_]());
97 } 97 }
98 switch (type) { 98 switch (type) {
99 case kStepInfinite: 99 case kStepInfinite:
100 step_func_ = &VarianceArray::InfiniteStep; 100 step_func_ = &VarianceArray::InfiniteStep;
101 break; 101 break;
102 case kStepDecaying: 102 case kStepDecaying:
103 step_func_ = &VarianceArray::DecayStep; 103 step_func_ = &VarianceArray::DecayStep;
104 break; 104 break;
105 case kStepWindowed: 105 case kStepWindowed:
106 step_func_ = &VarianceArray::WindowedStep; 106 step_func_ = &VarianceArray::WindowedStep;
107 break; 107 break;
108 case kStepBlocked: 108 case kStepBlocked:
109 step_func_ = &VarianceArray::BlockedStep; 109 step_func_ = &VarianceArray::BlockedStep;
110 break; 110 break;
111 case kStepBlockBasedMovingAverage: 111 case kStepBlockBasedMovingAverage:
112 step_func_ = &VarianceArray::BlockBasedMovingAverage; 112 step_func_ = &VarianceArray::BlockBasedMovingAverage;
113 break; 113 break;
114 } 114 }
115 } 115 }
116 116
117 // Compute the variance with Welford's algorithm, adding some fudge to 117 // Compute the variance with Welford's algorithm, adding some fudge to
118 // the input in case of all-zeroes. 118 // the input in case of all-zeroes.
119 void VarianceArray::InfiniteStep(const complex<float>* data, bool skip_fudge) { 119 void VarianceArray::InfiniteStep(const complex<float>* data, bool skip_fudge) {
120 array_mean_ = 0.0f; 120 array_mean_ = 0.0f;
121 ++count_; 121 ++count_;
122 for (int i = 0; i < freqs_; ++i) { 122 for (int i = 0; i < num_freqs_; ++i) {
123 complex<float> sample = data[i]; 123 complex<float> sample = data[i];
124 if (!skip_fudge) { 124 if (!skip_fudge) {
125 sample = zerofudge(sample); 125 sample = zerofudge(sample);
126 } 126 }
127 if (count_ == 1) { 127 if (count_ == 1) {
128 running_mean_[i] = sample; 128 running_mean_[i] = sample;
129 variance_[i] = 0.0f; 129 variance_[i] = 0.0f;
130 } else { 130 } else {
131 float old_sum = conj_sum_[i]; 131 float old_sum = conj_sum_[i];
132 complex<float> old_mean = running_mean_[i]; 132 complex<float> old_mean = running_mean_[i];
(...skipping 10 matching lines...) Expand all
143 } 143 }
144 array_mean_ += (variance_[i] - array_mean_) / (i + 1); 144 array_mean_ += (variance_[i] - array_mean_) / (i + 1);
145 } 145 }
146 } 146 }
147 147
148 // Compute the variance from the beginning, with exponential decaying of the 148 // Compute the variance from the beginning, with exponential decaying of the
149 // series data. 149 // series data.
150 void VarianceArray::DecayStep(const complex<float>* data, bool /*dummy*/) { 150 void VarianceArray::DecayStep(const complex<float>* data, bool /*dummy*/) {
151 array_mean_ = 0.0f; 151 array_mean_ = 0.0f;
152 ++count_; 152 ++count_;
153 for (int i = 0; i < freqs_; ++i) { 153 for (int i = 0; i < num_freqs_; ++i) {
154 complex<float> sample = data[i]; 154 complex<float> sample = data[i];
155 sample = zerofudge(sample); 155 sample = zerofudge(sample);
156 156
157 if (count_ == 1) { 157 if (count_ == 1) {
158 running_mean_[i] = sample; 158 running_mean_[i] = sample;
159 running_mean_sq_[i] = sample * std::conj(sample); 159 running_mean_sq_[i] = sample * std::conj(sample);
160 variance_[i] = 0.0f; 160 variance_[i] = 0.0f;
161 } else { 161 } else {
162 complex<float> prev = running_mean_[i]; 162 complex<float> prev = running_mean_[i];
163 complex<float> prev2 = running_mean_sq_[i]; 163 complex<float> prev2 = running_mean_sq_[i];
164 running_mean_[i] = decay_ * prev + (1.0f - decay_) * sample; 164 running_mean_[i] = decay_ * prev + (1.0f - decay_) * sample;
165 running_mean_sq_[i] = 165 running_mean_sq_[i] =
166 decay_ * prev2 + (1.0f - decay_) * sample * std::conj(sample); 166 decay_ * prev2 + (1.0f - decay_) * sample * std::conj(sample);
167 // variance_[i] = decay_ * variance_[i] + (1.0f - decay_) * ( 167 // variance_[i] = decay_ * variance_[i] + (1.0f - decay_) * (
168 // (sample - running_mean_[i]) * std::conj(sample - 168 // (sample - running_mean_[i]) * std::conj(sample -
169 // running_mean_[i])).real(); 169 // running_mean_[i])).real();
170 variance_[i] = (running_mean_sq_[i] - 170 variance_[i] = (running_mean_sq_[i] -
171 running_mean_[i] * std::conj(running_mean_[i])).real(); 171 running_mean_[i] * std::conj(running_mean_[i])).real();
172 } 172 }
173 173
174 array_mean_ += (variance_[i] - array_mean_) / (i + 1); 174 array_mean_ += (variance_[i] - array_mean_) / (i + 1);
175 } 175 }
176 } 176 }
177 177
178 // Windowed variance computation. On each step, the variances for the 178 // Windowed variance computation. On each step, the variances for the
179 // window are recomputed from scratch, using Welford's algorithm. 179 // window are recomputed from scratch, using Welford's algorithm.
180 void VarianceArray::WindowedStep(const complex<float>* data, bool /*dummy*/) { 180 void VarianceArray::WindowedStep(const complex<float>* data, bool /*dummy*/) {
181 int num = min(count_ + 1, window_size_); 181 int num = min(count_ + 1, window_size_);
182 array_mean_ = 0.0f; 182 array_mean_ = 0.0f;
183 for (int i = 0; i < freqs_; ++i) { 183 for (int i = 0; i < num_freqs_; ++i) {
184 complex<float> mean; 184 complex<float> mean;
185 float conj_sum = 0.0f; 185 float conj_sum = 0.0f;
186 186
187 history_[i][history_cursor_] = data[i]; 187 history_[i][history_cursor_] = data[i];
188 188
189 mean = history_[i][history_cursor_]; 189 mean = history_[i][history_cursor_];
190 variance_[i] = 0.0f; 190 variance_[i] = 0.0f;
191 for (int j = 1; j < num; ++j) { 191 for (int j = 1; j < num; ++j) {
192 complex<float> sample = 192 complex<float> sample =
193 zerofudge(history_[i][(history_cursor_ + j) % window_size_]); 193 zerofudge(history_[i][(history_cursor_ + j) % window_size_]);
(...skipping 12 matching lines...) Expand all
206 ++count_; 206 ++count_;
207 } 207 }
208 208
209 // Variance with a window of blocks. Within each block, the variances are 209 // Variance with a window of blocks. Within each block, the variances are
210 // recomputed from scratch at every stp, using |Var(X) = E(X^2) - E^2(X)|. 210 // recomputed from scratch at every stp, using |Var(X) = E(X^2) - E^2(X)|.
211 // Once a block is filled with kWindowBlockSize samples, it is added to the 211 // Once a block is filled with kWindowBlockSize samples, it is added to the
212 // history window and a new block is started. The variances for the window 212 // history window and a new block is started. The variances for the window
213 // are recomputed from scratch at each of these transitions. 213 // are recomputed from scratch at each of these transitions.
214 void VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) { 214 void VarianceArray::BlockedStep(const complex<float>* data, bool /*dummy*/) {
215 int blocks = min(window_size_, history_cursor_ + 1); 215 int blocks = min(window_size_, history_cursor_ + 1);
216 for (int i = 0; i < freqs_; ++i) { 216 for (int i = 0; i < num_freqs_; ++i) {
217 AddToMean(data[i], count_ + 1, &sub_running_mean_[i]); 217 AddToMean(data[i], count_ + 1, &sub_running_mean_[i]);
218 AddToMean(data[i] * std::conj(data[i]), count_ + 1, 218 AddToMean(data[i] * std::conj(data[i]), count_ + 1,
219 &sub_running_mean_sq_[i]); 219 &sub_running_mean_sq_[i]);
220 subhistory_[i][history_cursor_ % window_size_] = sub_running_mean_[i]; 220 subhistory_[i][history_cursor_ % window_size_] = sub_running_mean_[i];
221 subhistory_sq_[i][history_cursor_ % window_size_] = sub_running_mean_sq_[i]; 221 subhistory_sq_[i][history_cursor_ % window_size_] = sub_running_mean_sq_[i];
222 222
223 variance_[i] = 223 variance_[i] =
224 (NewMean(running_mean_sq_[i], sub_running_mean_sq_[i], blocks) - 224 (NewMean(running_mean_sq_[i], sub_running_mean_sq_[i], blocks) -
225 NewMean(running_mean_[i], sub_running_mean_[i], blocks) * 225 NewMean(running_mean_[i], sub_running_mean_[i], blocks) *
226 std::conj(NewMean(running_mean_[i], sub_running_mean_[i], blocks))) 226 std::conj(NewMean(running_mean_[i], sub_running_mean_[i], blocks)))
(...skipping 15 matching lines...) Expand all
242 count_ = 0; 242 count_ = 0;
243 } 243 }
244 } 244 }
245 245
246 // Recomputes variances for each window from scratch based on previous window. 246 // Recomputes variances for each window from scratch based on previous window.
247 void VarianceArray::BlockBasedMovingAverage(const std::complex<float>* data, 247 void VarianceArray::BlockBasedMovingAverage(const std::complex<float>* data,
248 bool /*dummy*/) { 248 bool /*dummy*/) {
249 // TODO(ekmeyerson) To mitigate potential divergence, add counter so that 249 // TODO(ekmeyerson) To mitigate potential divergence, add counter so that
250 // after every so often sums are computed scratch by summing over all 250 // after every so often sums are computed scratch by summing over all
251 // elements instead of subtracting oldest and adding newest. 251 // elements instead of subtracting oldest and adding newest.
252 for (int i = 0; i < freqs_; ++i) { 252 for (int i = 0; i < num_freqs_; ++i) {
253 sub_running_mean_[i] += data[i]; 253 sub_running_mean_[i] += data[i];
254 sub_running_mean_sq_[i] += data[i] * std::conj(data[i]); 254 sub_running_mean_sq_[i] += data[i] * std::conj(data[i]);
255 } 255 }
256 ++count_; 256 ++count_;
257 257
258 // TODO(ekmeyerson) Make kWindowBlockSize nonconstant to allow 258 // TODO(ekmeyerson) Make kWindowBlockSize nonconstant to allow
259 // experimentation with different block size,window size pairs. 259 // experimentation with different block size,window size pairs.
260 if (count_ >= kWindowBlockSize) { 260 if (count_ >= kWindowBlockSize) {
261 count_ = 0; 261 count_ = 0;
262 262
263 for (int i = 0; i < freqs_; ++i) { 263 for (int i = 0; i < num_freqs_; ++i) {
264 running_mean_[i] -= subhistory_[i][history_cursor_]; 264 running_mean_[i] -= subhistory_[i][history_cursor_];
265 running_mean_sq_[i] -= subhistory_sq_[i][history_cursor_]; 265 running_mean_sq_[i] -= subhistory_sq_[i][history_cursor_];
266 266
267 float scale = 1.f / kWindowBlockSize; 267 float scale = 1.f / kWindowBlockSize;
268 subhistory_[i][history_cursor_] = sub_running_mean_[i] * scale; 268 subhistory_[i][history_cursor_] = sub_running_mean_[i] * scale;
269 subhistory_sq_[i][history_cursor_] = sub_running_mean_sq_[i] * scale; 269 subhistory_sq_[i][history_cursor_] = sub_running_mean_sq_[i] * scale;
270 270
271 sub_running_mean_[i] = std::complex<float>(0.0f, 0.0f); 271 sub_running_mean_[i] = std::complex<float>(0.0f, 0.0f);
272 sub_running_mean_sq_[i] = std::complex<float>(0.0f, 0.0f); 272 sub_running_mean_sq_[i] = std::complex<float>(0.0f, 0.0f);
273 273
274 running_mean_[i] += subhistory_[i][history_cursor_]; 274 running_mean_[i] += subhistory_[i][history_cursor_];
275 running_mean_sq_[i] += subhistory_sq_[i][history_cursor_]; 275 running_mean_sq_[i] += subhistory_sq_[i][history_cursor_];
276 276
277 scale = 1.f / (buffer_full_ ? window_size_ : history_cursor_ + 1); 277 scale = 1.f / (buffer_full_ ? window_size_ : history_cursor_ + 1);
278 variance_[i] = std::real(running_mean_sq_[i] * scale - 278 variance_[i] = std::real(running_mean_sq_[i] * scale -
279 running_mean_[i] * scale * 279 running_mean_[i] * scale *
280 std::conj(running_mean_[i]) * scale); 280 std::conj(running_mean_[i]) * scale);
281 } 281 }
282 282
283 ++history_cursor_; 283 ++history_cursor_;
284 if (history_cursor_ >= window_size_) { 284 if (history_cursor_ >= window_size_) {
285 buffer_full_ = true; 285 buffer_full_ = true;
286 history_cursor_ = 0; 286 history_cursor_ = 0;
287 } 287 }
288 } 288 }
289 } 289 }
290 290
291 void VarianceArray::Clear() { 291 void VarianceArray::Clear() {
292 memset(running_mean_.get(), 0, sizeof(*running_mean_.get()) * freqs_); 292 memset(running_mean_.get(), 0, sizeof(*running_mean_.get()) * num_freqs_);
293 memset(running_mean_sq_.get(), 0, sizeof(*running_mean_sq_.get()) * freqs_); 293 memset(running_mean_sq_.get(), 0,
294 memset(variance_.get(), 0, sizeof(*variance_.get()) * freqs_); 294 sizeof(*running_mean_sq_.get()) * num_freqs_);
295 memset(conj_sum_.get(), 0, sizeof(*conj_sum_.get()) * freqs_); 295 memset(variance_.get(), 0, sizeof(*variance_.get()) * num_freqs_);
296 memset(conj_sum_.get(), 0, sizeof(*conj_sum_.get()) * num_freqs_);
296 history_cursor_ = 0; 297 history_cursor_ = 0;
297 count_ = 0; 298 count_ = 0;
298 array_mean_ = 0.0f; 299 array_mean_ = 0.0f;
299 } 300 }
300 301
301 void VarianceArray::ApplyScale(float scale) { 302 void VarianceArray::ApplyScale(float scale) {
302 array_mean_ = 0.0f; 303 array_mean_ = 0.0f;
303 for (int i = 0; i < freqs_; ++i) { 304 for (int i = 0; i < num_freqs_; ++i) {
304 variance_[i] *= scale * scale; 305 variance_[i] *= scale * scale;
305 array_mean_ += (variance_[i] - array_mean_) / (i + 1); 306 array_mean_ += (variance_[i] - array_mean_) / (i + 1);
306 } 307 }
307 } 308 }
308 309
309 GainApplier::GainApplier(int freqs, float change_limit) 310 GainApplier::GainApplier(int freqs, float change_limit)
310 : freqs_(freqs), 311 : num_freqs_(freqs),
311 change_limit_(change_limit), 312 change_limit_(change_limit),
312 target_(new float[freqs]()), 313 target_(new float[freqs]()),
313 current_(new float[freqs]()) { 314 current_(new float[freqs]()) {
314 for (int i = 0; i < freqs; ++i) { 315 for (int i = 0; i < freqs; ++i) {
315 target_[i] = 1.0f; 316 target_[i] = 1.0f;
316 current_[i] = 1.0f; 317 current_[i] = 1.0f;
317 } 318 }
318 } 319 }
319 320
320 void GainApplier::Apply(const complex<float>* in_block, 321 void GainApplier::Apply(const complex<float>* in_block,
321 complex<float>* out_block) { 322 complex<float>* out_block) {
322 for (int i = 0; i < freqs_; ++i) { 323 for (int i = 0; i < num_freqs_; ++i) {
323 float factor = sqrtf(fabsf(current_[i])); 324 float factor = sqrtf(fabsf(current_[i]));
324 if (!std::isnormal(factor)) { 325 if (!std::isnormal(factor)) {
325 factor = 1.0f; 326 factor = 1.0f;
326 } 327 }
327 out_block[i] = factor * in_block[i]; 328 out_block[i] = factor * in_block[i];
328 current_[i] = UpdateFactor(target_[i], current_[i], change_limit_); 329 current_[i] = UpdateFactor(target_[i], current_[i], change_limit_);
329 } 330 }
330 } 331 }
331 332
333 void GainApplier::Clear() {
334 for (int i = 0; i < num_freqs_; ++i) {
335 target_[i] = 1.f;
336 }
337 }
338
339 // TODO(ekmeyerson): Can reduce from O(|num_freqs_|) to O(1) if necessary.
340 bool GainApplier::IsIdentity() {
341 for (int i = 0; i < num_freqs_; ++i) {
342 if (current_[i] != 1.f || target_[i] != 1.f) {
343 return false;
344 }
345 }
346 return true;
347 }
348
332 } // namespace intelligibility 349 } // namespace intelligibility
333 350
334 } // namespace webrtc 351 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698