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

Side by Side Diff: webrtc/modules/audio_processing/aec3/echo_canceller3.cc

Issue 2784023002: Major AEC3 render pipeline changes (Closed)
Patch Set: Disabled one more DEATH test that caused issues due to bug on bots Created 3 years, 8 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 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 #include "webrtc/modules/audio_processing/aec3/echo_canceller3.h" 10 #include "webrtc/modules/audio_processing/aec3/echo_canceller3.h"
11 11
12 #include <sstream> 12 #include <sstream>
13 13
14 #include "webrtc/base/atomicops.h" 14 #include "webrtc/base/atomicops.h"
15 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" 15 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
16 16
17 namespace webrtc { 17 namespace webrtc {
18 18
19 namespace { 19 namespace {
20 20
21 enum class EchoCanceller3ApiCall { kCapture, kRender };
22
21 bool DetectSaturation(rtc::ArrayView<const float> y) { 23 bool DetectSaturation(rtc::ArrayView<const float> y) {
22 for (auto y_k : y) { 24 for (auto y_k : y) {
23 if (y_k >= 32700.0f || y_k <= -32700.0f) { 25 if (y_k >= 32700.0f || y_k <= -32700.0f) {
24 return true; 26 return true;
25 } 27 }
26 } 28 }
27 return false; 29 return false;
28 } 30 }
29 31
30 void FillSubFrameView(AudioBuffer* frame, 32 void FillSubFrameView(AudioBuffer* frame,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 if (!capture_blocker->IsBlockAvailable()) { 80 if (!capture_blocker->IsBlockAvailable()) {
79 return; 81 return;
80 } 82 }
81 83
82 capture_blocker->ExtractBlock(block); 84 capture_blocker->ExtractBlock(block);
83 block_processor->ProcessCapture(level_change, saturated_microphone_signal, 85 block_processor->ProcessCapture(level_change, saturated_microphone_signal,
84 block); 86 block);
85 output_framer->InsertBlock(*block); 87 output_framer->InsertBlock(*block);
86 } 88 }
87 89
88 bool BufferRenderFrameContent( 90 void BufferRenderFrameContent(
89 std::vector<std::vector<float>>* render_frame, 91 std::vector<std::vector<float>>* render_frame,
90 size_t sub_frame_index, 92 size_t sub_frame_index,
91 FrameBlocker* render_blocker, 93 FrameBlocker* render_blocker,
92 BlockProcessor* block_processor, 94 BlockProcessor* block_processor,
93 std::vector<std::vector<float>>* block, 95 std::vector<std::vector<float>>* block,
94 std::vector<rtc::ArrayView<float>>* sub_frame_view) { 96 std::vector<rtc::ArrayView<float>>* sub_frame_view) {
95 FillSubFrameView(render_frame, sub_frame_index, sub_frame_view); 97 FillSubFrameView(render_frame, sub_frame_index, sub_frame_view);
96 render_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block); 98 render_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block);
97 return block_processor->BufferRender(block); 99 block_processor->BufferRender(*block);
98 } 100 }
99 101
100 bool BufferRemainingRenderFrameContent(FrameBlocker* render_blocker, 102 void BufferRemainingRenderFrameContent(FrameBlocker* render_blocker,
101 BlockProcessor* block_processor, 103 BlockProcessor* block_processor,
102 std::vector<std::vector<float>>* block) { 104 std::vector<std::vector<float>>* block) {
103 if (!render_blocker->IsBlockAvailable()) { 105 if (!render_blocker->IsBlockAvailable()) {
104 return true; 106 return;
105 } 107 }
106 render_blocker->ExtractBlock(block); 108 render_blocker->ExtractBlock(block);
107 return block_processor->BufferRender(block); 109 block_processor->BufferRender(*block);
108 } 110 }
109 111
110 void CopyLowestBandIntoFrame(AudioBuffer* buffer, 112 void CopyBufferIntoFrame(AudioBuffer* buffer,
111 size_t num_bands, 113 size_t num_bands,
112 size_t frame_length, 114 size_t frame_length,
113 std::vector<std::vector<float>>* frame) { 115 std::vector<std::vector<float>>* frame) {
114 RTC_DCHECK_EQ(num_bands, frame->size()); 116 RTC_DCHECK_EQ(num_bands, frame->size());
115 RTC_DCHECK_EQ(frame_length, (*frame)[0].size()); 117 RTC_DCHECK_EQ(frame_length, (*frame)[0].size());
116 rtc::ArrayView<float> buffer_view(&buffer->channels_f()[0][0], frame_length); 118 for (size_t k = 0; k < num_bands; ++k) {
117 std::copy(buffer_view.begin(), buffer_view.end(), (*frame)[0].begin()); 119 rtc::ArrayView<float> buffer_view(&buffer->split_bands_f(0)[k][0],
120 frame_length);
121 std::copy(buffer_view.begin(), buffer_view.end(), (*frame)[k].begin());
122 }
118 } 123 }
119 124
120 // [B,A] = butter(2,100/4000,'high') 125 // [B,A] = butter(2,100/4000,'high')
121 const CascadedBiQuadFilter::BiQuadCoefficients 126 const CascadedBiQuadFilter::BiQuadCoefficients
122 kHighPassFilterCoefficients_8kHz = {{0.94598f, -1.89195f, 0.94598f}, 127 kHighPassFilterCoefficients_8kHz = {{0.94598f, -1.89195f, 0.94598f},
123 {-1.88903f, 0.89487f}}; 128 {-1.88903f, 0.89487f}};
124 const int kNumberOfHighPassBiQuads_8kHz = 1; 129 const int kNumberOfHighPassBiQuads_8kHz = 1;
125 130
126 // [B,A] = butter(2,100/8000,'high') 131 // [B,A] = butter(2,100/8000,'high')
127 const CascadedBiQuadFilter::BiQuadCoefficients 132 const CascadedBiQuadFilter::BiQuadCoefficients
128 kHighPassFilterCoefficients_16kHz = {{0.97261f, -1.94523f, 0.97261f}, 133 kHighPassFilterCoefficients_16kHz = {{0.97261f, -1.94523f, 0.97261f},
129 {-1.94448f, 0.94598f}}; 134 {-1.94448f, 0.94598f}};
130 const int kNumberOfHighPassBiQuads_16kHz = 1; 135 const int kNumberOfHighPassBiQuads_16kHz = 1;
131 136
132 static constexpr size_t kRenderTransferQueueSize = 30;
133
134 } // namespace 137 } // namespace
135 138
136 class EchoCanceller3::RenderWriter { 139 class EchoCanceller3::RenderWriter {
137 public: 140 public:
138 RenderWriter(ApmDataDumper* data_dumper, 141 RenderWriter(ApmDataDumper* data_dumper,
139 SwapQueue<std::vector<std::vector<float>>, 142 SwapQueue<std::vector<std::vector<float>>,
140 Aec3RenderQueueItemVerifier>* render_transfer_queue, 143 Aec3RenderQueueItemVerifier>* render_transfer_queue,
141 std::unique_ptr<CascadedBiQuadFilter> render_highpass_filter, 144 std::unique_ptr<CascadedBiQuadFilter> render_highpass_filter,
142 int sample_rate_hz, 145 int sample_rate_hz,
143 int frame_length, 146 int frame_length,
144 int num_bands); 147 int num_bands);
145 ~RenderWriter(); 148 ~RenderWriter();
146 bool Insert(AudioBuffer* render); 149 void Insert(AudioBuffer* render);
147 150
148 private: 151 private:
149 ApmDataDumper* data_dumper_; 152 ApmDataDumper* data_dumper_;
150 const int sample_rate_hz_; 153 const int sample_rate_hz_;
151 const size_t frame_length_; 154 const size_t frame_length_;
152 const int num_bands_; 155 const int num_bands_;
153 std::unique_ptr<CascadedBiQuadFilter> render_highpass_filter_; 156 std::unique_ptr<CascadedBiQuadFilter> render_highpass_filter_;
154 std::vector<std::vector<float>> render_queue_input_frame_; 157 std::vector<std::vector<float>> render_queue_input_frame_;
155 SwapQueue<std::vector<std::vector<float>>, Aec3RenderQueueItemVerifier>* 158 SwapQueue<std::vector<std::vector<float>>, Aec3RenderQueueItemVerifier>*
156 render_transfer_queue_; 159 render_transfer_queue_;
(...skipping 14 matching lines...) Expand all
171 num_bands_(num_bands), 174 num_bands_(num_bands),
172 render_highpass_filter_(std::move(render_highpass_filter)), 175 render_highpass_filter_(std::move(render_highpass_filter)),
173 render_queue_input_frame_(num_bands_, 176 render_queue_input_frame_(num_bands_,
174 std::vector<float>(frame_length_, 0.f)), 177 std::vector<float>(frame_length_, 0.f)),
175 render_transfer_queue_(render_transfer_queue) { 178 render_transfer_queue_(render_transfer_queue) {
176 RTC_DCHECK(data_dumper); 179 RTC_DCHECK(data_dumper);
177 } 180 }
178 181
179 EchoCanceller3::RenderWriter::~RenderWriter() = default; 182 EchoCanceller3::RenderWriter::~RenderWriter() = default;
180 183
181 bool EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) { 184 void EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) {
182 RTC_DCHECK_EQ(1, input->num_channels()); 185 RTC_DCHECK_EQ(1, input->num_channels());
183 RTC_DCHECK_EQ(frame_length_, input->num_frames_per_band()); 186 RTC_DCHECK_EQ(frame_length_, input->num_frames_per_band());
184 data_dumper_->DumpWav("aec3_render_input", frame_length_, 187 data_dumper_->DumpWav("aec3_render_input", frame_length_,
185 &input->channels_f()[0][0], 188 &input->split_bands_f(0)[0][0],
186 LowestBandRate(sample_rate_hz_), 1); 189 LowestBandRate(sample_rate_hz_), 1);
187 190
188 CopyLowestBandIntoFrame(input, num_bands_, frame_length_, 191 CopyBufferIntoFrame(input, num_bands_, frame_length_,
189 &render_queue_input_frame_); 192 &render_queue_input_frame_);
190 193
191 if (render_highpass_filter_) { 194 if (render_highpass_filter_) {
192 render_highpass_filter_->Process(render_queue_input_frame_[0]); 195 render_highpass_filter_->Process(render_queue_input_frame_[0]);
193 } 196 }
194 197
195 return render_transfer_queue_->Insert(&render_queue_input_frame_); 198 // TODO(peah): Change this two-step static cast once the CL for handling the
199 // bug causing this to fail in cc has landed.
200 bool result = render_transfer_queue_->Insert(&render_queue_input_frame_);
201 static_cast<void>(result);
196 } 202 }
197 203
198 int EchoCanceller3::instance_count_ = 0; 204 int EchoCanceller3::instance_count_ = 0;
199 205
200 EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter) 206 EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter)
201 : EchoCanceller3(sample_rate_hz, 207 : EchoCanceller3(sample_rate_hz,
202 use_highpass_filter, 208 use_highpass_filter,
203 std::unique_ptr<BlockProcessor>( 209 std::unique_ptr<BlockProcessor>(
204 BlockProcessor::Create(sample_rate_hz))) {} 210 BlockProcessor::Create(sample_rate_hz))) {}
205 EchoCanceller3::EchoCanceller3(int sample_rate_hz, 211 EchoCanceller3::EchoCanceller3(int sample_rate_hz,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 new RenderWriter(data_dumper_.get(), &render_transfer_queue_, 250 new RenderWriter(data_dumper_.get(), &render_transfer_queue_,
245 std::move(render_highpass_filter), sample_rate_hz_, 251 std::move(render_highpass_filter), sample_rate_hz_,
246 frame_length_, num_bands_)); 252 frame_length_, num_bands_));
247 253
248 RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000); 254 RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000);
249 RTC_DCHECK_GE(kMaxNumBands, num_bands_); 255 RTC_DCHECK_GE(kMaxNumBands, num_bands_);
250 } 256 }
251 257
252 EchoCanceller3::~EchoCanceller3() = default; 258 EchoCanceller3::~EchoCanceller3() = default;
253 259
254 bool EchoCanceller3::AnalyzeRender(AudioBuffer* render) { 260 void EchoCanceller3::AnalyzeRender(AudioBuffer* render) {
255 RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_); 261 RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_);
256 RTC_DCHECK(render); 262 RTC_DCHECK(render);
263 data_dumper_->DumpRaw("aec3_call_order",
264 static_cast<int>(EchoCanceller3ApiCall::kRender));
265
257 return render_writer_->Insert(render); 266 return render_writer_->Insert(render);
258 } 267 }
259 268
260 void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) { 269 void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) {
261 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); 270 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
262 RTC_DCHECK(capture); 271 RTC_DCHECK(capture);
263 data_dumper_->DumpWav("aec3_capture_analyze_input", capture->num_frames(), 272 data_dumper_->DumpWav("aec3_capture_analyze_input", capture->num_frames(),
264 capture->channels_f()[0], sample_rate_hz_, 1); 273 capture->channels_f()[0], sample_rate_hz_, 1);
265 274
266 saturated_microphone_signal_ = false; 275 saturated_microphone_signal_ = false;
267 for (size_t k = 0; k < capture->num_channels(); ++k) { 276 for (size_t k = 0; k < capture->num_channels(); ++k) {
268 saturated_microphone_signal_ |= 277 saturated_microphone_signal_ |=
269 DetectSaturation(rtc::ArrayView<const float>(capture->channels_f()[k], 278 DetectSaturation(rtc::ArrayView<const float>(capture->channels_f()[k],
270 capture->num_frames())); 279 capture->num_frames()));
271 if (saturated_microphone_signal_) { 280 if (saturated_microphone_signal_) {
272 break; 281 break;
273 } 282 }
274 } 283 }
275 } 284 }
276 285
277 void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) { 286 void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) {
278 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); 287 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
279 RTC_DCHECK(capture); 288 RTC_DCHECK(capture);
280 RTC_DCHECK_EQ(1u, capture->num_channels()); 289 RTC_DCHECK_EQ(1u, capture->num_channels());
281 RTC_DCHECK_EQ(num_bands_, capture->num_bands()); 290 RTC_DCHECK_EQ(num_bands_, capture->num_bands());
282 RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band()); 291 RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band());
292 data_dumper_->DumpRaw("aec3_call_order",
293 static_cast<int>(EchoCanceller3ApiCall::kCapture));
283 294
284 rtc::ArrayView<float> capture_lower_band = 295 rtc::ArrayView<float> capture_lower_band =
285 rtc::ArrayView<float>(&capture->split_bands_f(0)[0][0], frame_length_); 296 rtc::ArrayView<float>(&capture->split_bands_f(0)[0][0], frame_length_);
286 297
287 data_dumper_->DumpWav("aec3_capture_input", capture_lower_band, 298 data_dumper_->DumpWav("aec3_capture_input", capture_lower_band,
288 LowestBandRate(sample_rate_hz_), 1); 299 LowestBandRate(sample_rate_hz_), 1);
289 300
290 const bool successful_buffering = EmptyRenderQueue(); 301 EmptyRenderQueue();
291 RTC_DCHECK(successful_buffering);
292 302
293 if (capture_highpass_filter_) { 303 if (capture_highpass_filter_) {
294 capture_highpass_filter_->Process(capture_lower_band); 304 capture_highpass_filter_->Process(capture_lower_band);
295 } 305 }
296 306
297 ProcessCaptureFrameContent( 307 ProcessCaptureFrameContent(
298 capture, level_change, saturated_microphone_signal_, 0, &capture_blocker_, 308 capture, level_change, saturated_microphone_signal_, 0, &capture_blocker_,
299 &output_framer_, block_processor_.get(), &block_, &sub_frame_view_); 309 &output_framer_, block_processor_.get(), &block_, &sub_frame_view_);
300 310
301 if (sample_rate_hz_ != 8000) { 311 if (sample_rate_hz_ != 8000) {
(...skipping 18 matching lines...) Expand all
320 ss << "{" 330 ss << "{"
321 << "enabled: " << (config.enabled ? "true" : "false") << "}"; 331 << "enabled: " << (config.enabled ? "true" : "false") << "}";
322 return ss.str(); 332 return ss.str();
323 } 333 }
324 334
325 bool EchoCanceller3::Validate( 335 bool EchoCanceller3::Validate(
326 const AudioProcessing::Config::EchoCanceller3& config) { 336 const AudioProcessing::Config::EchoCanceller3& config) {
327 return true; 337 return true;
328 } 338 }
329 339
330 bool EchoCanceller3::EmptyRenderQueue() { 340 void EchoCanceller3::EmptyRenderQueue() {
331 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); 341 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
332 bool successful_buffering = true;
333 bool frame_to_buffer = 342 bool frame_to_buffer =
334 render_transfer_queue_.Remove(&render_queue_output_frame_); 343 render_transfer_queue_.Remove(&render_queue_output_frame_);
335 while (frame_to_buffer) { 344 while (frame_to_buffer) {
336 successful_buffering = 345 BufferRenderFrameContent(&render_queue_output_frame_, 0, &render_blocker_,
337 BufferRenderFrameContent(&render_queue_output_frame_, 0, 346 block_processor_.get(), &block_, &sub_frame_view_);
338 &render_blocker_, block_processor_.get(),
339 &block_, &sub_frame_view_) &&
340 successful_buffering;
341 347
342 if (sample_rate_hz_ != 8000) { 348 if (sample_rate_hz_ != 8000) {
343 successful_buffering = 349 BufferRenderFrameContent(&render_queue_output_frame_, 1, &render_blocker_,
344 BufferRenderFrameContent(&render_queue_output_frame_, 1, 350 block_processor_.get(), &block_,
345 &render_blocker_, block_processor_.get(), 351 &sub_frame_view_);
346 &block_, &sub_frame_view_) &&
347 successful_buffering;
348 } 352 }
349 353
350 successful_buffering = 354 BufferRemainingRenderFrameContent(&render_blocker_, block_processor_.get(),
351 BufferRemainingRenderFrameContent(&render_blocker_, 355 &block_);
352 block_processor_.get(), &block_) &&
353 successful_buffering;
354 356
355 frame_to_buffer = 357 frame_to_buffer =
356 render_transfer_queue_.Remove(&render_queue_output_frame_); 358 render_transfer_queue_.Remove(&render_queue_output_frame_);
357 } 359 }
358 return successful_buffering;
359 } 360 }
360 361
361 } // namespace webrtc 362 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698