blob: b6917f4407723055f11b40fac5dff147c9a6550d [file] [log] [blame]
ekm030249d2015-06-15 13:02:24 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/intelligibility/intelligibility_utils.h"
ekm030249d2015-06-15 13:02:24 -070012
ekm35b72fb2015-07-10 14:11:52 -070013#include <math.h>
ekmeyerson3ab2f142015-07-23 12:15:24 -070014#include <stdlib.h>
ekm35b72fb2015-07-10 14:11:52 -070015#include <string.h>
ekm030249d2015-06-15 13:02:24 -070016#include <algorithm>
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080017#include <limits>
ekm030249d2015-06-15 13:02:24 -070018
Karl Wiberge40468b2017-11-22 10:42:26 +010019#include "rtc_base/numerics/safe_minmax.h"
kwiberg07038562017-06-12 11:40:47 -070020
ekm35b72fb2015-07-10 14:11:52 -070021namespace webrtc {
ekm030249d2015-06-15 13:02:24 -070022
ekm35b72fb2015-07-10 14:11:52 -070023namespace intelligibility {
24
Alejandro Luebs32348192016-02-17 20:04:19 -080025namespace {
26
aluebs4896aaa2016-04-28 16:08:59 -070027const float kMinFactor = 0.01f;
aluebs7bd5f252016-06-21 11:30:25 -070028const float kMaxFactor = 100.f;
aluebs4896aaa2016-04-28 16:08:59 -070029
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080030// Return |current| changed towards |target|, with the relative change being at
31// most |limit|.
ekm35b72fb2015-07-10 14:11:52 -070032float UpdateFactor(float target, float current, float limit) {
kwiberg07038562017-06-12 11:40:47 -070033 const float gain = target / (current + std::numeric_limits<float>::epsilon());
34 const float clamped_gain = rtc::SafeClamp(gain, 1 - limit, 1 + limit);
35 return rtc::SafeClamp(current * clamped_gain, kMinFactor, kMaxFactor);
ekm030249d2015-06-15 13:02:24 -070036}
37
Alejandro Luebs32348192016-02-17 20:04:19 -080038} // namespace
ekm030249d2015-06-15 13:02:24 -070039
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080040template<typename T>
41PowerEstimator<T>::PowerEstimator(size_t num_freqs, float decay)
42 : power_(num_freqs, 0.f), decay_(decay) {}
ekm030249d2015-06-15 13:02:24 -070043
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080044template<typename T>
45void PowerEstimator<T>::Step(const T* data) {
46 for (size_t i = 0; i < power_.size(); ++i) {
47 power_[i] = decay_ * power_[i] +
48 (1.f - decay_) * std::abs(data[i]) * std::abs(data[i]);
ekm030249d2015-06-15 13:02:24 -070049 }
50}
51
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080052template class PowerEstimator<float>;
53template class PowerEstimator<std::complex<float>>;
ekm030249d2015-06-15 13:02:24 -070054
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080055GainApplier::GainApplier(size_t freqs, float relative_change_limit)
ekmeyerson60d9b332015-08-14 10:35:55 -070056 : num_freqs_(freqs),
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080057 relative_change_limit_(relative_change_limit),
aluebs0a007592016-02-26 17:17:38 -080058 target_(freqs, 1.f),
59 current_(freqs, 1.f) {}
ekm030249d2015-06-15 13:02:24 -070060
Alejandro Luebs37062ed2016-09-06 11:25:40 -070061GainApplier::~GainApplier() {}
62
Alejandro Luebs32348192016-02-17 20:04:19 -080063void GainApplier::Apply(const std::complex<float>* in_block,
64 std::complex<float>* out_block) {
Peter Kastingdce40cf2015-08-24 14:52:23 -070065 for (size_t i = 0; i < num_freqs_; ++i) {
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080066 current_[i] = UpdateFactor(target_[i], current_[i], relative_change_limit_);
67 out_block[i] = sqrtf(fabsf(current_[i])) * in_block[i];
ekm030249d2015-06-15 13:02:24 -070068 }
69}
70
Alejandro Luebsef009252016-09-20 14:51:56 -070071DelayBuffer::DelayBuffer(size_t delay, size_t num_channels)
72 : buffer_(num_channels, std::vector<float>(delay, 0.f)), read_index_(0u) {}
73
74DelayBuffer::~DelayBuffer() {}
75
76void DelayBuffer::Delay(float* const* data, size_t length) {
77 size_t sample_index = read_index_;
78 for (size_t i = 0u; i < buffer_.size(); ++i) {
79 sample_index = read_index_;
80 for (size_t j = 0u; j < length; ++j) {
81 float swap = data[i][j];
82 data[i][j] = buffer_[i][sample_index];
83 buffer_[i][sample_index] = swap;
84 if (++sample_index == buffer_.size()) {
85 sample_index = 0u;
86 }
87 }
88 }
89 read_index_ = sample_index;
90}
91
ekm030249d2015-06-15 13:02:24 -070092} // namespace intelligibility
93
94} // namespace webrtc