blob: 550f293a7cdccecf407c13798da803ea287789bd [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
11#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
12#define WEBRTC_MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
13
14#include <complex>
15
16#include "webrtc/system_wrappers/interface/scoped_ptr.h"
17
18namespace webrtc {
19
20namespace intelligibility {
21
22// Internal helper for computing the variances of a stream of arrays.
23// The result is an array of variances per position: the i-th variance
24// is the variance of the stream of data on the i-th positions in the
25// input arrays.
26// There are four methods of computation:
27// * kStepInfinite computes variances from the beginning onwards
28// * kStepDecaying uses a recursive exponential decay formula with a
29// settable forgetting factor
30// * kStepWindowed computes variances within a moving window
31// * kStepBlocked is similar to kStepWindowed, but history is kept
32// as a rolling window of blocks: multiple input elements are used for
33// one block and the history then consists of the variances of these blocks
34// with the same effect as kStepWindowed, but less storage, so the window
35// can be longer
36class VarianceArray {
37 public:
38 enum StepType {
39 kStepInfinite = 0,
40 kStepDecaying,
41 kStepWindowed,
42 kStepBlocked
43 };
44
45 // Construct an instance for the given input array length (|freqs|) and
46 // computation algorithm (|type|), with the appropriate parameters.
47 // |window_size| is the number of samples for kStepWindowed and
48 // the number of blocks for kStepBlocked. |decay| is the forgetting factor
49 // for kStepDecaying.
50 VarianceArray(int freqs, StepType type, int window_size, float decay);
51
52 // Add a new data point to the series and compute the new variances.
53 // TODO(bercic) |skip_fudge| is a flag for kStepWindowed and kStepDecaying,
54 // whether they should skip adding some small dummy values to the input
55 // to prevent problems with all-zero inputs. Can probably be removed.
56 void Step(const std::complex<float>* data, bool skip_fudge = false) {
57 (this->*step_func_)(data, skip_fudge);
58 }
59 // Reset variances to zero and forget all history.
60 void Clear();
61 // Scale the input data by |scale|. Effectively multiply variances
62 // by |scale^2|.
63 void ApplyScale(float scale);
64
65 // The current set of variances.
66 const float* variance() const {
67 return variance_.get();
68 }
69
70 // The mean value of the current set of variances.
71 float array_mean() const {
72 return array_mean_;
73 }
74
75 private:
76 void InfiniteStep(const std::complex<float>* data, bool dummy);
77 void DecayStep(const std::complex<float>* data, bool dummy);
78 void WindowedStep(const std::complex<float>* data, bool dummy);
79 void BlockedStep(const std::complex<float>* data, bool dummy);
80
81 // The current average X and X^2.
82 scoped_ptr<std::complex<float>[]> running_mean_;
83 scoped_ptr<std::complex<float>[]> running_mean_sq_;
84
85 // Average X and X^2 for the current block in kStepBlocked.
86 scoped_ptr<std::complex<float>[]> sub_running_mean_;
87 scoped_ptr<std::complex<float>[]> sub_running_mean_sq_;
88
89 // Sample history for the rolling window in kStepWindowed and block-wise
90 // histories for kStepBlocked.
91 scoped_ptr<scoped_ptr<std::complex<float>[]>[]> history_;
92 scoped_ptr<scoped_ptr<std::complex<float>[]>[]> subhistory_;
93 scoped_ptr<scoped_ptr<std::complex<float>[]>[]> subhistory_sq_;
94
95 // The current set of variances and sums for Welford's algorithm.
96 scoped_ptr<float[]> variance_;
97 scoped_ptr<float[]> conj_sum_;
98
99 const int freqs_;
100 const int window_size_;
101 const float decay_;
102 int history_cursor_;
103 int count_;
104 float array_mean_;
105 void (VarianceArray::*step_func_)(const std::complex<float>*, bool);
106};
107
108// Helper class for smoothing gain changes. On each applicatiion step, the
109// currently used gains are changed towards a set of settable target gains,
110// constrained by a limit on the magnitude of the changes.
111class GainApplier {
112 public:
113 GainApplier(int freqs, float change_limit);
114
115 // Copy |in_block| to |out_block|, multiplied by the current set of gains,
116 // and step the current set of gains towards the target set.
117 void Apply(const std::complex<float>* in_block,
118 std::complex<float>* out_block);
119
120 // Return the current target gain set. Modify this array to set the targets.
121 float* target() const {
122 return target_.get();
123 }
124
125 private:
126 const int freqs_;
127 const float change_limit_;
128 scoped_ptr<float[]> target_;
129 scoped_ptr<float[]> current_;
130};
131
132} // namespace intelligibility
133
134} // namespace webrtc
135
136#endif // WEBRTC_MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
137