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

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

Issue 2444793005: Moved the AECM render sample queue into the audio processing module (Closed)
Patch Set: Rebase Created 4 years, 1 month 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
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
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 case AECM_BAD_PARAMETER_ERROR: 46 case AECM_BAD_PARAMETER_ERROR:
47 return AudioProcessing::kBadParameterError; 47 return AudioProcessing::kBadParameterError;
48 case AECM_BAD_PARAMETER_WARNING: 48 case AECM_BAD_PARAMETER_WARNING:
49 return AudioProcessing::kBadStreamParameterWarning; 49 return AudioProcessing::kBadStreamParameterWarning;
50 default: 50 default:
51 // AECM_UNSPECIFIED_ERROR 51 // AECM_UNSPECIFIED_ERROR
52 // AECM_UNINITIALIZED_ERROR 52 // AECM_UNINITIALIZED_ERROR
53 return AudioProcessing::kUnspecifiedError; 53 return AudioProcessing::kUnspecifiedError;
54 } 54 }
55 } 55 }
56 // Maximum length that a frame of samples can have.
57 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
58 // Maximum number of frames to buffer in the render queue.
59 // TODO(peah): Decrease this once we properly handle hugely unbalanced
60 // reverse and forward call numbers.
61 static const size_t kMaxNumFramesToBuffer = 100;
62 } // namespace 56 } // namespace
63 57
64 size_t EchoControlMobile::echo_path_size_bytes() { 58 size_t EchoControlMobile::echo_path_size_bytes() {
65 return WebRtcAecm_echo_path_size_bytes(); 59 return WebRtcAecm_echo_path_size_bytes();
66 } 60 }
67 61
68 struct EchoControlMobileImpl::StreamProperties { 62 struct EchoControlMobileImpl::StreamProperties {
69 StreamProperties() = delete; 63 StreamProperties() = delete;
70 StreamProperties(int sample_rate_hz, 64 StreamProperties(int sample_rate_hz,
71 size_t num_reverse_channels, 65 size_t num_reverse_channels,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 void* state_; 107 void* state_;
114 RTC_DISALLOW_COPY_AND_ASSIGN(Canceller); 108 RTC_DISALLOW_COPY_AND_ASSIGN(Canceller);
115 }; 109 };
116 110
117 EchoControlMobileImpl::EchoControlMobileImpl(rtc::CriticalSection* crit_render, 111 EchoControlMobileImpl::EchoControlMobileImpl(rtc::CriticalSection* crit_render,
118 rtc::CriticalSection* crit_capture) 112 rtc::CriticalSection* crit_capture)
119 : crit_render_(crit_render), 113 : crit_render_(crit_render),
120 crit_capture_(crit_capture), 114 crit_capture_(crit_capture),
121 routing_mode_(kSpeakerphone), 115 routing_mode_(kSpeakerphone),
122 comfort_noise_enabled_(true), 116 comfort_noise_enabled_(true),
123 external_echo_path_(NULL), 117 external_echo_path_(NULL) {
124 render_queue_element_max_size_(0) {
125 RTC_DCHECK(crit_render); 118 RTC_DCHECK(crit_render);
126 RTC_DCHECK(crit_capture); 119 RTC_DCHECK(crit_capture);
127 } 120 }
128 121
129 EchoControlMobileImpl::~EchoControlMobileImpl() { 122 EchoControlMobileImpl::~EchoControlMobileImpl() {
130 if (external_echo_path_ != NULL) { 123 if (external_echo_path_ != NULL) {
131 delete [] external_echo_path_; 124 delete [] external_echo_path_;
132 external_echo_path_ = NULL; 125 external_echo_path_ = NULL;
133 } 126 }
134 } 127 }
135 128
136 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { 129 void EchoControlMobileImpl::ProcessRenderAudio(
137 rtc::CritScope cs_render(crit_render_); 130 rtc::ArrayView<const int16_t> packed_render_audio) {
138 if (!enabled_) {
139 return AudioProcessing::kNoError;
140 }
141
142 RTC_DCHECK(stream_properties_);
143 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
144 RTC_DCHECK_EQ(audio->num_channels(),
145 stream_properties_->num_reverse_channels);
146 RTC_DCHECK_GE(cancellers_.size(), stream_properties_->num_output_channels *
147 audio->num_channels());
148
149 int err = AudioProcessing::kNoError;
150 // The ordering convention must be followed to pass to the correct AECM.
151 render_queue_buffer_.clear();
152 int render_channel = 0;
153 for (auto& canceller : cancellers_) {
154 err = WebRtcAecm_GetBufferFarendError(
155 canceller->state(),
156 audio->split_bands_const(render_channel)[kBand0To8kHz],
157 audio->num_frames_per_band());
158
159 if (err != AudioProcessing::kNoError)
160 return MapError(err); // TODO(ajm): warning possible?);
161
162 // Buffer the samples in the render queue.
163 render_queue_buffer_.insert(
164 render_queue_buffer_.end(),
165 audio->split_bands_const(render_channel)[kBand0To8kHz],
166 (audio->split_bands_const(render_channel)[kBand0To8kHz] +
167 audio->num_frames_per_band()));
168 render_channel = (render_channel + 1) % audio->num_channels();
169 }
170
171 // Insert the samples into the queue.
172 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
173 // The data queue is full and needs to be emptied.
174 ReadQueuedRenderData();
175
176 // Retry the insert (should always work).
177 bool result = render_signal_queue_->Insert(&render_queue_buffer_);
178 RTC_DCHECK(result);
179 }
180
181 return AudioProcessing::kNoError;
182 }
183
184 // Read chunks of data that were received and queued on the render side from
185 // a queue. All the data chunks are buffered into the farend signal of the AEC.
186 void EchoControlMobileImpl::ReadQueuedRenderData() {
187 rtc::CritScope cs_capture(crit_capture_); 131 rtc::CritScope cs_capture(crit_capture_);
188 RTC_DCHECK(stream_properties_);
189
190 if (!enabled_) { 132 if (!enabled_) {
191 return; 133 return;
192 } 134 }
193 135
194 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { 136 RTC_DCHECK(stream_properties_);
195 size_t buffer_index = 0;
196 size_t num_frames_per_band = capture_queue_buffer_.size() /
197 (stream_properties_->num_output_channels *
198 stream_properties_->num_reverse_channels);
199 137
200 for (auto& canceller : cancellers_) { 138 size_t buffer_index = 0;
201 WebRtcAecm_BufferFarend(canceller->state(), 139 size_t num_frames_per_band =
202 &capture_queue_buffer_[buffer_index], 140 packed_render_audio.size() / (stream_properties_->num_output_channels *
203 num_frames_per_band); 141 stream_properties_->num_reverse_channels);
204 142
205 buffer_index += num_frames_per_band; 143 for (auto& canceller : cancellers_) {
144 WebRtcAecm_BufferFarend(canceller->state(),
145 &packed_render_audio[buffer_index],
146 num_frames_per_band);
147
148 buffer_index += num_frames_per_band;
149 }
150 }
151
152 void EchoControlMobileImpl::PackRenderAudioBuffer(
153 const AudioBuffer* audio,
154 size_t num_output_channels,
155 size_t num_channels,
156 std::vector<int16_t>* packed_buffer) {
157 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
158 RTC_DCHECK_EQ(num_channels, audio->num_channels());
159
160 // The ordering convention must be followed to pass to the correct AECM.
161 packed_buffer->clear();
162 int render_channel = 0;
163 for (size_t i = 0; i < num_output_channels; i++) {
164 for (size_t j = 0; j < audio->num_channels(); j++) {
165 // Buffer the samples in the render queue.
166 packed_buffer->insert(
167 packed_buffer->end(),
168 audio->split_bands_const(render_channel)[kBand0To8kHz],
169 (audio->split_bands_const(render_channel)[kBand0To8kHz] +
170 audio->num_frames_per_band()));
171 render_channel = (render_channel + 1) % audio->num_channels();
206 } 172 }
207 } 173 }
208 } 174 }
209 175
176 size_t EchoControlMobileImpl::NumCancellersRequired(
177 size_t num_output_channels,
178 size_t num_reverse_channels) {
179 return num_output_channels * num_reverse_channels;
180 }
181
210 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio, 182 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio,
211 int stream_delay_ms) { 183 int stream_delay_ms) {
212 rtc::CritScope cs_capture(crit_capture_); 184 rtc::CritScope cs_capture(crit_capture_);
213 if (!enabled_) { 185 if (!enabled_) {
214 return AudioProcessing::kNoError; 186 return AudioProcessing::kNoError;
215 } 187 }
216 188
217 RTC_DCHECK(stream_properties_); 189 RTC_DCHECK(stream_properties_);
218 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); 190 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
219 RTC_DCHECK_EQ(audio->num_channels(), stream_properties_->num_output_channels); 191 RTC_DCHECK_EQ(audio->num_channels(), stream_properties_->num_output_channels);
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 sample_rate_hz, num_reverse_channels, num_output_channels)); 350 sample_rate_hz, num_reverse_channels, num_output_channels));
379 351
380 if (!enabled_) { 352 if (!enabled_) {
381 return; 353 return;
382 } 354 }
383 355
384 if (stream_properties_->sample_rate_hz > AudioProcessing::kSampleRate16kHz) { 356 if (stream_properties_->sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
385 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; 357 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
386 } 358 }
387 359
388 cancellers_.resize(num_handles_required()); 360 cancellers_.resize(
361 NumCancellersRequired(stream_properties_->num_output_channels,
362 stream_properties_->num_reverse_channels));
363
389 for (auto& canceller : cancellers_) { 364 for (auto& canceller : cancellers_) {
390 if (!canceller) { 365 if (!canceller) {
391 canceller.reset(new Canceller()); 366 canceller.reset(new Canceller());
392 } 367 }
393 canceller->Initialize(sample_rate_hz, external_echo_path_, 368 canceller->Initialize(sample_rate_hz, external_echo_path_,
394 echo_path_size_bytes()); 369 echo_path_size_bytes());
395 } 370 }
396 371
397 Configure(); 372 Configure();
398
399 AllocateRenderQueue();
400 }
401
402 void EchoControlMobileImpl::AllocateRenderQueue() {
403 const size_t new_render_queue_element_max_size = std::max<size_t>(
404 static_cast<size_t>(1),
405 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
406
407 rtc::CritScope cs_render(crit_render_);
408 rtc::CritScope cs_capture(crit_capture_);
409
410 // Reallocate the queue if the queue item size is too small to fit the
411 // data to put in the queue.
412 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
413 render_queue_element_max_size_ = new_render_queue_element_max_size;
414
415 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
416
417 render_signal_queue_.reset(
418 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
419 kMaxNumFramesToBuffer, template_queue_element,
420 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
421
422 render_queue_buffer_.resize(render_queue_element_max_size_);
423 capture_queue_buffer_.resize(render_queue_element_max_size_);
424 } else {
425 render_signal_queue_->Clear();
426 }
427 } 373 }
428 374
429 int EchoControlMobileImpl::Configure() { 375 int EchoControlMobileImpl::Configure() {
430 rtc::CritScope cs_render(crit_render_); 376 rtc::CritScope cs_render(crit_render_);
431 rtc::CritScope cs_capture(crit_capture_); 377 rtc::CritScope cs_capture(crit_capture_);
432 AecmConfig config; 378 AecmConfig config;
433 config.cngMode = comfort_noise_enabled_; 379 config.cngMode = comfort_noise_enabled_;
434 config.echoMode = MapSetting(routing_mode_); 380 config.echoMode = MapSetting(routing_mode_);
435 int error = AudioProcessing::kNoError; 381 int error = AudioProcessing::kNoError;
436 for (auto& canceller : cancellers_) { 382 for (auto& canceller : cancellers_) {
437 int handle_error = WebRtcAecm_set_config(canceller->state(), config); 383 int handle_error = WebRtcAecm_set_config(canceller->state(), config);
438 if (handle_error != AudioProcessing::kNoError) { 384 if (handle_error != AudioProcessing::kNoError) {
439 error = handle_error; 385 error = handle_error;
440 } 386 }
441 } 387 }
442 return error; 388 return error;
443 } 389 }
444 390
445 size_t EchoControlMobileImpl::num_handles_required() const {
446 RTC_DCHECK(stream_properties_);
447 return stream_properties_->num_output_channels *
448 stream_properties_->num_reverse_channels;
449 }
450 } // namespace webrtc 391 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698