OLD | NEW |
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 Loading... |
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 Loading... |
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 static_cast<void>(render_transfer_queue_->Insert(&render_queue_input_frame_)); |
196 } | 199 } |
197 | 200 |
198 int EchoCanceller3::instance_count_ = 0; | 201 int EchoCanceller3::instance_count_ = 0; |
199 | 202 |
200 EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter) | 203 EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter) |
201 : EchoCanceller3(sample_rate_hz, | 204 : EchoCanceller3(sample_rate_hz, |
202 use_highpass_filter, | 205 use_highpass_filter, |
203 std::unique_ptr<BlockProcessor>( | 206 std::unique_ptr<BlockProcessor>( |
204 BlockProcessor::Create(sample_rate_hz))) {} | 207 BlockProcessor::Create(sample_rate_hz))) {} |
205 EchoCanceller3::EchoCanceller3(int sample_rate_hz, | 208 EchoCanceller3::EchoCanceller3(int sample_rate_hz, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 new RenderWriter(data_dumper_.get(), &render_transfer_queue_, | 247 new RenderWriter(data_dumper_.get(), &render_transfer_queue_, |
245 std::move(render_highpass_filter), sample_rate_hz_, | 248 std::move(render_highpass_filter), sample_rate_hz_, |
246 frame_length_, num_bands_)); | 249 frame_length_, num_bands_)); |
247 | 250 |
248 RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000); | 251 RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000); |
249 RTC_DCHECK_GE(kMaxNumBands, num_bands_); | 252 RTC_DCHECK_GE(kMaxNumBands, num_bands_); |
250 } | 253 } |
251 | 254 |
252 EchoCanceller3::~EchoCanceller3() = default; | 255 EchoCanceller3::~EchoCanceller3() = default; |
253 | 256 |
254 bool EchoCanceller3::AnalyzeRender(AudioBuffer* render) { | 257 void EchoCanceller3::AnalyzeRender(AudioBuffer* render) { |
255 RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_); | 258 RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_); |
256 RTC_DCHECK(render); | 259 RTC_DCHECK(render); |
| 260 data_dumper_->DumpRaw("aec3_call_order", |
| 261 static_cast<int>(EchoCanceller3ApiCall::kRender)); |
| 262 |
257 return render_writer_->Insert(render); | 263 return render_writer_->Insert(render); |
258 } | 264 } |
259 | 265 |
260 void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) { | 266 void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) { |
261 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); | 267 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); |
262 RTC_DCHECK(capture); | 268 RTC_DCHECK(capture); |
263 data_dumper_->DumpWav("aec3_capture_analyze_input", capture->num_frames(), | 269 data_dumper_->DumpWav("aec3_capture_analyze_input", capture->num_frames(), |
264 capture->channels_f()[0], sample_rate_hz_, 1); | 270 capture->channels_f()[0], sample_rate_hz_, 1); |
265 | 271 |
266 saturated_microphone_signal_ = false; | 272 saturated_microphone_signal_ = false; |
267 for (size_t k = 0; k < capture->num_channels(); ++k) { | 273 for (size_t k = 0; k < capture->num_channels(); ++k) { |
268 saturated_microphone_signal_ |= | 274 saturated_microphone_signal_ |= |
269 DetectSaturation(rtc::ArrayView<const float>(capture->channels_f()[k], | 275 DetectSaturation(rtc::ArrayView<const float>(capture->channels_f()[k], |
270 capture->num_frames())); | 276 capture->num_frames())); |
271 if (saturated_microphone_signal_) { | 277 if (saturated_microphone_signal_) { |
272 break; | 278 break; |
273 } | 279 } |
274 } | 280 } |
275 } | 281 } |
276 | 282 |
277 void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) { | 283 void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) { |
278 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); | 284 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); |
279 RTC_DCHECK(capture); | 285 RTC_DCHECK(capture); |
280 RTC_DCHECK_EQ(1u, capture->num_channels()); | 286 RTC_DCHECK_EQ(1u, capture->num_channels()); |
281 RTC_DCHECK_EQ(num_bands_, capture->num_bands()); | 287 RTC_DCHECK_EQ(num_bands_, capture->num_bands()); |
282 RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band()); | 288 RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band()); |
| 289 data_dumper_->DumpRaw("aec3_call_order", |
| 290 static_cast<int>(EchoCanceller3ApiCall::kCapture)); |
283 | 291 |
284 rtc::ArrayView<float> capture_lower_band = | 292 rtc::ArrayView<float> capture_lower_band = |
285 rtc::ArrayView<float>(&capture->split_bands_f(0)[0][0], frame_length_); | 293 rtc::ArrayView<float>(&capture->split_bands_f(0)[0][0], frame_length_); |
286 | 294 |
287 data_dumper_->DumpWav("aec3_capture_input", capture_lower_band, | 295 data_dumper_->DumpWav("aec3_capture_input", capture_lower_band, |
288 LowestBandRate(sample_rate_hz_), 1); | 296 LowestBandRate(sample_rate_hz_), 1); |
289 | 297 |
290 const bool successful_buffering = EmptyRenderQueue(); | 298 EmptyRenderQueue(); |
291 RTC_DCHECK(successful_buffering); | |
292 | 299 |
293 if (capture_highpass_filter_) { | 300 if (capture_highpass_filter_) { |
294 capture_highpass_filter_->Process(capture_lower_band); | 301 capture_highpass_filter_->Process(capture_lower_band); |
295 } | 302 } |
296 | 303 |
297 ProcessCaptureFrameContent( | 304 ProcessCaptureFrameContent( |
298 capture, level_change, saturated_microphone_signal_, 0, &capture_blocker_, | 305 capture, level_change, saturated_microphone_signal_, 0, &capture_blocker_, |
299 &output_framer_, block_processor_.get(), &block_, &sub_frame_view_); | 306 &output_framer_, block_processor_.get(), &block_, &sub_frame_view_); |
300 | 307 |
301 if (sample_rate_hz_ != 8000) { | 308 if (sample_rate_hz_ != 8000) { |
(...skipping 18 matching lines...) Expand all Loading... |
320 ss << "{" | 327 ss << "{" |
321 << "enabled: " << (config.enabled ? "true" : "false") << "}"; | 328 << "enabled: " << (config.enabled ? "true" : "false") << "}"; |
322 return ss.str(); | 329 return ss.str(); |
323 } | 330 } |
324 | 331 |
325 bool EchoCanceller3::Validate( | 332 bool EchoCanceller3::Validate( |
326 const AudioProcessing::Config::EchoCanceller3& config) { | 333 const AudioProcessing::Config::EchoCanceller3& config) { |
327 return true; | 334 return true; |
328 } | 335 } |
329 | 336 |
330 bool EchoCanceller3::EmptyRenderQueue() { | 337 void EchoCanceller3::EmptyRenderQueue() { |
331 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); | 338 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); |
332 bool successful_buffering = true; | |
333 bool frame_to_buffer = | 339 bool frame_to_buffer = |
334 render_transfer_queue_.Remove(&render_queue_output_frame_); | 340 render_transfer_queue_.Remove(&render_queue_output_frame_); |
335 while (frame_to_buffer) { | 341 while (frame_to_buffer) { |
336 successful_buffering = | 342 BufferRenderFrameContent(&render_queue_output_frame_, 0, &render_blocker_, |
337 BufferRenderFrameContent(&render_queue_output_frame_, 0, | 343 block_processor_.get(), &block_, &sub_frame_view_); |
338 &render_blocker_, block_processor_.get(), | |
339 &block_, &sub_frame_view_) && | |
340 successful_buffering; | |
341 | 344 |
342 if (sample_rate_hz_ != 8000) { | 345 if (sample_rate_hz_ != 8000) { |
343 successful_buffering = | 346 BufferRenderFrameContent(&render_queue_output_frame_, 1, &render_blocker_, |
344 BufferRenderFrameContent(&render_queue_output_frame_, 1, | 347 block_processor_.get(), &block_, |
345 &render_blocker_, block_processor_.get(), | 348 &sub_frame_view_); |
346 &block_, &sub_frame_view_) && | |
347 successful_buffering; | |
348 } | 349 } |
349 | 350 |
350 successful_buffering = | 351 BufferRemainingRenderFrameContent(&render_blocker_, block_processor_.get(), |
351 BufferRemainingRenderFrameContent(&render_blocker_, | 352 &block_); |
352 block_processor_.get(), &block_) && | |
353 successful_buffering; | |
354 | 353 |
355 frame_to_buffer = | 354 frame_to_buffer = |
356 render_transfer_queue_.Remove(&render_queue_output_frame_); | 355 render_transfer_queue_.Remove(&render_queue_output_frame_); |
357 } | 356 } |
358 return successful_buffering; | |
359 } | 357 } |
360 | 358 |
361 } // namespace webrtc | 359 } // namespace webrtc |
OLD | NEW |