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) { | |
28 return std::count_if(in.begin(), in.end(), [](float v) { | |
aleloi
2016/06/28 09:35:52
Probably the compiler is smart and this is not aff
peah-webrtc
2016/06/28 22:19:37
I'm not an expert on this, but I think it should b
hlundin-webrtc
2016/06/29 08:56:28
I think that in this case it makes no difference.
peah-webrtc
2016/06/29 09:13:53
Acknowledged.
| |
29 return v >= kMaxSampleValue || v <= kMinSampleValue; | |
30 }); | |
31 } | |
32 | |
33 int CountSaturations(const AudioBuffer& audio) { | |
34 int num_saturations = 0; | |
35 for (size_t k = 0; k < audio.num_channels(); ++k) { | |
36 num_saturations += CountSaturations(rtc::ArrayView<const float>( | |
37 audio.channels_const_f()[k], audio.num_frames())); | |
38 } | |
39 return num_saturations; | |
40 } | |
41 | |
42 void LimitToAllowedRange(rtc::ArrayView<float> x) { | |
43 for (auto& v : x) { | |
44 v = std::max(kMinSampleValue, v); | |
45 v = std::min(kMaxSampleValue, v); | |
46 } | |
47 } | |
48 | |
49 void LimitToAllowedRange(AudioBuffer* audio) { | |
50 for (size_t k = 0; k < audio->num_channels(); ++k) { | |
51 LimitToAllowedRange( | |
52 rtc::ArrayView<float>(audio->channels_f()[k], audio->num_frames())); | |
53 } | |
54 } | |
55 | |
56 float ApplyIncreasingGain(float new_gain, | |
57 float old_gain, | |
58 float step_size, | |
59 rtc::ArrayView<float> x) { | |
60 RTC_DCHECK_LT(0.f, step_size); | |
61 float gain = old_gain; | |
62 for (auto& v : x) { | |
63 gain = std::min(new_gain, gain + step_size); | |
aleloi
2016/06/28 09:35:52
Maybe move the gain calculation outside of the loo
peah-webrtc
2016/06/28 22:19:37
I'm not fully sure of what you mean, but the inten
aleloi
2016/06/29 14:11:18
Acknowledged.
| |
64 v *= gain; | |
65 } | |
66 return gain; | |
67 } | |
68 | |
69 float ApplyDecreasingGain(float new_gain, | |
70 float old_gain, | |
71 float step_size, | |
72 rtc::ArrayView<float> x) { | |
73 RTC_DCHECK_LT(0.f, step_size); | |
74 float gain = old_gain; | |
75 for (auto& v : x) { | |
76 gain = std::max(new_gain, gain - step_size); | |
77 v *= gain; | |
78 } | |
79 return gain; | |
80 } | |
81 | |
82 float ApplyConstantGain(float gain, rtc::ArrayView<float> x) { | |
83 for (auto& v : x) { | |
84 v *= gain; | |
85 } | |
86 | |
87 return gain; | |
88 } | |
89 | |
90 float ApplyGain(float new_gain, | |
91 float old_gain, | |
92 float step_size, | |
93 rtc::ArrayView<float> x) { | |
94 if (new_gain == old_gain) { | |
95 return ApplyConstantGain(new_gain, x); | |
96 } else if (new_gain > old_gain) { | |
97 return ApplyIncreasingGain(new_gain, old_gain, step_size, x); | |
98 } else { | |
99 return ApplyDecreasingGain(new_gain, old_gain, step_size, x); | |
100 } | |
101 } | |
102 | |
103 } // namespace | |
104 | |
105 GainApplier::GainApplier(ApmDataDumper* data_dumper) | |
106 : data_dumper_(data_dumper) {} | |
107 | |
108 void GainApplier::Initialize(int sample_rate_hz) { | |
109 RTC_DCHECK(sample_rate_hz == AudioProcessing::kSampleRate8kHz || | |
110 sample_rate_hz == AudioProcessing::kSampleRate16kHz || | |
111 sample_rate_hz == AudioProcessing::kSampleRate32kHz || | |
112 sample_rate_hz == AudioProcessing::kSampleRate48kHz); | |
113 old_gain_ = 1.f; | |
114 gain_change_step_size_ = 0.001f * (48000.f / sample_rate_hz); | |
aleloi
2016/06/28 09:35:52
Please define a constant for 0.001f.
peah-webrtc
2016/06/28 22:19:37
That definitely makes sense.
Done.
| |
115 } | |
aleloi
2016/06/28 09:35:52
Do we need both a constructor and an Initialize()
peah-webrtc
2016/06/28 22:19:37
I definitely agree that it would be nicer to do th
aleloi
2016/06/29 14:11:18
Acknowledged.
| |
116 | |
117 int GainApplier::Process(float new_gain, AudioBuffer* audio) { | |
118 RTC_CHECK_NE(0.f, gain_change_step_size_); | |
119 int num_saturations = 0; | |
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 |