OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/gain_control_impl.h" | 11 #include "webrtc/modules/audio_processing/gain_control_impl.h" |
12 | 12 |
13 #include <assert.h> | 13 #include <assert.h> |
the sun
2016/03/09 09:42:11
Remove assert() while you're at it
peah-webrtc
2016/03/09 12:23:39
Done.
| |
14 | 14 |
15 #include "webrtc/base/constructormagic.h" | |
the sun
2016/03/09 09:42:11
Won't be needed.
peah-webrtc
2016/03/09 12:23:39
Done.
| |
15 #include "webrtc/modules/audio_processing/audio_buffer.h" | 16 #include "webrtc/modules/audio_processing/audio_buffer.h" |
16 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" | 17 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" |
17 | 18 |
18 namespace webrtc { | 19 namespace webrtc { |
19 | 20 |
20 typedef void Handle; | 21 typedef void Handle; |
21 | 22 |
22 namespace { | 23 namespace { |
23 int16_t MapSetting(GainControl::Mode mode) { | 24 int16_t MapSetting(GainControl::Mode mode) { |
24 switch (mode) { | 25 switch (mode) { |
(...skipping 10 matching lines...) Expand all Loading... | |
35 | 36 |
36 // Maximum length that a frame of samples can have. | 37 // Maximum length that a frame of samples can have. |
37 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; | 38 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; |
38 // Maximum number of frames to buffer in the render queue. | 39 // Maximum number of frames to buffer in the render queue. |
39 // TODO(peah): Decrease this once we properly handle hugely unbalanced | 40 // TODO(peah): Decrease this once we properly handle hugely unbalanced |
40 // reverse and forward call numbers. | 41 // reverse and forward call numbers. |
41 static const size_t kMaxNumFramesToBuffer = 100; | 42 static const size_t kMaxNumFramesToBuffer = 100; |
42 | 43 |
43 } // namespace | 44 } // namespace |
44 | 45 |
46 class GainControlImpl::GainController { | |
47 public: | |
48 explicit GainController() { | |
49 state_ = WebRtcAgc_Create(); | |
50 RTC_CHECK(state_); | |
51 } | |
52 | |
53 ~GainController() { | |
54 RTC_DCHECK(state_); | |
the sun
2016/03/09 09:42:10
remove this DCHECK or add one in each of the other
peah-webrtc
2016/03/09 12:23:39
Done.
| |
55 WebRtcAgc_Free(state_); | |
56 } | |
57 | |
58 Handle* state() { return state_; } | |
59 void Initialize(int minimum_capture_level, | |
60 int maximum_capture_level, | |
61 Mode mode, | |
62 int sample_rate_hz) { | |
63 const int error = | |
64 WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level, | |
65 MapSetting(mode), sample_rate_hz); | |
66 RTC_DCHECK_EQ(0, error); | |
67 } | |
68 | |
69 private: | |
70 Handle* state_; | |
71 RTC_DISALLOW_COPY_AND_ASSIGN(GainController); | |
72 }; | |
73 | |
45 GainControlImpl::GainControlImpl(const AudioProcessing* apm, | 74 GainControlImpl::GainControlImpl(const AudioProcessing* apm, |
46 rtc::CriticalSection* crit_render, | 75 rtc::CriticalSection* crit_render, |
47 rtc::CriticalSection* crit_capture) | 76 rtc::CriticalSection* crit_capture) |
48 : ProcessingComponent(), | 77 : apm_(apm), |
49 apm_(apm), | |
50 crit_render_(crit_render), | 78 crit_render_(crit_render), |
51 crit_capture_(crit_capture), | 79 crit_capture_(crit_capture), |
52 mode_(kAdaptiveAnalog), | 80 mode_(kAdaptiveAnalog), |
53 minimum_capture_level_(0), | 81 minimum_capture_level_(0), |
54 maximum_capture_level_(255), | 82 maximum_capture_level_(255), |
55 limiter_enabled_(true), | 83 limiter_enabled_(true), |
56 target_level_dbfs_(3), | 84 target_level_dbfs_(3), |
57 compression_gain_db_(9), | 85 compression_gain_db_(9), |
58 analog_capture_level_(0), | 86 analog_capture_level_(0), |
59 was_analog_level_set_(false), | 87 was_analog_level_set_(false), |
60 stream_is_saturated_(false), | 88 stream_is_saturated_(false), |
61 render_queue_element_max_size_(0) { | 89 render_queue_element_max_size_(0) { |
62 RTC_DCHECK(apm); | 90 RTC_DCHECK(apm); |
63 RTC_DCHECK(crit_render); | 91 RTC_DCHECK(crit_render); |
64 RTC_DCHECK(crit_capture); | 92 RTC_DCHECK(crit_capture); |
65 } | 93 } |
66 | 94 |
67 GainControlImpl::~GainControlImpl() {} | 95 GainControlImpl::~GainControlImpl() {} |
68 | 96 |
69 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { | 97 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
70 rtc::CritScope cs(crit_render_); | 98 rtc::CritScope cs(crit_render_); |
71 if (!is_component_enabled()) { | 99 if (!enabled_) { |
72 return AudioProcessing::kNoError; | 100 return AudioProcessing::kNoError; |
73 } | 101 } |
74 | 102 |
75 assert(audio->num_frames_per_band() <= 160); | 103 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
76 | 104 |
77 render_queue_buffer_.resize(0); | 105 render_queue_buffer_.resize(0); |
78 for (size_t i = 0; i < num_handles(); i++) { | 106 for (size_t i = 0; i < num_handles_required(); i++) { |
79 Handle* my_handle = static_cast<Handle*>(handle(i)); | 107 Handle* my_handle = gain_controllers_[i]->state(); |
80 int err = | 108 int err = |
81 WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band()); | 109 WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band()); |
82 | 110 |
83 if (err != AudioProcessing::kNoError) | 111 if (err != AudioProcessing::kNoError) |
84 return GetHandleError(my_handle); | 112 return AudioProcessing::kUnspecifiedError; |
85 | 113 |
86 // Buffer the samples in the render queue. | 114 // Buffer the samples in the render queue. |
87 render_queue_buffer_.insert( | 115 render_queue_buffer_.insert( |
88 render_queue_buffer_.end(), audio->mixed_low_pass_data(), | 116 render_queue_buffer_.end(), audio->mixed_low_pass_data(), |
89 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); | 117 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); |
90 } | 118 } |
91 | 119 |
92 // Insert the samples into the queue. | 120 // Insert the samples into the queue. |
93 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { | 121 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { |
94 // The data queue is full and needs to be emptied. | 122 // The data queue is full and needs to be emptied. |
95 ReadQueuedRenderData(); | 123 ReadQueuedRenderData(); |
96 | 124 |
97 // Retry the insert (should always work). | 125 // Retry the insert (should always work). |
98 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | 126 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
99 } | 127 } |
100 | 128 |
101 return AudioProcessing::kNoError; | 129 return AudioProcessing::kNoError; |
102 } | 130 } |
103 | 131 |
104 // Read chunks of data that were received and queued on the render side from | 132 // Read chunks of data that were received and queued on the render side from |
105 // a queue. All the data chunks are buffered into the farend signal of the AGC. | 133 // a queue. All the data chunks are buffered into the farend signal of the AGC. |
106 void GainControlImpl::ReadQueuedRenderData() { | 134 void GainControlImpl::ReadQueuedRenderData() { |
107 rtc::CritScope cs(crit_capture_); | 135 rtc::CritScope cs(crit_capture_); |
108 | 136 |
109 if (!is_component_enabled()) { | 137 if (!enabled_) { |
110 return; | 138 return; |
111 } | 139 } |
112 | 140 |
113 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 141 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
114 size_t buffer_index = 0; | 142 size_t buffer_index = 0; |
115 const size_t num_frames_per_band = | 143 const size_t num_frames_per_band = |
116 capture_queue_buffer_.size() / num_handles(); | 144 capture_queue_buffer_.size() / num_handles_required(); |
117 for (size_t i = 0; i < num_handles(); i++) { | 145 for (size_t i = 0; i < num_handles_required(); i++) { |
the sun
2016/03/09 09:42:10
for (auto& gain_controller : gain_controllers_) {
peah-webrtc
2016/03/09 12:23:39
This does not work, as the number of gain controll
the sun
2016/03/09 13:01:53
That's ok, but it's quite a simple fix to resize t
peah-webrtc
2016/03/09 21:06:44
Simple it indeed is but this is as it was before t
| |
118 Handle* my_handle = static_cast<Handle*>(handle(i)); | 146 Handle* my_handle = gain_controllers_[i]->state(); |
119 WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index], | 147 WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index], |
120 num_frames_per_band); | 148 num_frames_per_band); |
121 | 149 |
122 buffer_index += num_frames_per_band; | 150 buffer_index += num_frames_per_band; |
123 } | 151 } |
124 } | 152 } |
125 } | 153 } |
126 | 154 |
127 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { | 155 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
128 rtc::CritScope cs(crit_capture_); | 156 rtc::CritScope cs(crit_capture_); |
129 | 157 |
130 if (!is_component_enabled()) { | 158 if (!enabled_) { |
131 return AudioProcessing::kNoError; | 159 return AudioProcessing::kNoError; |
132 } | 160 } |
133 | 161 |
134 assert(audio->num_frames_per_band() <= 160); | 162 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
135 assert(audio->num_channels() == num_handles()); | 163 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required()); |
the sun
2016/03/09 09:42:11
num_handles_required() -> gain_controllers_.size()
peah-webrtc
2016/03/09 12:23:39
Done.
| |
136 | 164 |
137 int err = AudioProcessing::kNoError; | 165 int err = AudioProcessing::kNoError; |
138 | 166 |
139 if (mode_ == kAdaptiveAnalog) { | 167 if (mode_ == kAdaptiveAnalog) { |
140 capture_levels_.assign(num_handles(), analog_capture_level_); | 168 capture_levels_.assign(num_handles_required(), analog_capture_level_); |
141 for (size_t i = 0; i < num_handles(); i++) { | 169 for (size_t i = 0; i < num_handles_required(); i++) { |
142 Handle* my_handle = static_cast<Handle*>(handle(i)); | 170 Handle* my_handle = gain_controllers_[i]->state(); |
143 err = WebRtcAgc_AddMic( | 171 err = WebRtcAgc_AddMic( |
144 my_handle, | 172 my_handle, |
145 audio->split_bands(i), | 173 audio->split_bands(i), |
the sun
2016/03/09 09:42:10
Is there one split band per channel? Is the DCHECK
peah-webrtc
2016/03/09 12:23:39
In analog_agc.c, the in each channel bands are pro
| |
146 audio->num_bands(), | 174 audio->num_bands(), |
147 audio->num_frames_per_band()); | 175 audio->num_frames_per_band()); |
148 | 176 |
149 if (err != AudioProcessing::kNoError) { | 177 if (err != AudioProcessing::kNoError) { |
150 return GetHandleError(my_handle); | 178 return AudioProcessing::kUnspecifiedError; |
151 } | 179 } |
152 } | 180 } |
153 } else if (mode_ == kAdaptiveDigital) { | 181 } else if (mode_ == kAdaptiveDigital) { |
154 | 182 for (size_t i = 0; i < num_handles_required(); i++) { |
155 for (size_t i = 0; i < num_handles(); i++) { | 183 Handle* my_handle = gain_controllers_[i]->state(); |
156 Handle* my_handle = static_cast<Handle*>(handle(i)); | |
157 int32_t capture_level_out = 0; | 184 int32_t capture_level_out = 0; |
158 | 185 |
159 err = WebRtcAgc_VirtualMic( | 186 err = WebRtcAgc_VirtualMic( |
160 my_handle, | 187 my_handle, |
161 audio->split_bands(i), | 188 audio->split_bands(i), |
162 audio->num_bands(), | 189 audio->num_bands(), |
163 audio->num_frames_per_band(), | 190 audio->num_frames_per_band(), |
164 analog_capture_level_, | 191 analog_capture_level_, |
165 &capture_level_out); | 192 &capture_level_out); |
166 | 193 |
167 capture_levels_[i] = capture_level_out; | 194 capture_levels_[i] = capture_level_out; |
168 | 195 |
169 if (err != AudioProcessing::kNoError) { | 196 if (err != AudioProcessing::kNoError) { |
170 return GetHandleError(my_handle); | 197 return AudioProcessing::kUnspecifiedError; |
171 } | 198 } |
172 | 199 |
173 } | 200 } |
174 } | 201 } |
175 | 202 |
176 return AudioProcessing::kNoError; | 203 return AudioProcessing::kNoError; |
177 } | 204 } |
178 | 205 |
179 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 206 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
180 rtc::CritScope cs(crit_capture_); | 207 rtc::CritScope cs(crit_capture_); |
181 | 208 |
182 if (!is_component_enabled()) { | 209 if (!enabled_) { |
183 return AudioProcessing::kNoError; | 210 return AudioProcessing::kNoError; |
184 } | 211 } |
185 | 212 |
186 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { | 213 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { |
187 return AudioProcessing::kStreamParameterNotSetError; | 214 return AudioProcessing::kStreamParameterNotSetError; |
188 } | 215 } |
189 | 216 |
190 assert(audio->num_frames_per_band() <= 160); | 217 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
191 assert(audio->num_channels() == num_handles()); | 218 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required()); |
192 | 219 |
193 stream_is_saturated_ = false; | 220 stream_is_saturated_ = false; |
194 for (size_t i = 0; i < num_handles(); i++) { | 221 for (size_t i = 0; i < num_handles_required(); i++) { |
195 Handle* my_handle = static_cast<Handle*>(handle(i)); | 222 Handle* my_handle = gain_controllers_[i]->state(); |
196 int32_t capture_level_out = 0; | 223 int32_t capture_level_out = 0; |
197 uint8_t saturation_warning = 0; | 224 uint8_t saturation_warning = 0; |
198 | 225 |
199 // The call to stream_has_echo() is ok from a deadlock perspective | 226 // The call to stream_has_echo() is ok from a deadlock perspective |
200 // as the capture lock is allready held. | 227 // as the capture lock is allready held. |
201 int err = WebRtcAgc_Process( | 228 int err = WebRtcAgc_Process( |
202 my_handle, | 229 my_handle, |
203 audio->split_bands_const(i), | 230 audio->split_bands_const(i), |
204 audio->num_bands(), | 231 audio->num_bands(), |
205 audio->num_frames_per_band(), | 232 audio->num_frames_per_band(), |
206 audio->split_bands(i), | 233 audio->split_bands(i), |
207 capture_levels_[i], | 234 capture_levels_[i], |
208 &capture_level_out, | 235 &capture_level_out, |
209 apm_->echo_cancellation()->stream_has_echo(), | 236 apm_->echo_cancellation()->stream_has_echo(), |
210 &saturation_warning); | 237 &saturation_warning); |
211 | 238 |
212 if (err != AudioProcessing::kNoError) { | 239 if (err != AudioProcessing::kNoError) { |
213 return GetHandleError(my_handle); | 240 return AudioProcessing::kUnspecifiedError; |
214 } | 241 } |
215 | 242 |
216 capture_levels_[i] = capture_level_out; | 243 capture_levels_[i] = capture_level_out; |
217 if (saturation_warning == 1) { | 244 if (saturation_warning == 1) { |
218 stream_is_saturated_ = true; | 245 stream_is_saturated_ = true; |
219 } | 246 } |
220 } | 247 } |
221 | 248 |
222 if (mode_ == kAdaptiveAnalog) { | 249 if (mode_ == kAdaptiveAnalog) { |
223 // Take the analog level to be the average across the handles. | 250 // Take the analog level to be the average across the handles. |
224 analog_capture_level_ = 0; | 251 analog_capture_level_ = 0; |
225 for (size_t i = 0; i < num_handles(); i++) { | 252 for (size_t i = 0; i < num_handles_required(); i++) { |
226 analog_capture_level_ += capture_levels_[i]; | 253 analog_capture_level_ += capture_levels_[i]; |
the sun
2016/03/09 09:42:10
Make capture_level_ a member of GainController to
peah-webrtc
2016/03/09 12:23:39
Awesome idea!!!
Done.
| |
227 } | 254 } |
228 | 255 |
229 analog_capture_level_ /= num_handles(); | 256 analog_capture_level_ /= num_handles_required(); |
230 } | 257 } |
231 | 258 |
232 was_analog_level_set_ = false; | 259 was_analog_level_set_ = false; |
233 return AudioProcessing::kNoError; | 260 return AudioProcessing::kNoError; |
234 } | 261 } |
235 | 262 |
236 // TODO(ajm): ensure this is called under kAdaptiveAnalog. | 263 // TODO(ajm): ensure this is called under kAdaptiveAnalog. |
237 int GainControlImpl::set_stream_analog_level(int level) { | 264 int GainControlImpl::set_stream_analog_level(int level) { |
238 rtc::CritScope cs(crit_capture_); | 265 rtc::CritScope cs(crit_capture_); |
239 | 266 |
(...skipping 10 matching lines...) Expand all Loading... | |
250 rtc::CritScope cs(crit_capture_); | 277 rtc::CritScope cs(crit_capture_); |
251 // TODO(ajm): enable this assertion? | 278 // TODO(ajm): enable this assertion? |
252 //assert(mode_ == kAdaptiveAnalog); | 279 //assert(mode_ == kAdaptiveAnalog); |
253 | 280 |
254 return analog_capture_level_; | 281 return analog_capture_level_; |
255 } | 282 } |
256 | 283 |
257 int GainControlImpl::Enable(bool enable) { | 284 int GainControlImpl::Enable(bool enable) { |
258 rtc::CritScope cs_render(crit_render_); | 285 rtc::CritScope cs_render(crit_render_); |
259 rtc::CritScope cs_capture(crit_capture_); | 286 rtc::CritScope cs_capture(crit_capture_); |
260 return EnableComponent(enable); | 287 if (enable && !enabled_) { |
288 enabled_ = enable; // Must be set before Initialize() is called. | |
289 Initialize(); | |
290 } else { | |
291 enabled_ = enable; | |
292 } | |
293 return AudioProcessing::kNoError; | |
261 } | 294 } |
262 | 295 |
263 bool GainControlImpl::is_enabled() const { | 296 bool GainControlImpl::is_enabled() const { |
264 rtc::CritScope cs(crit_capture_); | 297 rtc::CritScope cs(crit_capture_); |
265 return is_component_enabled(); | 298 return enabled_; |
266 } | 299 } |
267 | 300 |
268 int GainControlImpl::set_mode(Mode mode) { | 301 int GainControlImpl::set_mode(Mode mode) { |
269 rtc::CritScope cs_render(crit_render_); | 302 rtc::CritScope cs_render(crit_render_); |
270 rtc::CritScope cs_capture(crit_capture_); | 303 rtc::CritScope cs_capture(crit_capture_); |
271 if (MapSetting(mode) == -1) { | 304 if (MapSetting(mode) == -1) { |
272 return AudioProcessing::kBadParameterError; | 305 return AudioProcessing::kBadParameterError; |
273 } | 306 } |
274 | 307 |
275 mode_ = mode; | 308 mode_ = mode; |
276 return Initialize(); | 309 Initialize(); |
310 return AudioProcessing::kNoError; | |
277 } | 311 } |
278 | 312 |
279 GainControl::Mode GainControlImpl::mode() const { | 313 GainControl::Mode GainControlImpl::mode() const { |
280 rtc::CritScope cs(crit_capture_); | 314 rtc::CritScope cs(crit_capture_); |
281 return mode_; | 315 return mode_; |
282 } | 316 } |
283 | 317 |
284 int GainControlImpl::set_analog_level_limits(int minimum, | 318 int GainControlImpl::set_analog_level_limits(int minimum, |
285 int maximum) { | 319 int maximum) { |
286 rtc::CritScope cs(crit_capture_); | 320 rtc::CritScope cs(crit_capture_); |
287 if (minimum < 0) { | 321 if (minimum < 0) { |
288 return AudioProcessing::kBadParameterError; | 322 return AudioProcessing::kBadParameterError; |
289 } | 323 } |
290 | 324 |
291 if (maximum > 65535) { | 325 if (maximum > 65535) { |
292 return AudioProcessing::kBadParameterError; | 326 return AudioProcessing::kBadParameterError; |
293 } | 327 } |
294 | 328 |
295 if (maximum < minimum) { | 329 if (maximum < minimum) { |
296 return AudioProcessing::kBadParameterError; | 330 return AudioProcessing::kBadParameterError; |
297 } | 331 } |
298 | 332 |
299 minimum_capture_level_ = minimum; | 333 minimum_capture_level_ = minimum; |
300 maximum_capture_level_ = maximum; | 334 maximum_capture_level_ = maximum; |
301 | 335 |
302 return Initialize(); | 336 Initialize(); |
337 return AudioProcessing::kNoError; | |
303 } | 338 } |
304 | 339 |
305 int GainControlImpl::analog_level_minimum() const { | 340 int GainControlImpl::analog_level_minimum() const { |
306 rtc::CritScope cs(crit_capture_); | 341 rtc::CritScope cs(crit_capture_); |
307 return minimum_capture_level_; | 342 return minimum_capture_level_; |
308 } | 343 } |
309 | 344 |
310 int GainControlImpl::analog_level_maximum() const { | 345 int GainControlImpl::analog_level_maximum() const { |
311 rtc::CritScope cs(crit_capture_); | 346 rtc::CritScope cs(crit_capture_); |
312 return maximum_capture_level_; | 347 return maximum_capture_level_; |
313 } | 348 } |
314 | 349 |
315 bool GainControlImpl::stream_is_saturated() const { | 350 bool GainControlImpl::stream_is_saturated() const { |
316 rtc::CritScope cs(crit_capture_); | 351 rtc::CritScope cs(crit_capture_); |
317 return stream_is_saturated_; | 352 return stream_is_saturated_; |
318 } | 353 } |
319 | 354 |
320 int GainControlImpl::set_target_level_dbfs(int level) { | 355 int GainControlImpl::set_target_level_dbfs(int level) { |
321 rtc::CritScope cs(crit_capture_); | 356 { |
322 if (level > 31 || level < 0) { | 357 rtc::CritScope cs(crit_capture_); |
323 return AudioProcessing::kBadParameterError; | 358 if (level > 31 || level < 0) { |
the sun
2016/03/09 09:42:11
Verify the input parameter outside this scope, bef
peah-webrtc
2016/03/09 12:23:39
Done.
| |
359 return AudioProcessing::kBadParameterError; | |
360 } | |
361 | |
362 target_level_dbfs_ = level; | |
324 } | 363 } |
325 | |
326 target_level_dbfs_ = level; | |
327 return Configure(); | 364 return Configure(); |
328 } | 365 } |
329 | 366 |
330 int GainControlImpl::target_level_dbfs() const { | 367 int GainControlImpl::target_level_dbfs() const { |
331 rtc::CritScope cs(crit_capture_); | 368 rtc::CritScope cs(crit_capture_); |
332 return target_level_dbfs_; | 369 return target_level_dbfs_; |
333 } | 370 } |
334 | 371 |
335 int GainControlImpl::set_compression_gain_db(int gain) { | 372 int GainControlImpl::set_compression_gain_db(int gain) { |
336 rtc::CritScope cs(crit_capture_); | 373 { |
337 if (gain < 0 || gain > 90) { | 374 rtc::CritScope cs(crit_capture_); |
338 return AudioProcessing::kBadParameterError; | 375 if (gain < 0 || gain > 90) { |
the sun
2016/03/09 09:42:11
ditto
peah-webrtc
2016/03/09 12:23:39
Done.
| |
376 return AudioProcessing::kBadParameterError; | |
377 } | |
378 | |
379 compression_gain_db_ = gain; | |
339 } | 380 } |
340 | |
341 compression_gain_db_ = gain; | |
342 return Configure(); | 381 return Configure(); |
343 } | 382 } |
344 | 383 |
345 int GainControlImpl::compression_gain_db() const { | 384 int GainControlImpl::compression_gain_db() const { |
346 rtc::CritScope cs(crit_capture_); | 385 rtc::CritScope cs(crit_capture_); |
347 return compression_gain_db_; | 386 return compression_gain_db_; |
348 } | 387 } |
349 | 388 |
350 int GainControlImpl::enable_limiter(bool enable) { | 389 int GainControlImpl::enable_limiter(bool enable) { |
351 rtc::CritScope cs(crit_capture_); | 390 { |
352 limiter_enabled_ = enable; | 391 rtc::CritScope cs(crit_capture_); |
392 limiter_enabled_ = enable; | |
393 } | |
353 return Configure(); | 394 return Configure(); |
354 } | 395 } |
355 | 396 |
356 bool GainControlImpl::is_limiter_enabled() const { | 397 bool GainControlImpl::is_limiter_enabled() const { |
357 rtc::CritScope cs(crit_capture_); | 398 rtc::CritScope cs(crit_capture_); |
358 return limiter_enabled_; | 399 return limiter_enabled_; |
359 } | 400 } |
360 | 401 |
361 int GainControlImpl::Initialize() { | 402 void GainControlImpl::Initialize() { |
362 int err = ProcessingComponent::Initialize(); | 403 rtc::CritScope cs_render(crit_render_); |
363 if (err != AudioProcessing::kNoError || !is_component_enabled()) { | 404 rtc::CritScope cs_capture(crit_capture_); |
364 return err; | 405 if (!enabled_) { |
406 return; | |
365 } | 407 } |
366 | 408 |
409 const int sample_rate_hz = apm_->proc_sample_rate_hz(); | |
410 | |
411 if (num_handles_required() > gain_controllers_.size()) { | |
412 const size_t gain_controllers_old_size = gain_controllers_.size(); | |
the sun
2016/03/09 09:42:10
Remove const
peah-webrtc
2016/03/09 12:23:39
Done.
| |
413 gain_controllers_.resize(num_handles_required()); | |
the sun
2016/03/09 13:01:53
Like the comment for EchoControlMobile - is there
| |
414 | |
415 for (size_t i = gain_controllers_old_size; i < gain_controllers_.size(); | |
416 ++i) { | |
417 gain_controllers_[i].reset(new GainController()); | |
418 } | |
419 } | |
420 | |
421 for (auto& gain_controller : gain_controllers_) { | |
422 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_, | |
423 mode_, sample_rate_hz); | |
424 } | |
425 | |
426 Configure(); | |
427 | |
367 AllocateRenderQueue(); | 428 AllocateRenderQueue(); |
368 | 429 |
369 rtc::CritScope cs_capture(crit_capture_); | 430 const int n = num_handles_required(); |
370 const int n = num_handles(); | |
371 RTC_CHECK_GE(n, 0) << "Bad number of handles: " << n; | 431 RTC_CHECK_GE(n, 0) << "Bad number of handles: " << n; |
372 | 432 |
373 capture_levels_.assign(n, analog_capture_level_); | 433 capture_levels_.assign(n, analog_capture_level_); |
374 return AudioProcessing::kNoError; | |
375 } | 434 } |
376 | 435 |
377 void GainControlImpl::AllocateRenderQueue() { | 436 void GainControlImpl::AllocateRenderQueue() { |
378 const size_t new_render_queue_element_max_size = | 437 const size_t new_render_queue_element_max_size = std::max<size_t>( |
379 std::max<size_t>(static_cast<size_t>(1), | 438 static_cast<size_t>(1), |
380 kMaxAllowedValuesOfSamplesPerFrame * num_handles()); | 439 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); |
381 | 440 |
382 rtc::CritScope cs_render(crit_render_); | 441 rtc::CritScope cs_render(crit_render_); |
383 rtc::CritScope cs_capture(crit_capture_); | 442 rtc::CritScope cs_capture(crit_capture_); |
384 | 443 |
385 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | 444 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
386 render_queue_element_max_size_ = new_render_queue_element_max_size; | 445 render_queue_element_max_size_ = new_render_queue_element_max_size; |
387 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); | 446 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
388 | 447 |
389 render_signal_queue_.reset( | 448 render_signal_queue_.reset( |
390 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( | 449 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( |
391 kMaxNumFramesToBuffer, template_queue_element, | 450 kMaxNumFramesToBuffer, template_queue_element, |
392 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); | 451 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); |
393 | 452 |
394 render_queue_buffer_.resize(render_queue_element_max_size_); | 453 render_queue_buffer_.resize(render_queue_element_max_size_); |
395 capture_queue_buffer_.resize(render_queue_element_max_size_); | 454 capture_queue_buffer_.resize(render_queue_element_max_size_); |
396 } else { | 455 } else { |
397 render_signal_queue_->Clear(); | 456 render_signal_queue_->Clear(); |
398 } | 457 } |
399 } | 458 } |
400 | 459 |
401 void* GainControlImpl::CreateHandle() const { | 460 int GainControlImpl::Configure() { |
402 return WebRtcAgc_Create(); | |
403 } | |
404 | |
405 void GainControlImpl::DestroyHandle(void* handle) const { | |
406 WebRtcAgc_Free(static_cast<Handle*>(handle)); | |
407 } | |
408 | |
409 int GainControlImpl::InitializeHandle(void* handle) const { | |
410 rtc::CritScope cs_render(crit_render_); | |
411 rtc::CritScope cs_capture(crit_capture_); | |
412 | |
413 return WebRtcAgc_Init(static_cast<Handle*>(handle), | |
414 minimum_capture_level_, | |
415 maximum_capture_level_, | |
416 MapSetting(mode_), | |
417 apm_->proc_sample_rate_hz()); | |
418 } | |
419 | |
420 int GainControlImpl::ConfigureHandle(void* handle) const { | |
421 rtc::CritScope cs_render(crit_render_); | 461 rtc::CritScope cs_render(crit_render_); |
422 rtc::CritScope cs_capture(crit_capture_); | 462 rtc::CritScope cs_capture(crit_capture_); |
423 WebRtcAgcConfig config; | 463 WebRtcAgcConfig config; |
424 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we | 464 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we |
425 // change the interface. | 465 // change the interface. |
426 //assert(target_level_dbfs_ <= 0); | 466 //assert(target_level_dbfs_ <= 0); |
427 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); | 467 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); |
428 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); | 468 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); |
429 config.compressionGaindB = | 469 config.compressionGaindB = |
430 static_cast<int16_t>(compression_gain_db_); | 470 static_cast<int16_t>(compression_gain_db_); |
431 config.limiterEnable = limiter_enabled_; | 471 config.limiterEnable = limiter_enabled_; |
432 | 472 |
433 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config); | 473 int error = AudioProcessing::kNoError; |
474 for (auto& gain_controller : gain_controllers_) { | |
475 const int handle_error = | |
476 WebRtcAgc_set_config(gain_controller->state(), config); | |
477 if (handle_error != AudioProcessing::kNoError) { | |
478 error = AudioProcessing::kNoError; | |
the sun
2016/03/09 09:42:11
error = handle_error
peah-webrtc
2016/03/09 12:23:39
Good catch!
Done.
| |
479 } | |
480 } | |
481 return error; | |
434 } | 482 } |
435 | 483 |
436 size_t GainControlImpl::num_handles_required() const { | 484 size_t GainControlImpl::num_handles_required() const { |
437 // Not locked as it only relies on APM public API which is threadsafe. | 485 // Not locked as it only relies on APM public API which is threadsafe. |
438 return apm_->num_proc_channels(); | 486 return apm_->num_proc_channels(); |
439 } | 487 } |
440 | |
441 int GainControlImpl::GetHandleError(void* handle) const { | |
442 // The AGC has no get_error() function. | |
443 // (Despite listing errors in its interface...) | |
444 assert(handle != NULL); | |
445 return AudioProcessing::kUnspecifiedError; | |
446 } | |
447 } // namespace webrtc | 488 } // namespace webrtc |
OLD | NEW |