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