Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: webrtc/modules/audio_processing/echo_control_mobile_impl.cc

Issue 1772453002: Removing dependency of the EchoControlMobileImpl class on ProcessingComponent. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Changes in response to reviewer comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/audio_processing/echo_control_mobile_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/echo_control_mobile_impl.h" 11 #include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <string.h> 14 #include <string.h>
15 15
16 #include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h" 16 #include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h"
17 #include "webrtc/modules/audio_processing/audio_buffer.h" 17 #include "webrtc/modules/audio_processing/audio_buffer.h"
18 #include "webrtc/system_wrappers/include/logging.h" 18 #include "webrtc/system_wrappers/include/logging.h"
19 19
20 namespace webrtc { 20 namespace webrtc {
21 21
22 typedef void Handle;
23
24 namespace { 22 namespace {
25 int16_t MapSetting(EchoControlMobile::RoutingMode mode) { 23 int16_t MapSetting(EchoControlMobile::RoutingMode mode) {
26 switch (mode) { 24 switch (mode) {
27 case EchoControlMobile::kQuietEarpieceOrHeadset: 25 case EchoControlMobile::kQuietEarpieceOrHeadset:
28 return 0; 26 return 0;
29 case EchoControlMobile::kEarpiece: 27 case EchoControlMobile::kEarpiece:
30 return 1; 28 return 1;
31 case EchoControlMobile::kLoudEarpiece: 29 case EchoControlMobile::kLoudEarpiece:
32 return 2; 30 return 2;
33 case EchoControlMobile::kSpeakerphone: 31 case EchoControlMobile::kSpeakerphone:
34 return 3; 32 return 3;
35 case EchoControlMobile::kLoudSpeakerphone: 33 case EchoControlMobile::kLoudSpeakerphone:
36 return 4; 34 return 4;
37 } 35 }
38 assert(false); 36 assert(false);
the sun 2016/03/09 15:12:40 Please change to DCHECK, like you did for gaincont
peah-webrtc 2016/03/09 21:42:49 Done.
39 return -1; 37 return -1;
40 } 38 }
41 39
42 AudioProcessing::Error MapError(int err) { 40 AudioProcessing::Error MapError(int err) {
43 switch (err) { 41 switch (err) {
44 case AECM_UNSUPPORTED_FUNCTION_ERROR: 42 case AECM_UNSUPPORTED_FUNCTION_ERROR:
45 return AudioProcessing::kUnsupportedFunctionError; 43 return AudioProcessing::kUnsupportedFunctionError;
46 case AECM_NULL_POINTER_ERROR: 44 case AECM_NULL_POINTER_ERROR:
47 return AudioProcessing::kNullPointerError; 45 return AudioProcessing::kNullPointerError;
48 case AECM_BAD_PARAMETER_ERROR: 46 case AECM_BAD_PARAMETER_ERROR:
49 return AudioProcessing::kBadParameterError; 47 return AudioProcessing::kBadParameterError;
50 case AECM_BAD_PARAMETER_WARNING: 48 case AECM_BAD_PARAMETER_WARNING:
51 return AudioProcessing::kBadStreamParameterWarning; 49 return AudioProcessing::kBadStreamParameterWarning;
52 default: 50 default:
53 // AECM_UNSPECIFIED_ERROR 51 // AECM_UNSPECIFIED_ERROR
54 // AECM_UNINITIALIZED_ERROR 52 // AECM_UNINITIALIZED_ERROR
55 return AudioProcessing::kUnspecifiedError; 53 return AudioProcessing::kUnspecifiedError;
56 } 54 }
57 } 55 }
58 // Maximum length that a frame of samples can have. 56 // Maximum length that a frame of samples can have.
59 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; 57 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
60 // Maximum number of frames to buffer in the render queue. 58 // Maximum number of frames to buffer in the render queue.
61 // TODO(peah): Decrease this once we properly handle hugely unbalanced 59 // TODO(peah): Decrease this once we properly handle hugely unbalanced
62 // reverse and forward call numbers. 60 // reverse and forward call numbers.
63 static const size_t kMaxNumFramesToBuffer = 100; 61 static const size_t kMaxNumFramesToBuffer = 100;
64 } // namespace 62 } // namespace
65 63
66 size_t EchoControlMobile::echo_path_size_bytes() { 64 size_t EchoControlMobile::echo_path_size_bytes() {
67 return WebRtcAecm_echo_path_size_bytes(); 65 return WebRtcAecm_echo_path_size_bytes();
68 } 66 }
69 67
68 class EchoControlMobileImpl::Canceller {
69 public:
70 Canceller() {
71 state_ = WebRtcAecm_Create();
72 RTC_CHECK(state_);
73 }
74
75 ~Canceller() {
76 RTC_DCHECK(state_);
77 WebRtcAecm_Free(state_);
78 }
79
80 void* state() {
81 RTC_DCHECK(state_);
82 return state_;
83 }
84
85 void Initialize(int sample_rate_hz,
86 unsigned char* external_echo_path,
87 size_t echo_path_size_bytes) {
88 RTC_DCHECK(state_);
89 int error = WebRtcAecm_Init(state_, sample_rate_hz);
90 RTC_DCHECK_EQ(AudioProcessing::kNoError, error);
91 if (external_echo_path != NULL) {
92 error = WebRtcAecm_InitEchoPath(state_, external_echo_path,
93 echo_path_size_bytes);
94 RTC_DCHECK_EQ(AudioProcessing::kNoError, error);
95 }
96 }
97
98 private:
99 void* state_;
100 RTC_DISALLOW_COPY_AND_ASSIGN(Canceller);
101 };
102
70 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm, 103 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm,
71 rtc::CriticalSection* crit_render, 104 rtc::CriticalSection* crit_render,
72 rtc::CriticalSection* crit_capture) 105 rtc::CriticalSection* crit_capture)
73 : ProcessingComponent(), 106 : apm_(apm),
74 apm_(apm),
75 crit_render_(crit_render), 107 crit_render_(crit_render),
76 crit_capture_(crit_capture), 108 crit_capture_(crit_capture),
77 routing_mode_(kSpeakerphone), 109 routing_mode_(kSpeakerphone),
78 comfort_noise_enabled_(true), 110 comfort_noise_enabled_(true),
79 external_echo_path_(NULL), 111 external_echo_path_(NULL),
80 render_queue_element_max_size_(0) { 112 render_queue_element_max_size_(0) {
81 RTC_DCHECK(apm); 113 RTC_DCHECK(apm);
82 RTC_DCHECK(crit_render); 114 RTC_DCHECK(crit_render);
83 RTC_DCHECK(crit_capture); 115 RTC_DCHECK(crit_capture);
84 } 116 }
85 117
86 EchoControlMobileImpl::~EchoControlMobileImpl() { 118 EchoControlMobileImpl::~EchoControlMobileImpl() {
87 if (external_echo_path_ != NULL) { 119 if (external_echo_path_ != NULL) {
88 delete [] external_echo_path_; 120 delete [] external_echo_path_;
89 external_echo_path_ = NULL; 121 external_echo_path_ = NULL;
90 } 122 }
91 } 123 }
92 124
93 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { 125 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
94 rtc::CritScope cs_render(crit_render_); 126 rtc::CritScope cs_render(crit_render_);
95 127 if (!enabled_) {
96 if (!is_component_enabled()) {
97 return AudioProcessing::kNoError; 128 return AudioProcessing::kNoError;
98 } 129 }
99 130
100 assert(audio->num_frames_per_band() <= 160); 131 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
101 assert(audio->num_channels() == apm_->num_reverse_channels()); 132 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels());
133 RTC_DCHECK_GE(cancellers_.size(),
134 apm_->num_output_channels() * audio->num_channels());
102 135
103 int err = AudioProcessing::kNoError; 136 int err = AudioProcessing::kNoError;
104 // The ordering convention must be followed to pass to the correct AECM. 137 // The ordering convention must be followed to pass to the correct AECM.
105 size_t handle_index = 0;
106 render_queue_buffer_.clear(); 138 render_queue_buffer_.clear();
107 for (size_t i = 0; i < apm_->num_output_channels(); i++) { 139 int render_channel = 0;
108 for (size_t j = 0; j < audio->num_channels(); j++) { 140 for (auto& canceller : cancellers_) {
109 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 141 err = WebRtcAecm_GetBufferFarendError(
110 err = WebRtcAecm_GetBufferFarendError( 142 canceller->state(),
111 my_handle, audio->split_bands_const(j)[kBand0To8kHz], 143 audio->split_bands_const(render_channel)[kBand0To8kHz],
112 audio->num_frames_per_band()); 144 audio->num_frames_per_band());
113 145
114 if (err != AudioProcessing::kNoError) 146 if (err != AudioProcessing::kNoError)
115 return MapError(err); // TODO(ajm): warning possible?); 147 return MapError(err); // TODO(ajm): warning possible?);
116 148
117 // Buffer the samples in the render queue. 149 // Buffer the samples in the render queue.
118 render_queue_buffer_.insert(render_queue_buffer_.end(), 150 render_queue_buffer_.insert(
119 audio->split_bands_const(j)[kBand0To8kHz], 151 render_queue_buffer_.end(),
120 (audio->split_bands_const(j)[kBand0To8kHz] + 152 audio->split_bands_const(render_channel)[kBand0To8kHz],
121 audio->num_frames_per_band())); 153 (audio->split_bands_const(render_channel)[kBand0To8kHz] +
122 154 audio->num_frames_per_band()));
123 handle_index++; 155 render_channel = (render_channel + 1) % audio->num_channels();
124 }
125 } 156 }
126 157
127 // Insert the samples into the queue. 158 // Insert the samples into the queue.
128 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { 159 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
129 // The data queue is full and needs to be emptied. 160 // The data queue is full and needs to be emptied.
130 ReadQueuedRenderData(); 161 ReadQueuedRenderData();
131 162
132 // Retry the insert (should always work). 163 // Retry the insert (should always work).
133 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); 164 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
134 } 165 }
135 166
136 return AudioProcessing::kNoError; 167 return AudioProcessing::kNoError;
137 } 168 }
138 169
139 // Read chunks of data that were received and queued on the render side from 170 // Read chunks of data that were received and queued on the render side from
140 // a queue. All the data chunks are buffered into the farend signal of the AEC. 171 // a queue. All the data chunks are buffered into the farend signal of the AEC.
141 void EchoControlMobileImpl::ReadQueuedRenderData() { 172 void EchoControlMobileImpl::ReadQueuedRenderData() {
142 rtc::CritScope cs_capture(crit_capture_); 173 rtc::CritScope cs_capture(crit_capture_);
143 174
144 if (!is_component_enabled()) { 175 if (!enabled_) {
145 return; 176 return;
146 } 177 }
147 178
148 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { 179 while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
149 size_t handle_index = 0;
150 size_t buffer_index = 0; 180 size_t buffer_index = 0;
151 const size_t num_frames_per_band = 181 size_t num_frames_per_band =
152 capture_queue_buffer_.size() / 182 capture_queue_buffer_.size() /
153 (apm_->num_output_channels() * apm_->num_reverse_channels()); 183 (apm_->num_output_channels() * apm_->num_reverse_channels());
154 for (size_t i = 0; i < apm_->num_output_channels(); i++) {
155 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) {
156 Handle* my_handle = static_cast<Handle*>(handle(handle_index));
157 WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index],
158 num_frames_per_band);
159 184
160 buffer_index += num_frames_per_band; 185 for (auto& canceller : cancellers_) {
the sun 2016/03/09 15:12:40 Nice!
peah-webrtc 2016/03/09 21:42:49 :-) Acknowledged.
161 handle_index++; 186 WebRtcAecm_BufferFarend(canceller->state(),
162 } 187 &capture_queue_buffer_[buffer_index],
188 num_frames_per_band);
189
190 buffer_index += num_frames_per_band;
163 } 191 }
164 } 192 }
165 } 193 }
166 194
167 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { 195 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) {
168 rtc::CritScope cs_capture(crit_capture_); 196 rtc::CritScope cs_capture(crit_capture_);
169 197 if (!enabled_) {
170 if (!is_component_enabled()) {
171 return AudioProcessing::kNoError; 198 return AudioProcessing::kNoError;
172 } 199 }
173 200
174 if (!apm_->was_stream_delay_set()) { 201 if (!apm_->was_stream_delay_set()) {
175 return AudioProcessing::kStreamParameterNotSetError; 202 return AudioProcessing::kStreamParameterNotSetError;
176 } 203 }
177 204
178 assert(audio->num_frames_per_band() <= 160); 205 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
179 assert(audio->num_channels() == apm_->num_output_channels()); 206 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_output_channels());
180 207
181 int err = AudioProcessing::kNoError; 208 int err = AudioProcessing::kNoError;
182 209
183 // The ordering convention must be followed to pass to the correct AECM. 210 // The ordering convention must be followed to pass to the correct AECM.
184 size_t handle_index = 0; 211 const int16_t* noisy = nullptr;
185 for (size_t i = 0; i < audio->num_channels(); i++) { 212 const int16_t* clean = nullptr;
186 // TODO(ajm): improve how this works, possibly inside AECM. 213 size_t render_channel = apm_->num_reverse_channels() - 1;
the sun 2016/03/09 15:12:40 Uhm. I think the old code actually was easier to r
peah-webrtc 2016/03/09 21:42:49 This is extremely strange code, which is accentuat
187 // This is kind of hacked up. 214 int capture_channel = -1;
188 const int16_t* noisy = audio->low_pass_reference(i); 215 for (auto& canceller : cancellers_) {
189 const int16_t* clean = audio->split_bands_const(i)[kBand0To8kHz]; 216 ++render_channel;
190 if (noisy == NULL) { 217 if (render_channel == apm_->num_reverse_channels()) {
191 noisy = clean; 218 render_channel = 0;
192 clean = NULL; 219 ++capture_channel;
220 // TODO(ajm): improve how this works, possibly inside AECM.
221 // This is kind of hacked up.
222 noisy = audio->low_pass_reference(capture_channel);
223 clean = audio->split_bands_const(capture_channel)[kBand0To8kHz];
224 if (noisy == NULL) {
225 noisy = clean;
226 clean = NULL;
227 }
193 } 228 }
194 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) {
195 Handle* my_handle = static_cast<Handle*>(handle(handle_index));
196 err = WebRtcAecm_Process(
197 my_handle,
198 noisy,
199 clean,
200 audio->split_bands(i)[kBand0To8kHz],
201 audio->num_frames_per_band(),
202 apm_->stream_delay_ms());
203 229
204 if (err != AudioProcessing::kNoError) 230 err = WebRtcAecm_Process(canceller->state(), noisy, clean,
205 return MapError(err); 231 audio->split_bands(capture_channel)[kBand0To8kHz],
232 audio->num_frames_per_band(),
233 apm_->stream_delay_ms());
206 234
207 handle_index++; 235 if (err != AudioProcessing::kNoError) {
236 return MapError(err);
208 } 237 }
209 } 238 }
210
211 return AudioProcessing::kNoError; 239 return AudioProcessing::kNoError;
212 } 240 }
213 241
214 int EchoControlMobileImpl::Enable(bool enable) { 242 int EchoControlMobileImpl::Enable(bool enable) {
215 // Ensure AEC and AECM are not both enabled. 243 // Ensure AEC and AECM are not both enabled.
216 rtc::CritScope cs_render(crit_render_); 244 rtc::CritScope cs_render(crit_render_);
217 rtc::CritScope cs_capture(crit_capture_); 245 rtc::CritScope cs_capture(crit_capture_);
218 // The is_enabled call is safe from a deadlock perspective 246 // The is_enabled call is safe from a deadlock perspective
219 // as both locks are allready held in the correct order. 247 // as both locks are allready held in the correct order.
220 if (enable && apm_->echo_cancellation()->is_enabled()) { 248 if (enable && apm_->echo_cancellation()->is_enabled()) {
221 return AudioProcessing::kBadParameterError; 249 return AudioProcessing::kBadParameterError;
222 } 250 }
223 251
224 return EnableComponent(enable); 252 if (enable && !enabled_) {
253 enabled_ = enable; // Must be set before Initialize() is called.
254 Initialize();
255 } else {
256 enabled_ = enable;
257 }
258 return AudioProcessing::kNoError;
225 } 259 }
226 260
227 bool EchoControlMobileImpl::is_enabled() const { 261 bool EchoControlMobileImpl::is_enabled() const {
228 rtc::CritScope cs(crit_capture_); 262 rtc::CritScope cs(crit_capture_);
229 return is_component_enabled(); 263 return enabled_;
230 } 264 }
231 265
232 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { 266 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) {
233 if (MapSetting(mode) == -1) { 267 if (MapSetting(mode) == -1) {
234 return AudioProcessing::kBadParameterError; 268 return AudioProcessing::kBadParameterError;
235 } 269 }
236 270
237 { 271 {
238 rtc::CritScope cs(crit_capture_); 272 rtc::CritScope cs(crit_capture_);
239 routing_mode_ = mode; 273 routing_mode_ = mode;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 // Size mismatch 306 // Size mismatch
273 return AudioProcessing::kBadParameterError; 307 return AudioProcessing::kBadParameterError;
274 } 308 }
275 309
276 if (external_echo_path_ == NULL) { 310 if (external_echo_path_ == NULL) {
277 external_echo_path_ = new unsigned char[size_bytes]; 311 external_echo_path_ = new unsigned char[size_bytes];
278 } 312 }
279 memcpy(external_echo_path_, echo_path, size_bytes); 313 memcpy(external_echo_path_, echo_path, size_bytes);
280 } 314 }
281 315
282 return Initialize(); 316 Initialize();
317 return AudioProcessing::kNoError;
283 } 318 }
284 319
285 int EchoControlMobileImpl::GetEchoPath(void* echo_path, 320 int EchoControlMobileImpl::GetEchoPath(void* echo_path,
286 size_t size_bytes) const { 321 size_t size_bytes) const {
287 rtc::CritScope cs(crit_capture_); 322 rtc::CritScope cs(crit_capture_);
288 if (echo_path == NULL) { 323 if (echo_path == NULL) {
289 return AudioProcessing::kNullPointerError; 324 return AudioProcessing::kNullPointerError;
290 } 325 }
291 if (size_bytes != echo_path_size_bytes()) { 326 if (size_bytes != echo_path_size_bytes()) {
292 // Size mismatch 327 // Size mismatch
293 return AudioProcessing::kBadParameterError; 328 return AudioProcessing::kBadParameterError;
294 } 329 }
295 if (!is_component_enabled()) { 330 if (!enabled_) {
296 return AudioProcessing::kNotEnabledError; 331 return AudioProcessing::kNotEnabledError;
297 } 332 }
298 333
299 // Get the echo path from the first channel 334 // Get the echo path from the first channel
300 Handle* my_handle = static_cast<Handle*>(handle(0)); 335 int32_t err =
301 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes); 336 WebRtcAecm_GetEchoPath(cancellers_[0]->state(), echo_path, size_bytes);
302 if (err != 0) 337 if (err != 0) {
303 return MapError(err); 338 return MapError(err);
339 }
304 340
305 return AudioProcessing::kNoError; 341 return AudioProcessing::kNoError;
306 } 342 }
307 343
308 int EchoControlMobileImpl::Initialize() { 344 void EchoControlMobileImpl::Initialize() {
309 { 345 rtc::CritScope cs_render(crit_render_);
310 rtc::CritScope cs_capture(crit_capture_); 346 rtc::CritScope cs_capture(crit_capture_);
311 if (!is_component_enabled()) { 347 if (!enabled_) {
312 return AudioProcessing::kNoError; 348 return;
313 }
314 } 349 }
315 350
316 if (apm_->proc_sample_rate_hz() > AudioProcessing::kSampleRate16kHz) { 351 if (apm_->proc_sample_rate_hz() > AudioProcessing::kSampleRate16kHz) {
317 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; 352 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
318 return AudioProcessing::kBadSampleRateError;
319 } 353 }
320 354
321 int err = ProcessingComponent::Initialize(); 355 int sample_rate_hz = apm_->proc_sample_rate_hz();
322 if (err != AudioProcessing::kNoError) { 356 cancellers_.resize(num_handles_required());
323 return err; 357 for (auto& canceller : cancellers_) {
358 if (!canceller) {
the sun 2016/03/09 15:12:40 Ah, cute! :)
peah-webrtc 2016/03/09 21:42:49 :-) Acknowledged.
359 canceller.reset(new Canceller());
360 }
361 canceller->Initialize(sample_rate_hz, external_echo_path_,
362 echo_path_size_bytes());
324 } 363 }
325 364
365 Configure();
366
326 AllocateRenderQueue(); 367 AllocateRenderQueue();
327
328 return AudioProcessing::kNoError;
329 } 368 }
330 369
331 void EchoControlMobileImpl::AllocateRenderQueue() { 370 void EchoControlMobileImpl::AllocateRenderQueue() {
332 const size_t new_render_queue_element_max_size = std::max<size_t>( 371 const size_t new_render_queue_element_max_size = std::max<size_t>(
333 static_cast<size_t>(1), 372 static_cast<size_t>(1),
334 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); 373 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
335 374
336 rtc::CritScope cs_render(crit_render_); 375 rtc::CritScope cs_render(crit_render_);
337 rtc::CritScope cs_capture(crit_capture_); 376 rtc::CritScope cs_capture(crit_capture_);
338 377
339 // Reallocate the queue if the queue item size is too small to fit the 378 // Reallocate the queue if the queue item size is too small to fit the
340 // data to put in the queue. 379 // data to put in the queue.
341 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { 380 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
342 render_queue_element_max_size_ = new_render_queue_element_max_size; 381 render_queue_element_max_size_ = new_render_queue_element_max_size;
343 382
344 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); 383 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
345 384
346 render_signal_queue_.reset( 385 render_signal_queue_.reset(
347 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( 386 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
348 kMaxNumFramesToBuffer, template_queue_element, 387 kMaxNumFramesToBuffer, template_queue_element,
349 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); 388 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
350 389
351 render_queue_buffer_.resize(render_queue_element_max_size_); 390 render_queue_buffer_.resize(render_queue_element_max_size_);
352 capture_queue_buffer_.resize(render_queue_element_max_size_); 391 capture_queue_buffer_.resize(render_queue_element_max_size_);
353 } else { 392 } else {
354 render_signal_queue_->Clear(); 393 render_signal_queue_->Clear();
355 } 394 }
356 } 395 }
357 396
358 void* EchoControlMobileImpl::CreateHandle() const { 397 int EchoControlMobileImpl::Configure() {
359 return WebRtcAecm_Create();
360 }
361
362 void EchoControlMobileImpl::DestroyHandle(void* handle) const {
363 // This method is only called in a non-concurrent manner during APM
364 // destruction.
365 WebRtcAecm_Free(static_cast<Handle*>(handle));
366 }
367
368 int EchoControlMobileImpl::InitializeHandle(void* handle) const {
369 rtc::CritScope cs_render(crit_render_);
370 rtc::CritScope cs_capture(crit_capture_);
371 assert(handle != NULL);
372 Handle* my_handle = static_cast<Handle*>(handle);
373 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) {
374 return GetHandleError(my_handle);
375 }
376 if (external_echo_path_ != NULL) {
377 if (WebRtcAecm_InitEchoPath(my_handle,
378 external_echo_path_,
379 echo_path_size_bytes()) != 0) {
380 return GetHandleError(my_handle);
381 }
382 }
383
384 return AudioProcessing::kNoError;
385 }
386
387 int EchoControlMobileImpl::ConfigureHandle(void* handle) const {
388 rtc::CritScope cs_render(crit_render_); 398 rtc::CritScope cs_render(crit_render_);
389 rtc::CritScope cs_capture(crit_capture_); 399 rtc::CritScope cs_capture(crit_capture_);
390 AecmConfig config; 400 AecmConfig config;
391 config.cngMode = comfort_noise_enabled_; 401 config.cngMode = comfort_noise_enabled_;
392 config.echoMode = MapSetting(routing_mode_); 402 config.echoMode = MapSetting(routing_mode_);
393 403 int error = AudioProcessing::kNoError;
394 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); 404 for (auto& canceller : cancellers_) {
405 int handle_error = WebRtcAecm_set_config(canceller->state(), config);
406 if (handle_error != AudioProcessing::kNoError) {
407 error = handle_error;
408 }
409 }
410 return error;
395 } 411 }
396 412
397 size_t EchoControlMobileImpl::num_handles_required() const { 413 size_t EchoControlMobileImpl::num_handles_required() const {
398 // Not locked as it only relies on APM public API which is threadsafe. 414 // Not locked as it only relies on APM public API which is threadsafe.
399 return apm_->num_output_channels() * apm_->num_reverse_channels(); 415 return apm_->num_output_channels() * apm_->num_reverse_channels();
400 } 416 }
401
402 int EchoControlMobileImpl::GetHandleError(void* handle) const {
403 // Not locked as it does not rely on anything in the state.
404 assert(handle != NULL);
405 return AudioProcessing::kUnspecifiedError;
406 }
407 } // namespace webrtc 417 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/echo_control_mobile_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698