ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 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 |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h" |
| 12 | |
ekm | 35b72fb | 2015-07-10 14:11:52 -0700 | [diff] [blame] | 13 | #include <math.h> |
ekmeyerson | 3ab2f14 | 2015-07-23 12:15:24 -0700 | [diff] [blame] | 14 | #include <stdlib.h> |
ekm | 35b72fb | 2015-07-10 14:11:52 -0700 | [diff] [blame] | 15 | #include <string.h> |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 16 | #include <algorithm> |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 17 | |
ekm | 35b72fb | 2015-07-10 14:11:52 -0700 | [diff] [blame] | 18 | namespace webrtc { |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 19 | |
ekm | 35b72fb | 2015-07-10 14:11:52 -0700 | [diff] [blame] | 20 | namespace intelligibility { |
| 21 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 22 | namespace { |
| 23 | |
| 24 | // Return |current| changed towards |target|, with the change being at most |
| 25 | // |limit|. |
ekm | 35b72fb | 2015-07-10 14:11:52 -0700 | [diff] [blame] | 26 | float UpdateFactor(float target, float current, float limit) { |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 27 | float delta = fabsf(target - current); |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 28 | float sign = copysign(1.f, target - current); |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 29 | return current + sign * fminf(delta, limit); |
| 30 | } |
| 31 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 32 | } // namespace |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 33 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 34 | PowerEstimator::PowerEstimator(size_t num_freqs, |
| 35 | float decay) |
| 36 | : magnitude_(new float[num_freqs]()), |
| 37 | power_(new float[num_freqs]()), |
ekmeyerson | 60d9b33 | 2015-08-14 10:35:55 -0700 | [diff] [blame] | 38 | num_freqs_(num_freqs), |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 39 | decay_(decay) { |
| 40 | memset(magnitude_.get(), 0, sizeof(*magnitude_.get()) * num_freqs_); |
| 41 | memset(power_.get(), 0, sizeof(*power_.get()) * num_freqs_); |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 42 | } |
| 43 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 44 | // Compute the magnitude from the beginning, with exponential decaying of the |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 45 | // series data. |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 46 | void PowerEstimator::Step(const std::complex<float>* data) { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 47 | for (size_t i = 0; i < num_freqs_; ++i) { |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 48 | magnitude_[i] = decay_ * magnitude_[i] + |
| 49 | (1.f - decay_) * std::abs(data[i]); |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 50 | } |
| 51 | } |
| 52 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 53 | const float* PowerEstimator::Power() { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 54 | for (size_t i = 0; i < num_freqs_; ++i) { |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 55 | power_[i] = magnitude_[i] * magnitude_[i]; |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 56 | } |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 57 | return &power_[0]; |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 58 | } |
| 59 | |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 60 | GainApplier::GainApplier(size_t freqs, float change_limit) |
ekmeyerson | 60d9b33 | 2015-08-14 10:35:55 -0700 | [diff] [blame] | 61 | : num_freqs_(freqs), |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 62 | change_limit_(change_limit), |
| 63 | target_(new float[freqs]()), |
| 64 | current_(new float[freqs]()) { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 65 | for (size_t i = 0; i < freqs; ++i) { |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 66 | target_[i] = 1.f; |
| 67 | current_[i] = 1.f; |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 68 | } |
| 69 | } |
| 70 | |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 71 | void GainApplier::Apply(const std::complex<float>* in_block, |
| 72 | std::complex<float>* out_block) { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 73 | for (size_t i = 0; i < num_freqs_; ++i) { |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 74 | float factor = sqrtf(fabsf(current_[i])); |
| 75 | if (!std::isnormal(factor)) { |
Alejandro Luebs | 3234819 | 2016-02-17 20:04:19 -0800 | [diff] [blame] | 76 | factor = 1.f; |
ekm | 030249d | 2015-06-15 13:02:24 -0700 | [diff] [blame] | 77 | } |
| 78 | out_block[i] = factor * in_block[i]; |
| 79 | current_[i] = UpdateFactor(target_[i], current_[i], change_limit_); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | } // namespace intelligibility |
| 84 | |
| 85 | } // namespace webrtc |