| 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 |