OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 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/level_controller/gain_applier.h" | |
12 | |
13 #include <algorithm> | |
14 | |
15 #include "webrtc/base/array_view.h" | |
16 #include "webrtc/base/checks.h" | |
17 | |
18 #include "webrtc/modules/audio_processing/audio_buffer.h" | |
19 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | |
20 | |
21 namespace webrtc { | |
22 namespace { | |
23 | |
24 const float kMaxSampleValue = 32767.f; | |
25 const float kMinSampleValue = -32767.f; | |
26 | |
27 int CountSaturations(rtc::ArrayView<const float> in) { | |
hlundin-webrtc
2016/06/27 11:21:14
You can implement this as a one-liner:
return std
peah-webrtc
2016/06/27 22:51:47
Wow! Impressive! Thanks!!!
Done.
| |
28 int num_saturations = 0; | |
29 for (auto v : in) { | |
30 if (v >= kMaxSampleValue || v <= kMinSampleValue) { | |
31 ++num_saturations; | |
32 } | |
33 } | |
34 return num_saturations; | |
35 } | |
36 | |
37 int CountSaturations(const AudioBuffer& audio) { | |
38 int num_saturations = 0; | |
39 for (size_t k = 0; k < audio.num_channels(); ++k) { | |
40 num_saturations += CountSaturations(rtc::ArrayView<const float>( | |
41 audio.channels_const_f()[k], audio.num_frames())); | |
42 } | |
43 return num_saturations; | |
44 } | |
45 | |
46 void LimitToAllowedRange(rtc::ArrayView<float> x) { | |
47 for (auto& v : x) { | |
48 v = std::max(kMinSampleValue, v); | |
49 v = std::min(kMaxSampleValue, v); | |
50 } | |
51 } | |
52 | |
53 void LimitToAllowedRange(AudioBuffer* audio) { | |
54 for (size_t k = 0; k < audio->num_channels(); ++k) { | |
55 LimitToAllowedRange( | |
56 rtc::ArrayView<float>(audio->channels_f()[k], audio->num_frames())); | |
57 } | |
58 } | |
59 | |
60 float ApplyIncreasingGain(float new_gain, | |
61 float old_gain, | |
62 float step_size, | |
63 rtc::ArrayView<float> x) { | |
64 RTC_DCHECK_LT(0.f, step_size); | |
65 float gain = old_gain; | |
66 for (auto& x_v : x) { | |
hlundin-webrtc
2016/06/27 11:21:14
Stick to the same definition as above, and use v i
peah-webrtc
2016/06/27 22:51:47
Done.
| |
67 gain = std::min(new_gain, gain + step_size); | |
68 x_v *= gain; | |
69 } | |
70 return gain; | |
71 } | |
72 | |
73 float ApplyDecreasingGain(float new_gain, | |
74 float old_gain, | |
75 float step_size, | |
76 rtc::ArrayView<float> x) { | |
77 RTC_DCHECK_LT(0.f, step_size); | |
78 float gain = old_gain; | |
79 for (auto& x_v : x) { | |
80 gain = std::max(new_gain, gain - step_size); | |
81 x_v *= gain; | |
82 } | |
83 return gain; | |
84 } | |
85 | |
86 void ApplyConstantGain(float gain, rtc::ArrayView<float> x) { | |
87 for (auto& x_v : x) { | |
88 x_v *= gain; | |
89 } | |
90 } | |
91 | |
92 float ApplyGain(float new_gain, | |
93 float old_gain, | |
94 float step_size, | |
95 rtc::ArrayView<float> x) { | |
96 float last_applied_gain = new_gain; | |
hlundin-webrtc
2016/06/27 11:21:14
Not needed, with my suggestions below.
peah-webrtc
2016/06/27 22:51:47
Done.
| |
97 if (new_gain == old_gain) { | |
98 ApplyConstantGain(new_gain, x); | |
hlundin-webrtc
2016/06/27 11:21:14
ApplyConstantGain(new_gain, x);
return new_gain;
peah-webrtc
2016/06/27 22:51:47
Nice!!!
Done.
| |
99 } else if (new_gain > old_gain) { | |
100 last_applied_gain = ApplyIncreasingGain(new_gain, old_gain, step_size, x); | |
hlundin-webrtc
2016/06/27 11:21:14
return ApplyIncreasingGain(...
peah-webrtc
2016/06/27 22:51:47
Done.
| |
101 } else { | |
102 last_applied_gain = ApplyDecreasingGain(new_gain, old_gain, step_size, x); | |
hlundin-webrtc
2016/06/27 11:21:14
return ApplyDecreasingGain(...
peah-webrtc
2016/06/27 22:51:47
Done.
| |
103 } | |
104 return last_applied_gain; | |
105 } | |
106 | |
107 } // namespace | |
108 | |
109 GainApplier::GainApplier(ApmDataDumper* data_dumper) | |
110 : data_dumper_(data_dumper) {} | |
111 | |
112 void GainApplier::Initialize(int sample_rate_hz) { | |
113 RTC_DCHECK_LE(0.f, sample_rate_hz); | |
hlundin-webrtc
2016/06/27 11:21:14
Is 0 a valid rate?
peah-webrtc
2016/06/27 22:51:47
Good point!
Done.
| |
114 old_gain_ = 1.f; | |
115 gain_change_step_size_ = 0.001f * (48000.f / sample_rate_hz); | |
116 } | |
117 | |
118 int GainApplier::Process(float new_gain, AudioBuffer* audio) { | |
119 int num_saturations = 0; | |
hlundin-webrtc
2016/06/27 11:21:14
You may want to add RTC_DCHECK_NE(gain_change_step
peah-webrtc
2016/06/27 22:51:47
Good point!
Done.
| |
120 if (new_gain != 1.f) { | |
121 float last_applied_gain = 1.f; | |
122 for (size_t k = 0; k < audio->num_channels(); ++k) { | |
123 // TODO(peah): Consider using a faster update rate downwards than upwards. | |
124 last_applied_gain = ApplyGain( | |
125 new_gain, old_gain_, gain_change_step_size_, | |
126 rtc::ArrayView<float>(audio->channels_f()[k], audio->num_frames())); | |
127 } | |
128 // TODO(peah): Consider the need for faster gain reduction in case of | |
129 // excessive saturation. | |
130 num_saturations = CountSaturations(*audio); | |
131 LimitToAllowedRange(audio); | |
132 old_gain_ = last_applied_gain; | |
133 } | |
134 | |
135 data_dumper_->DumpRaw("lc_last_applied_gain", 1, &old_gain_); | |
136 | |
137 return num_saturations; | |
138 } | |
139 | |
140 } // namespace webrtc | |
OLD | NEW |