audio_processing_impl.cc (89461B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_processing/audio_processing_impl.h" 12 13 #include <algorithm> 14 #include <array> 15 #include <atomic> 16 #include <cstdint> 17 #include <cstdio> 18 #include <cstring> 19 #include <memory> 20 #include <optional> 21 #include <string> 22 #include <utility> 23 #include <vector> 24 25 #include "absl/base/nullability.h" 26 #include "absl/strings/string_view.h" 27 #include "api/array_view.h" 28 #include "api/audio/audio_processing.h" 29 #include "api/audio/audio_processing_statistics.h" 30 #include "api/audio/audio_view.h" 31 #include "api/audio/echo_canceller3_config.h" 32 #include "api/audio/echo_control.h" 33 #include "api/audio/neural_residual_echo_estimator.h" 34 #include "api/environment/environment.h" 35 #include "api/field_trials_view.h" 36 #include "api/scoped_refptr.h" 37 #include "api/task_queue/task_queue_base.h" 38 #include "common_audio/audio_converter.h" 39 #include "common_audio/include/audio_util.h" 40 #include "modules/audio_processing/aec3/echo_canceller3.h" 41 #include "modules/audio_processing/aec_dump/aec_dump_factory.h" 42 #include "modules/audio_processing/agc/agc_manager_direct.h" 43 #include "modules/audio_processing/agc/gain_control.h" 44 #include "modules/audio_processing/agc2/input_volume_controller.h" 45 #include "modules/audio_processing/agc2/input_volume_stats_reporter.h" 46 #include "modules/audio_processing/audio_buffer.h" 47 #include "modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h" 48 #include "modules/audio_processing/echo_control_mobile_impl.h" 49 #include "modules/audio_processing/gain_control_impl.h" 50 #include "modules/audio_processing/gain_controller2.h" 51 #include "modules/audio_processing/high_pass_filter.h" 52 #include "modules/audio_processing/include/aec_dump.h" 53 #include "modules/audio_processing/logging/apm_data_dumper.h" 54 #include "modules/audio_processing/ns/noise_suppressor.h" 55 #include "modules/audio_processing/ns/ns_config.h" 56 #include "modules/audio_processing/post_filter.h" 57 #include "modules/audio_processing/render_queue_item_verifier.h" 58 #include "modules/audio_processing/rms_level.h" 59 #include "rtc_base/checks.h" 60 #include "rtc_base/denormal_disabler.h" 61 #include "rtc_base/logging.h" 62 #include "rtc_base/swap_queue.h" 63 #include "rtc_base/synchronization/mutex.h" 64 #include "rtc_base/time_utils.h" 65 #include "rtc_base/trace_event.h" 66 #include "system_wrappers/include/metrics.h" 67 68 #define RETURN_ON_ERR(expr) \ 69 do { \ 70 int err = (expr); \ 71 if (err != kNoError) { \ 72 return err; \ 73 } \ 74 } while (0) 75 76 namespace webrtc { 77 78 namespace { 79 80 bool SampleRateSupportsMultiBand(int sample_rate_hz) { 81 return sample_rate_hz == AudioProcessing::kSampleRate32kHz || 82 sample_rate_hz == AudioProcessing::kSampleRate48kHz; 83 } 84 85 // Checks whether the high-pass filter should be done in the full-band. 86 bool EnforceSplitBandHpf(const FieldTrialsView& field_trials) { 87 return field_trials.IsEnabled("WebRTC-FullBandHpfKillSwitch"); 88 } 89 90 // Identify the native processing rate that best handles a sample rate. 91 int SuitableProcessRate(int minimum_rate, 92 int max_splitting_rate, 93 bool band_splitting_required) { 94 const int uppermost_native_rate = 95 band_splitting_required ? max_splitting_rate : 48000; 96 for (auto rate : {16000, 32000, 48000}) { 97 if (rate >= uppermost_native_rate) { 98 return uppermost_native_rate; 99 } 100 if (rate >= minimum_rate) { 101 return rate; 102 } 103 } 104 RTC_DCHECK_NOTREACHED(); 105 return uppermost_native_rate; 106 } 107 108 GainControl::Mode Agc1ConfigModeToInterfaceMode( 109 AudioProcessing::Config::GainController1::Mode mode) { 110 using Agc1Config = AudioProcessing::Config::GainController1; 111 switch (mode) { 112 case Agc1Config::kAdaptiveAnalog: 113 return GainControl::kAdaptiveAnalog; 114 case Agc1Config::kAdaptiveDigital: 115 return GainControl::kAdaptiveDigital; 116 case Agc1Config::kFixedDigital: 117 return GainControl::kFixedDigital; 118 } 119 RTC_CHECK_NOTREACHED(); 120 } 121 122 bool MinimizeProcessingForUnusedOutput(const FieldTrialsView& field_trials) { 123 return !field_trials.IsEnabled("WebRTC-MutedStateKillSwitch"); 124 } 125 126 // Maximum lengths that frame of samples being passed from the render side to 127 // the capture side can have (does not apply to AEC3). 128 const size_t kMaxAllowedValuesOfSamplesPerBand = 160; 129 const size_t kMaxAllowedValuesOfSamplesPerFrame = 480; 130 131 // Maximum number of frames to buffer in the render queue. 132 // TODO(peah): Decrease this once we properly handle hugely unbalanced 133 // reverse and forward call numbers. 134 const size_t kMaxNumFramesToBuffer = 100; 135 136 void PackRenderAudioBufferForEchoDetector(const AudioBuffer& audio, 137 std::vector<float>& packed_buffer) { 138 packed_buffer.clear(); 139 packed_buffer.insert(packed_buffer.end(), audio.channels_const()[0], 140 audio.channels_const()[0] + audio.num_frames()); 141 } 142 143 // Options for gracefully handling processing errors. 144 enum class FormatErrorOutputOption { 145 kOutputExactCopyOfInput, 146 kOutputBroadcastCopyOfFirstInputChannel, 147 kOutputSilence, 148 kDoNothing 149 }; 150 151 enum class AudioFormatValidity { 152 // Format is supported by APM. 153 kValidAndSupported, 154 // Format has a reasonable interpretation but is not supported. 155 kValidButUnsupportedSampleRate, 156 // The remaining enums values signal that the audio does not have a reasonable 157 // interpretation and cannot be used. 158 kInvalidSampleRate, 159 kInvalidChannelCount 160 }; 161 162 AudioFormatValidity ValidateAudioFormat(const StreamConfig& config) { 163 if (config.sample_rate_hz() < 0) 164 return AudioFormatValidity::kInvalidSampleRate; 165 if (config.num_channels() == 0) 166 return AudioFormatValidity::kInvalidChannelCount; 167 168 // Format has a reasonable interpretation, but may still be unsupported. 169 if (config.sample_rate_hz() < 8000 || 170 config.sample_rate_hz() > AudioBuffer::kMaxSampleRate) 171 return AudioFormatValidity::kValidButUnsupportedSampleRate; 172 173 // Format is fully supported. 174 return AudioFormatValidity::kValidAndSupported; 175 } 176 177 int AudioFormatValidityToErrorCode(AudioFormatValidity validity) { 178 switch (validity) { 179 case AudioFormatValidity::kValidAndSupported: 180 return AudioProcessing::kNoError; 181 case AudioFormatValidity::kValidButUnsupportedSampleRate: // fall-through 182 case AudioFormatValidity::kInvalidSampleRate: 183 return AudioProcessing::kBadSampleRateError; 184 case AudioFormatValidity::kInvalidChannelCount: 185 return AudioProcessing::kBadNumberChannelsError; 186 } 187 RTC_DCHECK(false); 188 } 189 190 // Returns an AudioProcessing::Error together with the best possible option for 191 // output audio content. 192 std::pair<int, FormatErrorOutputOption> ChooseErrorOutputOption( 193 const StreamConfig& input_config, 194 const StreamConfig& output_config) { 195 AudioFormatValidity input_validity = ValidateAudioFormat(input_config); 196 AudioFormatValidity output_validity = ValidateAudioFormat(output_config); 197 198 if (input_validity == AudioFormatValidity::kValidAndSupported && 199 output_validity == AudioFormatValidity::kValidAndSupported && 200 (output_config.num_channels() == 1 || 201 output_config.num_channels() == input_config.num_channels())) { 202 return {AudioProcessing::kNoError, FormatErrorOutputOption::kDoNothing}; 203 } 204 205 int error_code = AudioFormatValidityToErrorCode(input_validity); 206 if (error_code == AudioProcessing::kNoError) { 207 error_code = AudioFormatValidityToErrorCode(output_validity); 208 } 209 if (error_code == AudioProcessing::kNoError) { 210 // The individual formats are valid but there is some error - must be 211 // channel mismatch. 212 error_code = AudioProcessing::kBadNumberChannelsError; 213 } 214 215 FormatErrorOutputOption output_option; 216 if (output_validity != AudioFormatValidity::kValidAndSupported && 217 output_validity != AudioFormatValidity::kValidButUnsupportedSampleRate) { 218 // The output format is uninterpretable: cannot do anything. 219 output_option = FormatErrorOutputOption::kDoNothing; 220 } else if (input_validity != AudioFormatValidity::kValidAndSupported && 221 input_validity != 222 AudioFormatValidity::kValidButUnsupportedSampleRate) { 223 // The input format is uninterpretable: cannot use it, must output silence. 224 output_option = FormatErrorOutputOption::kOutputSilence; 225 } else if (input_config.sample_rate_hz() != output_config.sample_rate_hz()) { 226 // Sample rates do not match: Cannot copy input into output, output silence. 227 // Note: If the sample rates are in a supported range, we could resample. 228 // However, that would significantly increase complexity of this error 229 // handling code. 230 output_option = FormatErrorOutputOption::kOutputSilence; 231 } else if (input_config.num_channels() != output_config.num_channels()) { 232 // Channel counts do not match: We cannot easily map input channels to 233 // output channels. 234 output_option = 235 FormatErrorOutputOption::kOutputBroadcastCopyOfFirstInputChannel; 236 } else { 237 // The formats match exactly. 238 RTC_DCHECK(input_config == output_config); 239 output_option = FormatErrorOutputOption::kOutputExactCopyOfInput; 240 } 241 return std::make_pair(error_code, output_option); 242 } 243 244 // Checks if the audio format is supported. If not, the output is populated in a 245 // best-effort manner and an APM error code is returned. 246 int HandleUnsupportedAudioFormats(const int16_t* const src, 247 const StreamConfig& input_config, 248 const StreamConfig& output_config, 249 int16_t* const dest) { 250 RTC_DCHECK(src); 251 RTC_DCHECK(dest); 252 253 auto [error_code, output_option] = 254 ChooseErrorOutputOption(input_config, output_config); 255 if (error_code == AudioProcessing::kNoError) 256 return AudioProcessing::kNoError; 257 258 const size_t num_output_channels = output_config.num_channels(); 259 switch (output_option) { 260 case FormatErrorOutputOption::kOutputSilence: 261 memset(dest, 0, output_config.num_samples() * sizeof(int16_t)); 262 break; 263 case FormatErrorOutputOption::kOutputBroadcastCopyOfFirstInputChannel: 264 for (size_t i = 0; i < output_config.num_frames(); ++i) { 265 int16_t sample = src[input_config.num_channels() * i]; 266 for (size_t ch = 0; ch < num_output_channels; ++ch) { 267 dest[ch + num_output_channels * i] = sample; 268 } 269 } 270 break; 271 case FormatErrorOutputOption::kOutputExactCopyOfInput: 272 memcpy(dest, src, output_config.num_samples() * sizeof(int16_t)); 273 break; 274 case FormatErrorOutputOption::kDoNothing: 275 break; 276 } 277 return error_code; 278 } 279 280 // Checks if the audio format is supported. If not, the output is populated in a 281 // best-effort manner and an APM error code is returned. 282 int HandleUnsupportedAudioFormats(const float* const* src, 283 const StreamConfig& input_config, 284 const StreamConfig& output_config, 285 float* const* dest) { 286 RTC_DCHECK(src); 287 RTC_DCHECK(dest); 288 for (size_t i = 0; i < input_config.num_channels(); ++i) { 289 RTC_DCHECK(src[i]); 290 } 291 for (size_t i = 0; i < output_config.num_channels(); ++i) { 292 RTC_DCHECK(dest[i]); 293 } 294 295 auto [error_code, output_option] = 296 ChooseErrorOutputOption(input_config, output_config); 297 if (error_code == AudioProcessing::kNoError) 298 return AudioProcessing::kNoError; 299 300 const size_t num_output_channels = output_config.num_channels(); 301 switch (output_option) { 302 case FormatErrorOutputOption::kOutputSilence: 303 for (size_t ch = 0; ch < num_output_channels; ++ch) { 304 memset(dest[ch], 0, output_config.num_frames() * sizeof(float)); 305 } 306 break; 307 case FormatErrorOutputOption::kOutputBroadcastCopyOfFirstInputChannel: 308 for (size_t ch = 0; ch < num_output_channels; ++ch) { 309 memcpy(dest[ch], src[0], output_config.num_frames() * sizeof(float)); 310 } 311 break; 312 case FormatErrorOutputOption::kOutputExactCopyOfInput: 313 for (size_t ch = 0; ch < num_output_channels; ++ch) { 314 memcpy(dest[ch], src[ch], output_config.num_frames() * sizeof(float)); 315 } 316 break; 317 case FormatErrorOutputOption::kDoNothing: 318 break; 319 } 320 return error_code; 321 } 322 323 using DownmixMethod = AudioProcessing::Config::Pipeline::DownmixMethod; 324 325 void SetDownmixMethod(AudioBuffer& buffer, DownmixMethod method) { 326 switch (method) { 327 case DownmixMethod::kAverageChannels: 328 buffer.set_downmixing_by_averaging(); 329 break; 330 case DownmixMethod::kUseFirstChannel: 331 buffer.set_downmixing_to_specific_channel(/*channel=*/0); 332 break; 333 } 334 } 335 336 constexpr int kUnspecifiedDataDumpInputVolume = -100; 337 338 } // namespace 339 340 // Throughout webrtc, it's assumed that success is represented by zero. 341 static_assert(AudioProcessing::kNoError == 0, "kNoError must be zero"); 342 343 AudioProcessingImpl::SubmoduleStates::SubmoduleStates( 344 bool capture_post_processor_enabled, 345 bool render_pre_processor_enabled, 346 bool capture_analyzer_enabled) 347 : capture_post_processor_enabled_(capture_post_processor_enabled), 348 render_pre_processor_enabled_(render_pre_processor_enabled), 349 capture_analyzer_enabled_(capture_analyzer_enabled) {} 350 351 bool AudioProcessingImpl::SubmoduleStates::Update( 352 bool high_pass_filter_enabled, 353 bool mobile_echo_controller_enabled, 354 bool noise_suppressor_enabled, 355 bool adaptive_gain_controller_enabled, 356 bool gain_controller2_enabled, 357 bool gain_adjustment_enabled, 358 bool echo_controller_enabled) { 359 bool changed = false; 360 changed |= (high_pass_filter_enabled != high_pass_filter_enabled_); 361 changed |= 362 (mobile_echo_controller_enabled != mobile_echo_controller_enabled_); 363 changed |= (noise_suppressor_enabled != noise_suppressor_enabled_); 364 changed |= 365 (adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_); 366 changed |= (gain_controller2_enabled != gain_controller2_enabled_); 367 changed |= (gain_adjustment_enabled != gain_adjustment_enabled_); 368 changed |= (echo_controller_enabled != echo_controller_enabled_); 369 if (changed) { 370 high_pass_filter_enabled_ = high_pass_filter_enabled; 371 mobile_echo_controller_enabled_ = mobile_echo_controller_enabled; 372 noise_suppressor_enabled_ = noise_suppressor_enabled; 373 adaptive_gain_controller_enabled_ = adaptive_gain_controller_enabled; 374 gain_controller2_enabled_ = gain_controller2_enabled; 375 gain_adjustment_enabled_ = gain_adjustment_enabled; 376 echo_controller_enabled_ = echo_controller_enabled; 377 } 378 379 changed |= first_update_; 380 first_update_ = false; 381 return changed; 382 } 383 384 bool AudioProcessingImpl::SubmoduleStates::CaptureMultiBandSubModulesActive() 385 const { 386 return CaptureMultiBandProcessingPresent(); 387 } 388 389 bool AudioProcessingImpl::SubmoduleStates::CaptureMultiBandProcessingPresent() 390 const { 391 // If echo controller is present, assume it performs active processing. 392 return CaptureMultiBandProcessingActive(/*ec_processing_active=*/true); 393 } 394 395 bool AudioProcessingImpl::SubmoduleStates::CaptureMultiBandProcessingActive( 396 bool ec_processing_active) const { 397 return high_pass_filter_enabled_ || mobile_echo_controller_enabled_ || 398 noise_suppressor_enabled_ || adaptive_gain_controller_enabled_ || 399 (echo_controller_enabled_ && ec_processing_active); 400 } 401 402 bool AudioProcessingImpl::SubmoduleStates::CaptureFullBandProcessingActive() 403 const { 404 return gain_controller2_enabled_ || capture_post_processor_enabled_ || 405 gain_adjustment_enabled_; 406 } 407 408 bool AudioProcessingImpl::SubmoduleStates::CaptureAnalyzerActive() const { 409 return capture_analyzer_enabled_; 410 } 411 412 bool AudioProcessingImpl::SubmoduleStates::RenderMultiBandSubModulesActive() 413 const { 414 return RenderMultiBandProcessingActive() || mobile_echo_controller_enabled_ || 415 adaptive_gain_controller_enabled_ || echo_controller_enabled_; 416 } 417 418 bool AudioProcessingImpl::SubmoduleStates::RenderFullBandProcessingActive() 419 const { 420 return render_pre_processor_enabled_; 421 } 422 423 bool AudioProcessingImpl::SubmoduleStates::RenderMultiBandProcessingActive() 424 const { 425 return false; 426 } 427 428 bool AudioProcessingImpl::SubmoduleStates::HighPassFilteringRequired() const { 429 return high_pass_filter_enabled_ || mobile_echo_controller_enabled_ || 430 noise_suppressor_enabled_; 431 } 432 433 AudioProcessingImpl::AudioProcessingImpl(const Environment& env) 434 : AudioProcessingImpl(env, 435 /*config=*/{}, 436 /*echo_canceller_config=*/std::nullopt, 437 /*echo_canceller_multichannel_config=*/std::nullopt, 438 /*capture_post_processor=*/nullptr, 439 /*render_pre_processor=*/nullptr, 440 /*echo_control_factory=*/nullptr, 441 /*echo_detector=*/nullptr, 442 /*capture_analyzer=*/nullptr, 443 /*neural_residual_echo_estimator=*/nullptr) {} 444 445 std::atomic<int> AudioProcessingImpl::instance_count_(0); 446 447 AudioProcessingImpl::AudioProcessingImpl( 448 const Environment& env, 449 const AudioProcessing::Config& config, 450 std::optional<EchoCanceller3Config> echo_canceller_config, 451 std::optional<EchoCanceller3Config> echo_canceller_multichannel_config, 452 std::unique_ptr<CustomProcessing> capture_post_processor, 453 std::unique_ptr<CustomProcessing> render_pre_processor, 454 std::unique_ptr<EchoControlFactory> echo_control_factory, 455 scoped_refptr<EchoDetector> echo_detector, 456 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer, 457 std::unique_ptr<NeuralResidualEchoEstimator> neural_residual_echo_estimator) 458 : env_(env), 459 data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)), 460 capture_runtime_settings_(RuntimeSettingQueueSize()), 461 render_runtime_settings_(RuntimeSettingQueueSize()), 462 capture_runtime_settings_enqueuer_(&capture_runtime_settings_), 463 render_runtime_settings_enqueuer_(&render_runtime_settings_), 464 echo_control_factory_(std::move(echo_control_factory)), 465 config_(config), 466 echo_canceller_config_(echo_canceller_config), 467 echo_canceller_multichannel_config_(echo_canceller_multichannel_config), 468 submodule_states_(!!capture_post_processor, 469 !!render_pre_processor, 470 !!capture_analyzer), 471 submodules_(std::move(capture_post_processor), 472 std::move(render_pre_processor), 473 std::move(echo_detector), 474 std::move(capture_analyzer), 475 std::move(neural_residual_echo_estimator)), 476 constants_(!env.field_trials().IsEnabled( 477 "WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"), 478 !env.field_trials().IsEnabled( 479 "WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch"), 480 EnforceSplitBandHpf(env.field_trials()), 481 MinimizeProcessingForUnusedOutput(env.field_trials())), 482 capture_(), 483 capture_nonlocked_(), 484 applied_input_volume_stats_reporter_( 485 InputVolumeStatsReporter::InputVolumeType::kApplied), 486 recommended_input_volume_stats_reporter_( 487 InputVolumeStatsReporter::InputVolumeType::kRecommended) { 488 RTC_LOG(LS_INFO) << "Injected APM submodules:" 489 "\nEcho control factory: " 490 << !!echo_control_factory_ 491 << "\nEcho detector: " << !!submodules_.echo_detector 492 << "\nCapture analyzer: " << !!submodules_.capture_analyzer 493 << "\nCapture post processor: " 494 << !!submodules_.capture_post_processor 495 << "\nRender pre processor: " 496 << !!submodules_.render_pre_processor 497 << "\nNeural residual echo estimator " 498 << !!submodules_.neural_residual_echo_estimator; 499 if (!DenormalDisabler::IsSupported()) { 500 RTC_LOG(LS_INFO) << "Denormal disabler unsupported"; 501 } 502 503 RTC_LOG(LS_INFO) << "AudioProcessing: " << config_.ToString(); 504 505 // Mark Echo Controller enabled if a factory is injected. 506 capture_nonlocked_.echo_controller_enabled = 507 static_cast<bool>(echo_control_factory_); 508 509 Initialize(); 510 } 511 512 AudioProcessingImpl::~AudioProcessingImpl() = default; 513 514 int AudioProcessingImpl::Initialize() { 515 // Run in a single-threaded manner during initialization. 516 MutexLock lock_render(&mutex_render_); 517 MutexLock lock_capture(&mutex_capture_); 518 InitializeLocked(); 519 return kNoError; 520 } 521 522 int AudioProcessingImpl::Initialize(const ProcessingConfig& processing_config) { 523 // Run in a single-threaded manner during initialization. 524 MutexLock lock_render(&mutex_render_); 525 MutexLock lock_capture(&mutex_capture_); 526 InitializeLocked(processing_config); 527 return kNoError; 528 } 529 530 void AudioProcessingImpl::MaybeInitializeRender( 531 const StreamConfig& input_config, 532 const StreamConfig& output_config) { 533 ProcessingConfig processing_config = formats_.api_format; 534 processing_config.reverse_input_stream() = input_config; 535 processing_config.reverse_output_stream() = output_config; 536 537 if (processing_config == formats_.api_format) { 538 return; 539 } 540 541 MutexLock lock_capture(&mutex_capture_); 542 InitializeLocked(processing_config); 543 } 544 545 void AudioProcessingImpl::InitializeLocked() { 546 UpdateActiveSubmoduleStates(); 547 548 const int render_audiobuffer_sample_rate_hz = 549 formats_.api_format.reverse_output_stream().num_frames() == 0 550 ? formats_.render_processing_format.sample_rate_hz() 551 : formats_.api_format.reverse_output_stream().sample_rate_hz(); 552 if (formats_.api_format.reverse_input_stream().num_channels() > 0) { 553 render_.render_audio.reset(new AudioBuffer( 554 formats_.api_format.reverse_input_stream().sample_rate_hz(), 555 formats_.api_format.reverse_input_stream().num_channels(), 556 formats_.render_processing_format.sample_rate_hz(), 557 formats_.render_processing_format.num_channels(), 558 render_audiobuffer_sample_rate_hz, 559 formats_.render_processing_format.num_channels())); 560 if (formats_.api_format.reverse_input_stream() != 561 formats_.api_format.reverse_output_stream()) { 562 render_.render_converter = AudioConverter::Create( 563 formats_.api_format.reverse_input_stream().num_channels(), 564 formats_.api_format.reverse_input_stream().num_frames(), 565 formats_.api_format.reverse_output_stream().num_channels(), 566 formats_.api_format.reverse_output_stream().num_frames()); 567 } else { 568 render_.render_converter.reset(nullptr); 569 } 570 } else { 571 render_.render_audio.reset(nullptr); 572 render_.render_converter.reset(nullptr); 573 } 574 575 capture_.capture_audio.reset(new AudioBuffer( 576 formats_.api_format.input_stream().sample_rate_hz(), 577 formats_.api_format.input_stream().num_channels(), 578 capture_nonlocked_.capture_processing_format.sample_rate_hz(), 579 formats_.api_format.output_stream().num_channels(), 580 formats_.api_format.output_stream().sample_rate_hz(), 581 formats_.api_format.output_stream().num_channels())); 582 SetDownmixMethod(*capture_.capture_audio, 583 config_.pipeline.capture_downmix_method); 584 585 if (capture_nonlocked_.capture_processing_format.sample_rate_hz() < 586 formats_.api_format.output_stream().sample_rate_hz() && 587 formats_.api_format.output_stream().sample_rate_hz() == 48000) { 588 capture_.capture_fullband_audio.reset( 589 new AudioBuffer(formats_.api_format.input_stream().sample_rate_hz(), 590 formats_.api_format.input_stream().num_channels(), 591 formats_.api_format.output_stream().sample_rate_hz(), 592 formats_.api_format.output_stream().num_channels(), 593 formats_.api_format.output_stream().sample_rate_hz(), 594 formats_.api_format.output_stream().num_channels())); 595 SetDownmixMethod(*capture_.capture_fullband_audio, 596 config_.pipeline.capture_downmix_method); 597 } else { 598 capture_.capture_fullband_audio.reset(); 599 } 600 601 AllocateRenderQueue(); 602 603 InitializeGainController1(); 604 InitializeHighPassFilter(true); 605 InitializeResidualEchoDetector(); 606 InitializeEchoController(); 607 InitializeGainController2(); 608 InitializeNoiseSuppressor(); 609 InitializeAnalyzer(); 610 InitializePostProcessor(); 611 InitializePreProcessor(); 612 InitializeCaptureLevelsAdjuster(); 613 614 if (aec_dump_) { 615 aec_dump_->WriteInitMessage(formats_.api_format, TimeUTCMillis()); 616 } 617 } 618 619 void AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) { 620 UpdateActiveSubmoduleStates(); 621 622 formats_.api_format = config; 623 624 // Choose maximum rate to use for the split filtering. 625 RTC_DCHECK(config_.pipeline.maximum_internal_processing_rate == 48000 || 626 config_.pipeline.maximum_internal_processing_rate == 32000); 627 int max_splitting_rate = 48000; 628 if (config_.pipeline.maximum_internal_processing_rate == 32000) { 629 max_splitting_rate = config_.pipeline.maximum_internal_processing_rate; 630 } 631 632 int capture_processing_rate = SuitableProcessRate( 633 std::min(formats_.api_format.input_stream().sample_rate_hz(), 634 formats_.api_format.output_stream().sample_rate_hz()), 635 max_splitting_rate, 636 submodule_states_.CaptureMultiBandSubModulesActive() || 637 submodule_states_.RenderMultiBandSubModulesActive()); 638 RTC_DCHECK_NE(8000, capture_processing_rate); 639 640 capture_nonlocked_.capture_processing_format = 641 StreamConfig(capture_processing_rate); 642 643 int render_processing_rate; 644 if (!capture_nonlocked_.echo_controller_enabled) { 645 render_processing_rate = SuitableProcessRate( 646 std::min(formats_.api_format.reverse_input_stream().sample_rate_hz(), 647 formats_.api_format.reverse_output_stream().sample_rate_hz()), 648 max_splitting_rate, 649 submodule_states_.CaptureMultiBandSubModulesActive() || 650 submodule_states_.RenderMultiBandSubModulesActive()); 651 } else { 652 render_processing_rate = capture_processing_rate; 653 } 654 655 // If the forward sample rate is 8 kHz, the render stream is also processed 656 // at this rate. 657 if (capture_nonlocked_.capture_processing_format.sample_rate_hz() == 658 kSampleRate8kHz) { 659 render_processing_rate = kSampleRate8kHz; 660 } else { 661 render_processing_rate = 662 std::max(render_processing_rate, static_cast<int>(kSampleRate16kHz)); 663 } 664 665 RTC_DCHECK_NE(8000, render_processing_rate); 666 667 if (submodule_states_.RenderMultiBandSubModulesActive()) { 668 // By default, downmix the render stream to mono for analysis. This has been 669 // demonstrated to work well for AEC in most practical scenarios. 670 const bool multi_channel_render = config_.pipeline.multi_channel_render && 671 constants_.multi_channel_render_support; 672 int render_processing_num_channels = 673 multi_channel_render 674 ? formats_.api_format.reverse_input_stream().num_channels() 675 : 1; 676 formats_.render_processing_format = 677 StreamConfig(render_processing_rate, render_processing_num_channels); 678 } else { 679 formats_.render_processing_format = StreamConfig( 680 formats_.api_format.reverse_input_stream().sample_rate_hz(), 681 formats_.api_format.reverse_input_stream().num_channels()); 682 } 683 684 if (capture_nonlocked_.capture_processing_format.sample_rate_hz() == 685 kSampleRate32kHz || 686 capture_nonlocked_.capture_processing_format.sample_rate_hz() == 687 kSampleRate48kHz) { 688 capture_nonlocked_.split_rate = kSampleRate16kHz; 689 } else { 690 capture_nonlocked_.split_rate = 691 capture_nonlocked_.capture_processing_format.sample_rate_hz(); 692 } 693 694 InitializeLocked(); 695 } 696 697 void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { 698 // Run in a single-threaded manner when applying the settings. 699 MutexLock lock_render(&mutex_render_); 700 MutexLock lock_capture(&mutex_capture_); 701 702 RTC_LOG(LS_INFO) << "AudioProcessing::ApplyConfig: " << config.ToString(); 703 704 const bool pipeline_config_changed = 705 config_.pipeline.multi_channel_render != 706 config.pipeline.multi_channel_render || 707 config_.pipeline.multi_channel_capture != 708 config.pipeline.multi_channel_capture || 709 config_.pipeline.maximum_internal_processing_rate != 710 config.pipeline.maximum_internal_processing_rate || 711 config_.pipeline.capture_downmix_method != 712 config.pipeline.capture_downmix_method; 713 714 const bool aec_config_changed = 715 config_.echo_canceller.enabled != config.echo_canceller.enabled || 716 config_.echo_canceller.mobile_mode != config.echo_canceller.mobile_mode; 717 718 const bool agc1_config_changed = 719 config_.gain_controller1 != config.gain_controller1; 720 721 const bool agc2_config_changed = 722 config_.gain_controller2 != config.gain_controller2; 723 724 const bool ns_config_changed = 725 config_.noise_suppression.enabled != config.noise_suppression.enabled || 726 config_.noise_suppression.level != config.noise_suppression.level; 727 728 const bool pre_amplifier_config_changed = 729 config_.pre_amplifier.enabled != config.pre_amplifier.enabled || 730 config_.pre_amplifier.fixed_gain_factor != 731 config.pre_amplifier.fixed_gain_factor; 732 733 const bool gain_adjustment_config_changed = 734 config_.capture_level_adjustment != config.capture_level_adjustment; 735 736 config_ = config; 737 738 if (aec_config_changed) { 739 InitializeEchoController(); 740 } 741 742 if (ns_config_changed) { 743 InitializeNoiseSuppressor(); 744 } 745 746 InitializeHighPassFilter(false); 747 748 if (agc1_config_changed) { 749 InitializeGainController1(); 750 } 751 752 const bool config_ok = GainController2::Validate(config_.gain_controller2); 753 if (!config_ok) { 754 RTC_LOG(LS_ERROR) 755 << "Invalid Gain Controller 2 config; using the default config."; 756 config_.gain_controller2 = AudioProcessing::Config::GainController2(); 757 } 758 759 if (agc2_config_changed) { 760 InitializeGainController2(); 761 } 762 763 if (pre_amplifier_config_changed || gain_adjustment_config_changed) { 764 InitializeCaptureLevelsAdjuster(); 765 } 766 767 // Reinitialization must happen after all submodule configuration to avoid 768 // additional reinitializations on the next capture / render processing call. 769 if (pipeline_config_changed) { 770 InitializeLocked(formats_.api_format); 771 } 772 } 773 774 int AudioProcessingImpl::proc_sample_rate_hz() const { 775 // Used as callback from submodules, hence locking is not allowed. 776 return capture_nonlocked_.capture_processing_format.sample_rate_hz(); 777 } 778 779 int AudioProcessingImpl::proc_fullband_sample_rate_hz() const { 780 return capture_.capture_fullband_audio 781 ? capture_.capture_fullband_audio->num_frames() * 100 782 : capture_nonlocked_.capture_processing_format.sample_rate_hz(); 783 } 784 785 int AudioProcessingImpl::proc_split_sample_rate_hz() const { 786 // Used as callback from submodules, hence locking is not allowed. 787 return capture_nonlocked_.split_rate; 788 } 789 790 size_t AudioProcessingImpl::num_reverse_channels() const { 791 // Used as callback from submodules, hence locking is not allowed. 792 return formats_.render_processing_format.num_channels(); 793 } 794 795 size_t AudioProcessingImpl::num_input_channels() const { 796 // Used as callback from submodules, hence locking is not allowed. 797 return formats_.api_format.input_stream().num_channels(); 798 } 799 800 size_t AudioProcessingImpl::num_proc_channels() const { 801 // Used as callback from submodules, hence locking is not allowed. 802 const bool multi_channel_capture = config_.pipeline.multi_channel_capture && 803 constants_.multi_channel_capture_support; 804 if (capture_nonlocked_.echo_controller_enabled && !multi_channel_capture) { 805 return 1; 806 } 807 return num_output_channels(); 808 } 809 810 size_t AudioProcessingImpl::num_output_channels() const { 811 // Used as callback from submodules, hence locking is not allowed. 812 return formats_.api_format.output_stream().num_channels(); 813 } 814 815 void AudioProcessingImpl::set_output_will_be_muted(bool muted) { 816 MutexLock lock(&mutex_capture_); 817 HandleCaptureOutputUsedSetting(!muted); 818 } 819 820 void AudioProcessingImpl::HandleCaptureOutputUsedSetting( 821 bool capture_output_used) { 822 capture_.capture_output_used = 823 capture_output_used || !constants_.minimize_processing_for_unused_output; 824 825 if (submodules_.agc_manager) { 826 submodules_.agc_manager->HandleCaptureOutputUsedChange( 827 capture_.capture_output_used); 828 } 829 if (submodules_.echo_controller) { 830 submodules_.echo_controller->SetCaptureOutputUsage( 831 capture_.capture_output_used); 832 } 833 if (submodules_.noise_suppressor) { 834 submodules_.noise_suppressor->SetCaptureOutputUsage( 835 capture_.capture_output_used); 836 } 837 if (submodules_.gain_controller2) { 838 submodules_.gain_controller2->SetCaptureOutputUsed( 839 capture_.capture_output_used); 840 } 841 } 842 843 void AudioProcessingImpl::SetRuntimeSetting(RuntimeSetting setting) { 844 PostRuntimeSetting(setting); 845 } 846 847 bool AudioProcessingImpl::PostRuntimeSetting(RuntimeSetting setting) { 848 switch (setting.type()) { 849 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting: 850 case RuntimeSetting::Type::kPlayoutAudioDeviceChange: 851 return render_runtime_settings_enqueuer_.Enqueue(setting); 852 case RuntimeSetting::Type::kCapturePreGain: 853 case RuntimeSetting::Type::kCapturePostGain: 854 case RuntimeSetting::Type::kCaptureCompressionGain: 855 case RuntimeSetting::Type::kCaptureFixedPostGain: 856 case RuntimeSetting::Type::kCaptureOutputUsed: 857 return capture_runtime_settings_enqueuer_.Enqueue(setting); 858 case RuntimeSetting::Type::kPlayoutVolumeChange: { 859 bool enqueueing_successful; 860 enqueueing_successful = 861 capture_runtime_settings_enqueuer_.Enqueue(setting); 862 enqueueing_successful = 863 render_runtime_settings_enqueuer_.Enqueue(setting) && 864 enqueueing_successful; 865 return enqueueing_successful; 866 } 867 case RuntimeSetting::Type::kNotSpecified: 868 RTC_DCHECK_NOTREACHED(); 869 return true; 870 } 871 // The language allows the enum to have a non-enumerator 872 // value. Check that this doesn't happen. 873 RTC_DCHECK_NOTREACHED(); 874 return true; 875 } 876 877 AudioProcessingImpl::RuntimeSettingEnqueuer::RuntimeSettingEnqueuer( 878 SwapQueue<RuntimeSetting>* runtime_settings) 879 : runtime_settings_(*runtime_settings) { 880 RTC_DCHECK(runtime_settings); 881 } 882 883 AudioProcessingImpl::RuntimeSettingEnqueuer::~RuntimeSettingEnqueuer() = 884 default; 885 886 bool AudioProcessingImpl::RuntimeSettingEnqueuer::Enqueue( 887 RuntimeSetting setting) { 888 const bool successful_insert = runtime_settings_.Insert(&setting); 889 890 if (!successful_insert) { 891 RTC_LOG(LS_ERROR) << "Cannot enqueue a new runtime setting."; 892 } 893 return successful_insert; 894 } 895 896 void AudioProcessingImpl::MaybeInitializeCapture( 897 const StreamConfig& input_config, 898 const StreamConfig& output_config) { 899 ProcessingConfig processing_config; 900 bool reinitialization_required = false; 901 { 902 // Acquire the capture lock in order to access api_format. The lock is 903 // released immediately, as we may need to acquire the render lock as part 904 // of the conditional reinitialization. 905 MutexLock lock_capture(&mutex_capture_); 906 processing_config = formats_.api_format; 907 reinitialization_required = UpdateActiveSubmoduleStates(); 908 } 909 910 if (processing_config.input_stream() != input_config) { 911 reinitialization_required = true; 912 } 913 914 if (processing_config.output_stream() != output_config) { 915 reinitialization_required = true; 916 } 917 918 if (reinitialization_required) { 919 MutexLock lock_render(&mutex_render_); 920 MutexLock lock_capture(&mutex_capture_); 921 // Reread the API format since the render format may have changed. 922 processing_config = formats_.api_format; 923 processing_config.input_stream() = input_config; 924 processing_config.output_stream() = output_config; 925 InitializeLocked(processing_config); 926 } 927 } 928 929 int AudioProcessingImpl::ProcessStream(const float* const* src, 930 const StreamConfig& input_config, 931 const StreamConfig& output_config, 932 float* const* dest) { 933 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_StreamConfig"); 934 DenormalDisabler denormal_disabler; 935 RETURN_ON_ERR( 936 HandleUnsupportedAudioFormats(src, input_config, output_config, dest)); 937 MaybeInitializeCapture(input_config, output_config); 938 939 MutexLock lock_capture(&mutex_capture_); 940 941 if (aec_dump_) { 942 RecordUnprocessedCaptureStream(src); 943 } 944 945 capture_.capture_audio->CopyFrom(src, formats_.api_format.input_stream()); 946 if (capture_.capture_fullband_audio) { 947 capture_.capture_fullband_audio->CopyFrom( 948 src, formats_.api_format.input_stream()); 949 } 950 RETURN_ON_ERR(ProcessCaptureStreamLocked()); 951 if (capture_.capture_fullband_audio) { 952 capture_.capture_fullband_audio->CopyTo(formats_.api_format.output_stream(), 953 dest); 954 } else { 955 capture_.capture_audio->CopyTo(formats_.api_format.output_stream(), dest); 956 } 957 958 if (aec_dump_) { 959 RecordProcessedCaptureStream(dest); 960 } 961 return kNoError; 962 } 963 964 void AudioProcessingImpl::HandleCaptureRuntimeSettings() { 965 RuntimeSetting setting; 966 int num_settings_processed = 0; 967 while (capture_runtime_settings_.Remove(&setting)) { 968 if (aec_dump_) { 969 aec_dump_->WriteRuntimeSetting(setting); 970 } 971 switch (setting.type()) { 972 case RuntimeSetting::Type::kCapturePreGain: 973 if (config_.pre_amplifier.enabled || 974 config_.capture_level_adjustment.enabled) { 975 float value; 976 setting.GetFloat(&value); 977 // If the pre-amplifier is used, apply the new gain to the 978 // pre-amplifier regardless if the capture level adjustment is 979 // activated. This approach allows both functionalities to coexist 980 // until they have been properly merged. 981 if (config_.pre_amplifier.enabled) { 982 config_.pre_amplifier.fixed_gain_factor = value; 983 } else { 984 config_.capture_level_adjustment.pre_gain_factor = value; 985 } 986 987 // Use both the pre-amplifier and the capture level adjustment gains 988 // as pre-gains. 989 float gain = 1.f; 990 if (config_.pre_amplifier.enabled) { 991 gain *= config_.pre_amplifier.fixed_gain_factor; 992 } 993 if (config_.capture_level_adjustment.enabled) { 994 gain *= config_.capture_level_adjustment.pre_gain_factor; 995 } 996 997 submodules_.capture_levels_adjuster->SetPreGain(gain); 998 } 999 // TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump. 1000 break; 1001 case RuntimeSetting::Type::kCapturePostGain: 1002 if (config_.capture_level_adjustment.enabled) { 1003 float value; 1004 setting.GetFloat(&value); 1005 config_.capture_level_adjustment.post_gain_factor = value; 1006 submodules_.capture_levels_adjuster->SetPostGain( 1007 config_.capture_level_adjustment.post_gain_factor); 1008 } 1009 // TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump. 1010 break; 1011 case RuntimeSetting::Type::kCaptureCompressionGain: { 1012 if (!submodules_.agc_manager && 1013 !(submodules_.gain_controller2 && 1014 config_.gain_controller2.input_volume_controller.enabled)) { 1015 float value; 1016 setting.GetFloat(&value); 1017 int int_value = static_cast<int>(value + .5f); 1018 config_.gain_controller1.compression_gain_db = int_value; 1019 if (submodules_.gain_control) { 1020 int error = 1021 submodules_.gain_control->set_compression_gain_db(int_value); 1022 RTC_DCHECK_EQ(kNoError, error); 1023 } 1024 } 1025 break; 1026 } 1027 case RuntimeSetting::Type::kCaptureFixedPostGain: { 1028 if (submodules_.gain_controller2) { 1029 float value; 1030 setting.GetFloat(&value); 1031 config_.gain_controller2.fixed_digital.gain_db = value; 1032 submodules_.gain_controller2->SetFixedGainDb(value); 1033 } 1034 break; 1035 } 1036 case RuntimeSetting::Type::kPlayoutVolumeChange: { 1037 int value; 1038 setting.GetInt(&value); 1039 capture_.playout_volume = value; 1040 break; 1041 } 1042 case RuntimeSetting::Type::kPlayoutAudioDeviceChange: 1043 RTC_DCHECK_NOTREACHED(); 1044 break; 1045 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting: 1046 RTC_DCHECK_NOTREACHED(); 1047 break; 1048 case RuntimeSetting::Type::kNotSpecified: 1049 RTC_DCHECK_NOTREACHED(); 1050 break; 1051 case RuntimeSetting::Type::kCaptureOutputUsed: 1052 bool value; 1053 setting.GetBool(&value); 1054 HandleCaptureOutputUsedSetting(value); 1055 break; 1056 } 1057 ++num_settings_processed; 1058 } 1059 1060 if (num_settings_processed >= RuntimeSettingQueueSize()) { 1061 // Handle overrun of the runtime settings queue, which likely will has 1062 // caused settings to be discarded. 1063 HandleOverrunInCaptureRuntimeSettingsQueue(); 1064 } 1065 } 1066 1067 void AudioProcessingImpl::HandleOverrunInCaptureRuntimeSettingsQueue() { 1068 // Fall back to a safe state for the case when a setting for capture output 1069 // usage setting has been missed. 1070 HandleCaptureOutputUsedSetting(/*capture_output_used=*/true); 1071 } 1072 1073 void AudioProcessingImpl::HandleRenderRuntimeSettings() { 1074 RuntimeSetting setting; 1075 while (render_runtime_settings_.Remove(&setting)) { 1076 if (aec_dump_) { 1077 aec_dump_->WriteRuntimeSetting(setting); 1078 } 1079 switch (setting.type()) { 1080 case RuntimeSetting::Type::kPlayoutAudioDeviceChange: // fall-through 1081 case RuntimeSetting::Type::kPlayoutVolumeChange: // fall-through 1082 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting: 1083 if (submodules_.render_pre_processor) { 1084 submodules_.render_pre_processor->SetRuntimeSetting(setting); 1085 } 1086 break; 1087 case RuntimeSetting::Type::kCapturePreGain: // fall-through 1088 case RuntimeSetting::Type::kCapturePostGain: // fall-through 1089 case RuntimeSetting::Type::kCaptureCompressionGain: // fall-through 1090 case RuntimeSetting::Type::kCaptureFixedPostGain: // fall-through 1091 case RuntimeSetting::Type::kCaptureOutputUsed: // fall-through 1092 case RuntimeSetting::Type::kNotSpecified: 1093 RTC_DCHECK_NOTREACHED(); 1094 break; 1095 } 1096 } 1097 } 1098 1099 void AudioProcessingImpl::QueueBandedRenderAudio(AudioBuffer* audio) { 1100 RTC_DCHECK_GE(160, audio->num_frames_per_band()); 1101 1102 if (submodules_.echo_control_mobile) { 1103 EchoControlMobileImpl::PackRenderAudioBuffer(audio, num_output_channels(), 1104 num_reverse_channels(), 1105 &aecm_render_queue_buffer_); 1106 RTC_DCHECK(aecm_render_signal_queue_); 1107 // Insert the samples into the queue. 1108 if (!aecm_render_signal_queue_->Insert(&aecm_render_queue_buffer_)) { 1109 // The data queue is full and needs to be emptied. 1110 EmptyQueuedRenderAudio(); 1111 1112 // Retry the insert (should always work). 1113 bool result = 1114 aecm_render_signal_queue_->Insert(&aecm_render_queue_buffer_); 1115 RTC_DCHECK(result); 1116 } 1117 } 1118 1119 if (!submodules_.agc_manager && submodules_.gain_control) { 1120 GainControlImpl::PackRenderAudioBuffer(*audio, &agc_render_queue_buffer_); 1121 // Insert the samples into the queue. 1122 if (!agc_render_signal_queue_->Insert(&agc_render_queue_buffer_)) { 1123 // The data queue is full and needs to be emptied. 1124 EmptyQueuedRenderAudio(); 1125 1126 // Retry the insert (should always work). 1127 bool result = agc_render_signal_queue_->Insert(&agc_render_queue_buffer_); 1128 RTC_DCHECK(result); 1129 } 1130 } 1131 } 1132 1133 void AudioProcessingImpl::QueueNonbandedRenderAudio(AudioBuffer* audio) { 1134 if (submodules_.echo_detector) { 1135 PackRenderAudioBufferForEchoDetector(*audio, red_render_queue_buffer_); 1136 RTC_DCHECK(red_render_signal_queue_); 1137 // Insert the samples into the queue. 1138 if (!red_render_signal_queue_->Insert(&red_render_queue_buffer_)) { 1139 // The data queue is full and needs to be emptied. 1140 EmptyQueuedRenderAudio(); 1141 1142 // Retry the insert (should always work). 1143 bool result = red_render_signal_queue_->Insert(&red_render_queue_buffer_); 1144 RTC_DCHECK(result); 1145 } 1146 } 1147 } 1148 1149 void AudioProcessingImpl::AllocateRenderQueue() { 1150 const size_t new_agc_render_queue_element_max_size = 1151 std::max(static_cast<size_t>(1), kMaxAllowedValuesOfSamplesPerBand); 1152 1153 const size_t new_red_render_queue_element_max_size = 1154 std::max(static_cast<size_t>(1), kMaxAllowedValuesOfSamplesPerFrame); 1155 1156 // Reallocate the queues if the queue item sizes are too small to fit the 1157 // data to put in the queues. 1158 1159 if (agc_render_queue_element_max_size_ < 1160 new_agc_render_queue_element_max_size) { 1161 agc_render_queue_element_max_size_ = new_agc_render_queue_element_max_size; 1162 1163 std::vector<int16_t> template_queue_element( 1164 agc_render_queue_element_max_size_); 1165 1166 agc_render_signal_queue_.reset( 1167 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( 1168 kMaxNumFramesToBuffer, template_queue_element, 1169 RenderQueueItemVerifier<int16_t>( 1170 agc_render_queue_element_max_size_))); 1171 1172 agc_render_queue_buffer_.resize(agc_render_queue_element_max_size_); 1173 agc_capture_queue_buffer_.resize(agc_render_queue_element_max_size_); 1174 } else { 1175 agc_render_signal_queue_->Clear(); 1176 } 1177 1178 if (submodules_.echo_detector) { 1179 if (red_render_queue_element_max_size_ < 1180 new_red_render_queue_element_max_size) { 1181 red_render_queue_element_max_size_ = 1182 new_red_render_queue_element_max_size; 1183 1184 std::vector<float> template_queue_element( 1185 red_render_queue_element_max_size_); 1186 1187 red_render_signal_queue_.reset( 1188 new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>( 1189 kMaxNumFramesToBuffer, template_queue_element, 1190 RenderQueueItemVerifier<float>( 1191 red_render_queue_element_max_size_))); 1192 1193 red_render_queue_buffer_.resize(red_render_queue_element_max_size_); 1194 red_capture_queue_buffer_.resize(red_render_queue_element_max_size_); 1195 } else { 1196 red_render_signal_queue_->Clear(); 1197 } 1198 } 1199 } 1200 1201 void AudioProcessingImpl::EmptyQueuedRenderAudio() { 1202 MutexLock lock_capture(&mutex_capture_); 1203 EmptyQueuedRenderAudioLocked(); 1204 } 1205 1206 void AudioProcessingImpl::EmptyQueuedRenderAudioLocked() { 1207 if (submodules_.echo_control_mobile) { 1208 RTC_DCHECK(aecm_render_signal_queue_); 1209 while (aecm_render_signal_queue_->Remove(&aecm_capture_queue_buffer_)) { 1210 submodules_.echo_control_mobile->ProcessRenderAudio( 1211 aecm_capture_queue_buffer_); 1212 } 1213 } 1214 1215 if (submodules_.gain_control) { 1216 while (agc_render_signal_queue_->Remove(&agc_capture_queue_buffer_)) { 1217 submodules_.gain_control->ProcessRenderAudio(agc_capture_queue_buffer_); 1218 } 1219 } 1220 1221 if (submodules_.echo_detector) { 1222 while (red_render_signal_queue_->Remove(&red_capture_queue_buffer_)) { 1223 submodules_.echo_detector->AnalyzeRenderAudio(red_capture_queue_buffer_); 1224 } 1225 } 1226 } 1227 1228 int AudioProcessingImpl::ProcessStream(const int16_t* const src, 1229 const StreamConfig& input_config, 1230 const StreamConfig& output_config, 1231 int16_t* const dest) { 1232 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_AudioFrame"); 1233 1234 RETURN_ON_ERR( 1235 HandleUnsupportedAudioFormats(src, input_config, output_config, dest)); 1236 MaybeInitializeCapture(input_config, output_config); 1237 1238 MutexLock lock_capture(&mutex_capture_); 1239 DenormalDisabler denormal_disabler; 1240 1241 if (aec_dump_) { 1242 RecordUnprocessedCaptureStream(src, input_config); 1243 } 1244 1245 capture_.capture_audio->CopyFrom(src, input_config); 1246 if (capture_.capture_fullband_audio) { 1247 capture_.capture_fullband_audio->CopyFrom(src, input_config); 1248 } 1249 RETURN_ON_ERR(ProcessCaptureStreamLocked()); 1250 if (submodule_states_.CaptureMultiBandProcessingPresent() || 1251 submodule_states_.CaptureFullBandProcessingActive()) { 1252 if (capture_.capture_fullband_audio) { 1253 capture_.capture_fullband_audio->CopyTo(output_config, dest); 1254 } else { 1255 capture_.capture_audio->CopyTo(output_config, dest); 1256 } 1257 } 1258 1259 if (aec_dump_) { 1260 RecordProcessedCaptureStream(dest, output_config); 1261 } 1262 return kNoError; 1263 } 1264 1265 int AudioProcessingImpl::ProcessCaptureStreamLocked() { 1266 EmptyQueuedRenderAudioLocked(); 1267 HandleCaptureRuntimeSettings(); 1268 DenormalDisabler denormal_disabler; 1269 1270 // Ensure that not both the AEC and AECM are active at the same time. 1271 // TODO(peah): Simplify once the public API Enable functions for these 1272 // are moved to APM. 1273 RTC_DCHECK_LE( 1274 !!submodules_.echo_controller + !!submodules_.echo_control_mobile, 1); 1275 1276 data_dumper_->DumpRaw( 1277 "applied_input_volume", 1278 capture_.applied_input_volume.value_or(kUnspecifiedDataDumpInputVolume)); 1279 1280 AudioBuffer* capture_buffer = capture_.capture_audio.get(); // For brevity. 1281 AudioBuffer* linear_aec_buffer = capture_.linear_aec_output.get(); 1282 1283 if (submodules_.high_pass_filter && 1284 config_.high_pass_filter.apply_in_full_band && 1285 !constants_.enforce_split_band_hpf) { 1286 submodules_.high_pass_filter->Process(capture_buffer, 1287 /*use_split_band_data=*/false); 1288 } 1289 1290 if (submodules_.capture_levels_adjuster) { 1291 if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) { 1292 // When the input volume is emulated, retrieve the volume applied to the 1293 // input audio and notify that to APM so that the volume is passed to the 1294 // active AGC. 1295 set_stream_analog_level_locked( 1296 submodules_.capture_levels_adjuster->GetAnalogMicGainLevel()); 1297 } 1298 submodules_.capture_levels_adjuster->ApplyPreLevelAdjustment( 1299 *capture_buffer); 1300 } 1301 1302 capture_input_rms_.Analyze(ArrayView<const float>( 1303 capture_buffer->channels_const()[0], 1304 capture_nonlocked_.capture_processing_format.num_frames())); 1305 const bool log_rms = ++capture_rms_interval_counter_ >= 1000; 1306 if (log_rms) { 1307 capture_rms_interval_counter_ = 0; 1308 RmsLevel::Levels levels = capture_input_rms_.AverageAndPeak(); 1309 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelAverageRms", 1310 levels.average, 1, RmsLevel::kMinLevelDb, 64); 1311 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelPeakRms", 1312 levels.peak, 1, RmsLevel::kMinLevelDb, 64); 1313 } 1314 1315 if (capture_.applied_input_volume.has_value()) { 1316 applied_input_volume_stats_reporter_.UpdateStatistics( 1317 *capture_.applied_input_volume); 1318 } 1319 1320 if (submodules_.echo_controller) { 1321 // Determine if the echo path gain has changed by checking all the gains 1322 // applied before AEC. 1323 capture_.echo_path_gain_change = capture_.applied_input_volume_changed; 1324 1325 // Detect and flag any change in the capture level adjustment pre-gain. 1326 if (submodules_.capture_levels_adjuster) { 1327 float pre_adjustment_gain = 1328 submodules_.capture_levels_adjuster->GetPreAdjustmentGain(); 1329 capture_.echo_path_gain_change = 1330 capture_.echo_path_gain_change || 1331 (capture_.prev_pre_adjustment_gain != pre_adjustment_gain && 1332 capture_.prev_pre_adjustment_gain >= 0.0f); 1333 capture_.prev_pre_adjustment_gain = pre_adjustment_gain; 1334 } 1335 1336 // Detect volume change. 1337 capture_.echo_path_gain_change = 1338 capture_.echo_path_gain_change || 1339 (capture_.prev_playout_volume != capture_.playout_volume && 1340 capture_.prev_playout_volume >= 0); 1341 capture_.prev_playout_volume = capture_.playout_volume; 1342 1343 submodules_.echo_controller->AnalyzeCapture(capture_buffer); 1344 } 1345 1346 if (submodules_.agc_manager) { 1347 submodules_.agc_manager->AnalyzePreProcess(*capture_buffer); 1348 } 1349 1350 if (submodules_.gain_controller2 && 1351 config_.gain_controller2.input_volume_controller.enabled) { 1352 // Expect the volume to be available if the input controller is enabled. 1353 RTC_DCHECK(capture_.applied_input_volume.has_value()); 1354 if (capture_.applied_input_volume.has_value()) { 1355 submodules_.gain_controller2->Analyze(*capture_.applied_input_volume, 1356 *capture_buffer); 1357 } 1358 } 1359 1360 if (submodule_states_.CaptureMultiBandSubModulesActive() && 1361 SampleRateSupportsMultiBand( 1362 capture_nonlocked_.capture_processing_format.sample_rate_hz())) { 1363 capture_buffer->SplitIntoFrequencyBands(); 1364 } 1365 1366 const bool multi_channel_capture = config_.pipeline.multi_channel_capture && 1367 constants_.multi_channel_capture_support; 1368 if (submodules_.echo_controller && !multi_channel_capture) { 1369 // Force down-mixing of the number of channels after the detection of 1370 // capture signal saturation. 1371 // TODO(peah): Look into ensuring that this kind of tampering with the 1372 // AudioBuffer functionality should not be needed. 1373 capture_buffer->set_num_channels(1); 1374 } 1375 1376 if (submodules_.high_pass_filter && 1377 (!config_.high_pass_filter.apply_in_full_band || 1378 constants_.enforce_split_band_hpf)) { 1379 submodules_.high_pass_filter->Process(capture_buffer, 1380 /*use_split_band_data=*/true); 1381 } 1382 1383 if (submodules_.gain_control) { 1384 RETURN_ON_ERR( 1385 submodules_.gain_control->AnalyzeCaptureAudio(*capture_buffer)); 1386 } 1387 1388 if ((!config_.noise_suppression.analyze_linear_aec_output_when_available || 1389 !linear_aec_buffer || submodules_.echo_control_mobile) && 1390 submodules_.noise_suppressor) { 1391 submodules_.noise_suppressor->Analyze(*capture_buffer); 1392 } 1393 1394 if (submodules_.echo_control_mobile) { 1395 // Ensure that the stream delay was set before the call to the 1396 // AECM ProcessCaptureAudio function. 1397 if (!capture_.was_stream_delay_set) { 1398 return AudioProcessing::kStreamParameterNotSetError; 1399 } 1400 1401 if (submodules_.noise_suppressor) { 1402 submodules_.noise_suppressor->Process(capture_buffer); 1403 } 1404 1405 RETURN_ON_ERR(submodules_.echo_control_mobile->ProcessCaptureAudio( 1406 capture_buffer, stream_delay_ms())); 1407 } else { 1408 if (submodules_.echo_controller) { 1409 data_dumper_->DumpRaw("stream_delay", stream_delay_ms()); 1410 1411 if (capture_.was_stream_delay_set) { 1412 submodules_.echo_controller->SetAudioBufferDelay(stream_delay_ms()); 1413 } 1414 1415 submodules_.echo_controller->ProcessCapture( 1416 capture_buffer, linear_aec_buffer, capture_.echo_path_gain_change); 1417 } 1418 1419 if (config_.noise_suppression.analyze_linear_aec_output_when_available && 1420 linear_aec_buffer && submodules_.noise_suppressor) { 1421 submodules_.noise_suppressor->Analyze(*linear_aec_buffer); 1422 } 1423 1424 if (submodules_.noise_suppressor) { 1425 submodules_.noise_suppressor->Process(capture_buffer); 1426 } 1427 } 1428 1429 if (submodules_.agc_manager) { 1430 submodules_.agc_manager->Process(*capture_buffer); 1431 1432 std::optional<int> new_digital_gain = 1433 submodules_.agc_manager->GetDigitalComressionGain(); 1434 if (new_digital_gain && submodules_.gain_control) { 1435 submodules_.gain_control->set_compression_gain_db(*new_digital_gain); 1436 } 1437 } 1438 1439 if (submodules_.gain_control) { 1440 // TODO(peah): Add reporting from AEC3 whether there is echo. 1441 RETURN_ON_ERR(submodules_.gain_control->ProcessCaptureAudio( 1442 capture_buffer, /*stream_has_echo*/ false)); 1443 } 1444 1445 if (submodule_states_.CaptureMultiBandProcessingPresent() && 1446 SampleRateSupportsMultiBand( 1447 capture_nonlocked_.capture_processing_format.sample_rate_hz())) { 1448 capture_buffer->MergeFrequencyBands(); 1449 } 1450 1451 if (capture_.capture_output_used) { 1452 if (capture_.capture_fullband_audio) { 1453 const auto& ec = submodules_.echo_controller; 1454 bool ec_active = ec ? ec->ActiveProcessing() : false; 1455 // Only update the fullband buffer if the multiband processing has changed 1456 // the signal. Keep the original signal otherwise. 1457 if (submodule_states_.CaptureMultiBandProcessingActive(ec_active)) { 1458 capture_buffer->CopyTo(capture_.capture_fullband_audio.get()); 1459 } 1460 capture_buffer = capture_.capture_fullband_audio.get(); 1461 } 1462 1463 if (submodules_.echo_detector) { 1464 submodules_.echo_detector->AnalyzeCaptureAudio(ArrayView<const float>( 1465 capture_buffer->channels()[0], capture_buffer->num_frames())); 1466 } 1467 1468 // Experimental APM sub-module that analyzes `capture_buffer`. 1469 if (submodules_.capture_analyzer) { 1470 submodules_.capture_analyzer->Analyze(capture_buffer); 1471 } 1472 1473 if (submodules_.gain_controller2) { 1474 // TODO(bugs.webrtc.org/7494): Let AGC2 detect applied input volume 1475 // changes. 1476 submodules_.gain_controller2->Process( 1477 /*speech_probability=*/std::nullopt, 1478 capture_.applied_input_volume_changed, capture_buffer); 1479 } 1480 1481 if (submodules_.post_filter) { 1482 submodules_.post_filter->Process(*capture_buffer); 1483 } 1484 1485 if (submodules_.capture_post_processor) { 1486 submodules_.capture_post_processor->Process(capture_buffer); 1487 } 1488 1489 capture_output_rms_.Analyze(ArrayView<const float>( 1490 capture_buffer->channels_const()[0], 1491 capture_nonlocked_.capture_processing_format.num_frames())); 1492 if (log_rms) { 1493 RmsLevel::Levels levels = capture_output_rms_.AverageAndPeak(); 1494 RTC_HISTOGRAM_COUNTS_LINEAR( 1495 "WebRTC.Audio.ApmCaptureOutputLevelAverageRms", levels.average, 1, 1496 RmsLevel::kMinLevelDb, 64); 1497 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureOutputLevelPeakRms", 1498 levels.peak, 1, RmsLevel::kMinLevelDb, 64); 1499 } 1500 1501 // Compute echo-detector stats. 1502 if (submodules_.echo_detector) { 1503 auto ed_metrics = submodules_.echo_detector->GetMetrics(); 1504 capture_.stats.residual_echo_likelihood = ed_metrics.echo_likelihood; 1505 capture_.stats.residual_echo_likelihood_recent_max = 1506 ed_metrics.echo_likelihood_recent_max; 1507 } 1508 } 1509 1510 // Compute echo-controller stats. 1511 if (submodules_.echo_controller) { 1512 auto ec_metrics = submodules_.echo_controller->GetMetrics(); 1513 capture_.stats.echo_return_loss = ec_metrics.echo_return_loss; 1514 capture_.stats.echo_return_loss_enhancement = 1515 ec_metrics.echo_return_loss_enhancement; 1516 capture_.stats.delay_ms = ec_metrics.delay_ms; 1517 } 1518 1519 // Pass stats for reporting. 1520 stats_reporter_.UpdateStatistics(capture_.stats); 1521 1522 UpdateRecommendedInputVolumeLocked(); 1523 if (capture_.recommended_input_volume.has_value()) { 1524 recommended_input_volume_stats_reporter_.UpdateStatistics( 1525 *capture_.recommended_input_volume); 1526 } 1527 1528 if (submodules_.capture_levels_adjuster) { 1529 submodules_.capture_levels_adjuster->ApplyPostLevelAdjustment( 1530 *capture_buffer); 1531 1532 if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) { 1533 // If the input volume emulation is used, retrieve the recommended input 1534 // volume and set that to emulate the input volume on the next processed 1535 // audio frame. 1536 RTC_DCHECK(capture_.recommended_input_volume.has_value()); 1537 submodules_.capture_levels_adjuster->SetAnalogMicGainLevel( 1538 *capture_.recommended_input_volume); 1539 } 1540 } 1541 1542 // Temporarily set the output to zero after the stream has been unmuted 1543 // (capture output is again used). The purpose of this is to avoid clicks and 1544 // artefacts in the audio that results when the processing again is 1545 // reactivated after unmuting. 1546 if (!capture_.capture_output_used_last_frame && 1547 capture_.capture_output_used) { 1548 for (size_t ch = 0; ch < capture_buffer->num_channels(); ++ch) { 1549 ArrayView<float> channel_view(capture_buffer->channels()[ch], 1550 capture_buffer->num_frames()); 1551 std::fill(channel_view.begin(), channel_view.end(), 0.f); 1552 } 1553 } 1554 capture_.capture_output_used_last_frame = capture_.capture_output_used; 1555 1556 capture_.was_stream_delay_set = false; 1557 1558 data_dumper_->DumpRaw("recommended_input_volume", 1559 capture_.recommended_input_volume.value_or( 1560 kUnspecifiedDataDumpInputVolume)); 1561 1562 return kNoError; 1563 } 1564 1565 int AudioProcessingImpl::AnalyzeReverseStream( 1566 const float* const* data, 1567 const StreamConfig& reverse_config) { 1568 TRACE_EVENT0("webrtc", "AudioProcessing::AnalyzeReverseStream_StreamConfig"); 1569 MutexLock lock(&mutex_render_); 1570 DenormalDisabler denormal_disabler; 1571 RTC_DCHECK(data); 1572 for (size_t i = 0; i < reverse_config.num_channels(); ++i) { 1573 RTC_DCHECK(data[i]); 1574 } 1575 RETURN_ON_ERR( 1576 AudioFormatValidityToErrorCode(ValidateAudioFormat(reverse_config))); 1577 1578 MaybeInitializeRender(reverse_config, reverse_config); 1579 return AnalyzeReverseStreamLocked(data, reverse_config, reverse_config); 1580 } 1581 1582 int AudioProcessingImpl::ProcessReverseStream(const float* const* src, 1583 const StreamConfig& input_config, 1584 const StreamConfig& output_config, 1585 float* const* dest) { 1586 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_StreamConfig"); 1587 MutexLock lock(&mutex_render_); 1588 DenormalDisabler denormal_disabler; 1589 RETURN_ON_ERR( 1590 HandleUnsupportedAudioFormats(src, input_config, output_config, dest)); 1591 1592 MaybeInitializeRender(input_config, output_config); 1593 1594 RETURN_ON_ERR(AnalyzeReverseStreamLocked(src, input_config, output_config)); 1595 1596 if (submodule_states_.RenderMultiBandProcessingActive() || 1597 submodule_states_.RenderFullBandProcessingActive()) { 1598 render_.render_audio->CopyTo(formats_.api_format.reverse_output_stream(), 1599 dest); 1600 } else if (formats_.api_format.reverse_input_stream() != 1601 formats_.api_format.reverse_output_stream()) { 1602 render_.render_converter->Convert(src, input_config.num_samples(), dest, 1603 output_config.num_samples()); 1604 } else { 1605 CopyAudioIfNeeded(src, input_config.num_frames(), 1606 input_config.num_channels(), dest); 1607 } 1608 1609 return kNoError; 1610 } 1611 1612 int AudioProcessingImpl::AnalyzeReverseStreamLocked( 1613 const float* const* src, 1614 const StreamConfig& /* input_config */, 1615 const StreamConfig& /* output_config */) { 1616 if (aec_dump_) { 1617 const size_t channel_size = 1618 formats_.api_format.reverse_input_stream().num_frames(); 1619 const size_t num_channels = 1620 formats_.api_format.reverse_input_stream().num_channels(); 1621 aec_dump_->WriteRenderStreamMessage(src, num_channels, channel_size); 1622 } 1623 render_.render_audio->CopyFrom(src, 1624 formats_.api_format.reverse_input_stream()); 1625 return ProcessRenderStreamLocked(); 1626 } 1627 1628 int AudioProcessingImpl::ProcessReverseStream(const int16_t* const src, 1629 const StreamConfig& input_config, 1630 const StreamConfig& output_config, 1631 int16_t* const dest) { 1632 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_AudioFrame"); 1633 1634 MutexLock lock(&mutex_render_); 1635 DenormalDisabler denormal_disabler; 1636 1637 RETURN_ON_ERR( 1638 HandleUnsupportedAudioFormats(src, input_config, output_config, dest)); 1639 MaybeInitializeRender(input_config, output_config); 1640 1641 if (aec_dump_) { 1642 aec_dump_->WriteRenderStreamMessage(src, input_config.num_frames(), 1643 input_config.num_channels()); 1644 } 1645 1646 render_.render_audio->CopyFrom(src, input_config); 1647 RETURN_ON_ERR(ProcessRenderStreamLocked()); 1648 if (submodule_states_.RenderMultiBandProcessingActive() || 1649 submodule_states_.RenderFullBandProcessingActive()) { 1650 render_.render_audio->CopyTo(output_config, dest); 1651 } 1652 return kNoError; 1653 } 1654 1655 int AudioProcessingImpl::ProcessRenderStreamLocked() { 1656 AudioBuffer* render_buffer = render_.render_audio.get(); // For brevity. 1657 1658 HandleRenderRuntimeSettings(); 1659 DenormalDisabler denormal_disabler; 1660 1661 if (submodules_.render_pre_processor) { 1662 submodules_.render_pre_processor->Process(render_buffer); 1663 } 1664 1665 QueueNonbandedRenderAudio(render_buffer); 1666 1667 if (submodule_states_.RenderMultiBandSubModulesActive() && 1668 SampleRateSupportsMultiBand( 1669 formats_.render_processing_format.sample_rate_hz())) { 1670 render_buffer->SplitIntoFrequencyBands(); 1671 } 1672 1673 if (submodule_states_.RenderMultiBandSubModulesActive()) { 1674 QueueBandedRenderAudio(render_buffer); 1675 } 1676 1677 // TODO(peah): Perform the queuing inside QueueRenderAudiuo(). 1678 if (submodules_.echo_controller) { 1679 submodules_.echo_controller->AnalyzeRender(render_buffer); 1680 } 1681 1682 if (submodule_states_.RenderMultiBandProcessingActive() && 1683 SampleRateSupportsMultiBand( 1684 formats_.render_processing_format.sample_rate_hz())) { 1685 render_buffer->MergeFrequencyBands(); 1686 } 1687 1688 return kNoError; 1689 } 1690 1691 int AudioProcessingImpl::set_stream_delay_ms(int delay) { 1692 MutexLock lock(&mutex_capture_); 1693 Error retval = kNoError; 1694 capture_.was_stream_delay_set = true; 1695 1696 if (delay < 0) { 1697 delay = 0; 1698 retval = kBadStreamParameterWarning; 1699 } 1700 1701 // TODO(ajm): the max is rather arbitrarily chosen; investigate. 1702 if (delay > 500) { 1703 delay = 500; 1704 retval = kBadStreamParameterWarning; 1705 } 1706 1707 capture_nonlocked_.stream_delay_ms = delay; 1708 return retval; 1709 } 1710 1711 bool AudioProcessingImpl::GetLinearAecOutput( 1712 ArrayView<std::array<float, 160>> linear_output) const { 1713 MutexLock lock(&mutex_capture_); 1714 AudioBuffer* linear_aec_buffer = capture_.linear_aec_output.get(); 1715 1716 RTC_DCHECK(linear_aec_buffer); 1717 if (linear_aec_buffer) { 1718 RTC_DCHECK_EQ(1, linear_aec_buffer->num_bands()); 1719 RTC_DCHECK_EQ(linear_output.size(), linear_aec_buffer->num_channels()); 1720 1721 for (size_t ch = 0; ch < linear_aec_buffer->num_channels(); ++ch) { 1722 RTC_DCHECK_EQ(linear_output[ch].size(), linear_aec_buffer->num_frames()); 1723 ArrayView<const float> channel_view = 1724 ArrayView<const float>(linear_aec_buffer->channels_const()[ch], 1725 linear_aec_buffer->num_frames()); 1726 FloatS16ToFloat(channel_view.data(), channel_view.size(), 1727 linear_output[ch].data()); 1728 } 1729 return true; 1730 } 1731 RTC_LOG(LS_ERROR) << "No linear AEC output available"; 1732 RTC_DCHECK_NOTREACHED(); 1733 return false; 1734 } 1735 1736 int AudioProcessingImpl::stream_delay_ms() const { 1737 // Used as callback from submodules, hence locking is not allowed. 1738 return capture_nonlocked_.stream_delay_ms; 1739 } 1740 1741 void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) { 1742 MutexLock lock(&mutex_capture_); 1743 capture_.key_pressed = key_pressed; 1744 } 1745 1746 void AudioProcessingImpl::set_stream_analog_level(int level) { 1747 MutexLock lock_capture(&mutex_capture_); 1748 set_stream_analog_level_locked(level); 1749 } 1750 1751 void AudioProcessingImpl::set_stream_analog_level_locked(int level) { 1752 capture_.applied_input_volume_changed = 1753 capture_.applied_input_volume.has_value() && 1754 *capture_.applied_input_volume != level; 1755 capture_.applied_input_volume = level; 1756 1757 // Invalidate any previously recommended input volume which will be updated by 1758 // `ProcessStream()`. 1759 capture_.recommended_input_volume = std::nullopt; 1760 1761 if (submodules_.agc_manager) { 1762 submodules_.agc_manager->set_stream_analog_level(level); 1763 return; 1764 } 1765 1766 if (submodules_.gain_control) { 1767 int error = submodules_.gain_control->set_stream_analog_level(level); 1768 RTC_DCHECK_EQ(kNoError, error); 1769 return; 1770 } 1771 } 1772 1773 int AudioProcessingImpl::recommended_stream_analog_level() const { 1774 MutexLock lock_capture(&mutex_capture_); 1775 if (!capture_.applied_input_volume.has_value()) { 1776 RTC_LOG(LS_ERROR) << "set_stream_analog_level has not been called"; 1777 } 1778 // Input volume to recommend when `set_stream_analog_level()` is not called. 1779 constexpr int kFallBackInputVolume = 255; 1780 // When APM has no input volume to recommend, return the latest applied input 1781 // volume that has been observed in order to possibly produce no input volume 1782 // change. If no applied input volume has been observed, return a fall-back 1783 // value. 1784 return capture_.recommended_input_volume.value_or( 1785 capture_.applied_input_volume.value_or(kFallBackInputVolume)); 1786 } 1787 1788 void AudioProcessingImpl::UpdateRecommendedInputVolumeLocked() { 1789 if (!capture_.applied_input_volume.has_value()) { 1790 // When `set_stream_analog_level()` is not called, no input level can be 1791 // recommended. 1792 capture_.recommended_input_volume = std::nullopt; 1793 return; 1794 } 1795 1796 if (submodules_.agc_manager) { 1797 capture_.recommended_input_volume = 1798 submodules_.agc_manager->recommended_analog_level(); 1799 return; 1800 } 1801 1802 if (submodules_.gain_control) { 1803 capture_.recommended_input_volume = 1804 submodules_.gain_control->stream_analog_level(); 1805 return; 1806 } 1807 1808 if (submodules_.gain_controller2 && 1809 config_.gain_controller2.input_volume_controller.enabled) { 1810 capture_.recommended_input_volume = 1811 submodules_.gain_controller2->recommended_input_volume(); 1812 return; 1813 } 1814 1815 capture_.recommended_input_volume = capture_.applied_input_volume; 1816 } 1817 1818 bool AudioProcessingImpl::CreateAndAttachAecDump(absl::string_view file_name, 1819 int64_t max_log_size_bytes, 1820 TaskQueueBase* absl_nonnull 1821 worker_queue) { 1822 std::unique_ptr<AecDump> aec_dump = 1823 AecDumpFactory::Create(file_name, max_log_size_bytes, worker_queue); 1824 if (!aec_dump) { 1825 return false; 1826 } 1827 1828 AttachAecDump(std::move(aec_dump)); 1829 return true; 1830 } 1831 1832 bool AudioProcessingImpl::CreateAndAttachAecDump(FILE* handle, 1833 int64_t max_log_size_bytes, 1834 TaskQueueBase* absl_nonnull 1835 worker_queue) { 1836 std::unique_ptr<AecDump> aec_dump = 1837 AecDumpFactory::Create(handle, max_log_size_bytes, worker_queue); 1838 if (!aec_dump) { 1839 return false; 1840 } 1841 1842 AttachAecDump(std::move(aec_dump)); 1843 return true; 1844 } 1845 1846 void AudioProcessingImpl::AttachAecDump(std::unique_ptr<AecDump> aec_dump) { 1847 RTC_DCHECK(aec_dump); 1848 MutexLock lock_render(&mutex_render_); 1849 MutexLock lock_capture(&mutex_capture_); 1850 1851 // The previously attached AecDump will be destroyed with the 1852 // 'aec_dump' parameter, which is after locks are released. 1853 aec_dump_.swap(aec_dump); 1854 WriteAecDumpConfigMessage(true); 1855 aec_dump_->WriteInitMessage(formats_.api_format, TimeUTCMillis()); 1856 } 1857 1858 void AudioProcessingImpl::DetachAecDump() { 1859 // The d-tor of a task-queue based AecDump blocks until all pending 1860 // tasks are done. This construction avoids blocking while holding 1861 // the render and capture locks. 1862 std::unique_ptr<AecDump> aec_dump = nullptr; 1863 { 1864 MutexLock lock_render(&mutex_render_); 1865 MutexLock lock_capture(&mutex_capture_); 1866 aec_dump = std::move(aec_dump_); 1867 } 1868 } 1869 1870 AudioProcessing::Config AudioProcessingImpl::GetConfig() const { 1871 MutexLock lock_render(&mutex_render_); 1872 MutexLock lock_capture(&mutex_capture_); 1873 return config_; 1874 } 1875 1876 bool AudioProcessingImpl::UpdateActiveSubmoduleStates() { 1877 return submodule_states_.Update( 1878 config_.high_pass_filter.enabled, !!submodules_.echo_control_mobile, 1879 !!submodules_.noise_suppressor, !!submodules_.gain_control, 1880 !!submodules_.gain_controller2, 1881 config_.pre_amplifier.enabled || config_.capture_level_adjustment.enabled, 1882 capture_nonlocked_.echo_controller_enabled); 1883 } 1884 1885 void AudioProcessingImpl::InitializeHighPassFilter(bool forced_reset) { 1886 bool high_pass_filter_needed_by_aec = 1887 config_.echo_canceller.enabled && 1888 config_.echo_canceller.enforce_high_pass_filtering && 1889 !config_.echo_canceller.mobile_mode; 1890 if (submodule_states_.HighPassFilteringRequired() || 1891 high_pass_filter_needed_by_aec) { 1892 bool use_full_band = config_.high_pass_filter.apply_in_full_band && 1893 !constants_.enforce_split_band_hpf; 1894 int rate = use_full_band ? proc_fullband_sample_rate_hz() 1895 : proc_split_sample_rate_hz(); 1896 size_t num_channels = 1897 use_full_band ? num_output_channels() : num_proc_channels(); 1898 1899 if (!submodules_.high_pass_filter || 1900 rate != submodules_.high_pass_filter->sample_rate_hz() || 1901 forced_reset || 1902 num_channels != submodules_.high_pass_filter->num_channels()) { 1903 submodules_.high_pass_filter.reset( 1904 new HighPassFilter(rate, num_channels)); 1905 } 1906 } else { 1907 submodules_.high_pass_filter.reset(); 1908 } 1909 } 1910 1911 void AudioProcessingImpl::InitializeEchoController() { 1912 bool use_echo_controller = 1913 echo_control_factory_ || 1914 (config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode); 1915 1916 if (use_echo_controller) { 1917 // Create and activate the echo controller. 1918 if (echo_control_factory_) { 1919 submodules_.echo_controller = echo_control_factory_->Create( 1920 env_, proc_sample_rate_hz(), num_reverse_channels(), 1921 num_proc_channels(), 1922 submodules_.neural_residual_echo_estimator.get()); 1923 RTC_DCHECK(submodules_.echo_controller); 1924 } else { 1925 EchoCanceller3Config config_to_use = 1926 echo_canceller_config_.value_or(EchoCanceller3Config()); 1927 std::optional<EchoCanceller3Config> multichannel_config_to_use = 1928 echo_canceller_multichannel_config_; 1929 if (!echo_canceller_config_.has_value() && 1930 !multichannel_config_to_use.has_value()) { 1931 // We create a default multichannel config only if the user has set no 1932 // config: If the user only provides a non-multichannel config, that 1933 // config is used for both mono and multichannel AEC. 1934 multichannel_config_to_use = 1935 EchoCanceller3Config::CreateDefaultMultichannelConfig(); 1936 } 1937 submodules_.echo_controller = std::make_unique<EchoCanceller3>( 1938 env_, config_to_use, multichannel_config_to_use, 1939 submodules_.neural_residual_echo_estimator.get(), 1940 proc_sample_rate_hz(), num_reverse_channels(), num_proc_channels()); 1941 } 1942 1943 // Setup the storage for returning the linear AEC output. 1944 if (config_.echo_canceller.export_linear_aec_output) { 1945 constexpr int kLinearOutputRateHz = 16000; 1946 capture_.linear_aec_output = std::make_unique<AudioBuffer>( 1947 kLinearOutputRateHz, num_proc_channels(), kLinearOutputRateHz, 1948 num_proc_channels(), kLinearOutputRateHz, num_proc_channels()); 1949 } else { 1950 capture_.linear_aec_output.reset(); 1951 } 1952 1953 capture_nonlocked_.echo_controller_enabled = true; 1954 1955 if (!env_.field_trials().IsEnabled("WebRTC-PostFilterKillSwitch")) { 1956 // Only creates a PostFilter if current sample-rate is high enough to 1957 // require a filter. 1958 submodules_.post_filter = PostFilter::CreateIfNeeded( 1959 proc_sample_rate_hz(), num_proc_channels()); 1960 } 1961 1962 submodules_.echo_control_mobile.reset(); 1963 aecm_render_signal_queue_.reset(); 1964 return; 1965 } 1966 1967 submodules_.echo_controller.reset(); 1968 capture_nonlocked_.echo_controller_enabled = false; 1969 capture_.linear_aec_output.reset(); 1970 1971 if (!config_.echo_canceller.enabled) { 1972 submodules_.echo_control_mobile.reset(); 1973 aecm_render_signal_queue_.reset(); 1974 return; 1975 } 1976 1977 if (config_.echo_canceller.mobile_mode) { 1978 // Create and activate AECM. 1979 size_t max_element_size = 1980 std::max(static_cast<size_t>(1), 1981 kMaxAllowedValuesOfSamplesPerBand * 1982 EchoControlMobileImpl::NumCancellersRequired( 1983 num_output_channels(), num_reverse_channels())); 1984 1985 std::vector<int16_t> template_queue_element(max_element_size); 1986 1987 aecm_render_signal_queue_.reset( 1988 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( 1989 kMaxNumFramesToBuffer, template_queue_element, 1990 RenderQueueItemVerifier<int16_t>(max_element_size))); 1991 1992 aecm_render_queue_buffer_.resize(max_element_size); 1993 aecm_capture_queue_buffer_.resize(max_element_size); 1994 1995 submodules_.echo_control_mobile.reset(new EchoControlMobileImpl()); 1996 1997 submodules_.echo_control_mobile->Initialize(proc_split_sample_rate_hz(), 1998 num_reverse_channels(), 1999 num_output_channels()); 2000 return; 2001 } 2002 2003 submodules_.echo_control_mobile.reset(); 2004 aecm_render_signal_queue_.reset(); 2005 } 2006 2007 void AudioProcessingImpl::InitializeGainController1() { 2008 if (config_.gain_controller2.enabled && 2009 config_.gain_controller2.input_volume_controller.enabled && 2010 config_.gain_controller1.enabled && 2011 (config_.gain_controller1.mode == 2012 AudioProcessing::Config::GainController1::kAdaptiveAnalog || 2013 config_.gain_controller1.analog_gain_controller.enabled)) { 2014 RTC_LOG(LS_ERROR) << "APM configuration not valid: " 2015 << "Multiple input volume controllers enabled."; 2016 } 2017 2018 if (!config_.gain_controller1.enabled) { 2019 submodules_.agc_manager.reset(); 2020 submodules_.gain_control.reset(); 2021 return; 2022 } 2023 2024 RTC_HISTOGRAM_BOOLEAN( 2025 "WebRTC.Audio.GainController.Analog.Enabled", 2026 config_.gain_controller1.analog_gain_controller.enabled); 2027 2028 if (!submodules_.gain_control) { 2029 submodules_.gain_control.reset(new GainControlImpl()); 2030 } 2031 2032 submodules_.gain_control->Initialize(num_proc_channels(), 2033 proc_sample_rate_hz()); 2034 if (!config_.gain_controller1.analog_gain_controller.enabled) { 2035 int error = submodules_.gain_control->set_mode( 2036 Agc1ConfigModeToInterfaceMode(config_.gain_controller1.mode)); 2037 RTC_DCHECK_EQ(kNoError, error); 2038 error = submodules_.gain_control->set_target_level_dbfs( 2039 config_.gain_controller1.target_level_dbfs); 2040 RTC_DCHECK_EQ(kNoError, error); 2041 error = submodules_.gain_control->set_compression_gain_db( 2042 config_.gain_controller1.compression_gain_db); 2043 RTC_DCHECK_EQ(kNoError, error); 2044 error = submodules_.gain_control->enable_limiter( 2045 config_.gain_controller1.enable_limiter); 2046 RTC_DCHECK_EQ(kNoError, error); 2047 constexpr int kAnalogLevelMinimum = 0; 2048 constexpr int kAnalogLevelMaximum = 255; 2049 error = submodules_.gain_control->set_analog_level_limits( 2050 kAnalogLevelMinimum, kAnalogLevelMaximum); 2051 RTC_DCHECK_EQ(kNoError, error); 2052 2053 submodules_.agc_manager.reset(); 2054 return; 2055 } 2056 2057 if (!submodules_.agc_manager || submodules_.agc_manager->num_channels() != 2058 static_cast<int>(num_proc_channels())) { 2059 int stream_analog_level = -1; 2060 const bool re_creation = !!submodules_.agc_manager; 2061 if (re_creation) { 2062 stream_analog_level = submodules_.agc_manager->recommended_analog_level(); 2063 } 2064 submodules_.agc_manager = std::make_unique<AgcManagerDirect>( 2065 env_, num_proc_channels(), 2066 config_.gain_controller1.analog_gain_controller); 2067 if (re_creation) { 2068 submodules_.agc_manager->set_stream_analog_level(stream_analog_level); 2069 } 2070 } 2071 submodules_.agc_manager->Initialize(); 2072 submodules_.agc_manager->SetupDigitalGainControl(*submodules_.gain_control); 2073 submodules_.agc_manager->HandleCaptureOutputUsedChange( 2074 capture_.capture_output_used); 2075 } 2076 2077 void AudioProcessingImpl::InitializeGainController2() { 2078 if (!config_.gain_controller2.enabled) { 2079 submodules_.gain_controller2.reset(); 2080 return; 2081 } 2082 // Input volume controller configuration if the AGC2 is running 2083 // and its parameters require to fully switch the gain control to 2084 // AGC2. 2085 const InputVolumeController::Config input_volume_controller_config = 2086 InputVolumeController::Config{}; 2087 submodules_.gain_controller2 = std::make_unique<GainController2>( 2088 env_, config_.gain_controller2, input_volume_controller_config, 2089 proc_fullband_sample_rate_hz(), num_output_channels(), 2090 /*use_internal_vad=*/true); 2091 submodules_.gain_controller2->SetCaptureOutputUsed( 2092 capture_.capture_output_used); 2093 } 2094 2095 void AudioProcessingImpl::InitializeNoiseSuppressor() { 2096 submodules_.noise_suppressor.reset(); 2097 2098 if (config_.noise_suppression.enabled) { 2099 auto map_level = 2100 [](AudioProcessing::Config::NoiseSuppression::Level level) { 2101 using NoiseSuppresionConfig = 2102 AudioProcessing::Config::NoiseSuppression; 2103 switch (level) { 2104 case NoiseSuppresionConfig::kLow: 2105 return NsConfig::SuppressionLevel::k6dB; 2106 case NoiseSuppresionConfig::kModerate: 2107 return NsConfig::SuppressionLevel::k12dB; 2108 case NoiseSuppresionConfig::kHigh: 2109 return NsConfig::SuppressionLevel::k18dB; 2110 case NoiseSuppresionConfig::kVeryHigh: 2111 return NsConfig::SuppressionLevel::k21dB; 2112 } 2113 RTC_CHECK_NOTREACHED(); 2114 }; 2115 2116 NsConfig cfg; 2117 cfg.target_level = map_level(config_.noise_suppression.level); 2118 submodules_.noise_suppressor = std::make_unique<NoiseSuppressor>( 2119 cfg, proc_sample_rate_hz(), num_proc_channels()); 2120 } 2121 } 2122 2123 void AudioProcessingImpl::InitializeCaptureLevelsAdjuster() { 2124 if (config_.pre_amplifier.enabled || 2125 config_.capture_level_adjustment.enabled) { 2126 // Use both the pre-amplifier and the capture level adjustment gains as 2127 // pre-gains. 2128 float pre_gain = 1.f; 2129 if (config_.pre_amplifier.enabled) { 2130 pre_gain *= config_.pre_amplifier.fixed_gain_factor; 2131 } 2132 if (config_.capture_level_adjustment.enabled) { 2133 pre_gain *= config_.capture_level_adjustment.pre_gain_factor; 2134 } 2135 2136 submodules_.capture_levels_adjuster = 2137 std::make_unique<CaptureLevelsAdjuster>( 2138 config_.capture_level_adjustment.analog_mic_gain_emulation.enabled, 2139 config_.capture_level_adjustment.analog_mic_gain_emulation 2140 .initial_level, 2141 pre_gain, config_.capture_level_adjustment.post_gain_factor); 2142 } else { 2143 submodules_.capture_levels_adjuster.reset(); 2144 } 2145 } 2146 2147 void AudioProcessingImpl::InitializeResidualEchoDetector() { 2148 if (submodules_.echo_detector) { 2149 submodules_.echo_detector->Initialize( 2150 proc_fullband_sample_rate_hz(), 1, 2151 formats_.render_processing_format.sample_rate_hz(), 1); 2152 } 2153 } 2154 2155 void AudioProcessingImpl::InitializeAnalyzer() { 2156 if (submodules_.capture_analyzer) { 2157 submodules_.capture_analyzer->Initialize(proc_fullband_sample_rate_hz(), 2158 num_proc_channels()); 2159 } 2160 } 2161 2162 void AudioProcessingImpl::InitializePostProcessor() { 2163 if (submodules_.capture_post_processor) { 2164 submodules_.capture_post_processor->Initialize( 2165 proc_fullband_sample_rate_hz(), num_proc_channels()); 2166 } 2167 } 2168 2169 void AudioProcessingImpl::InitializePreProcessor() { 2170 if (submodules_.render_pre_processor) { 2171 submodules_.render_pre_processor->Initialize( 2172 formats_.render_processing_format.sample_rate_hz(), 2173 formats_.render_processing_format.num_channels()); 2174 } 2175 } 2176 2177 void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) { 2178 if (!aec_dump_) { 2179 return; 2180 } 2181 2182 std::string experiments_description = ""; 2183 // TODO(peah): Add semicolon-separated concatenations of experiment 2184 // descriptions for other submodules. 2185 if (!!submodules_.capture_post_processor) { 2186 experiments_description += "CapturePostProcessor;"; 2187 } 2188 if (!!submodules_.render_pre_processor) { 2189 experiments_description += "RenderPreProcessor;"; 2190 } 2191 if (capture_nonlocked_.echo_controller_enabled) { 2192 experiments_description += "EchoController;"; 2193 } 2194 if (config_.gain_controller2.enabled) { 2195 experiments_description += "GainController2;"; 2196 } 2197 if (submodules_.neural_residual_echo_estimator) { 2198 experiments_description += "NeuralResidualEchoEstimator;"; 2199 } 2200 2201 InternalAPMConfig apm_config; 2202 2203 apm_config.aec_enabled = config_.echo_canceller.enabled; 2204 apm_config.aec_delay_agnostic_enabled = false; 2205 apm_config.aec_extended_filter_enabled = false; 2206 apm_config.aec_suppression_level = 0; 2207 2208 apm_config.aecm_enabled = !!submodules_.echo_control_mobile; 2209 apm_config.aecm_comfort_noise_enabled = 2210 submodules_.echo_control_mobile && 2211 submodules_.echo_control_mobile->is_comfort_noise_enabled(); 2212 apm_config.aecm_routing_mode = 2213 submodules_.echo_control_mobile 2214 ? static_cast<int>(submodules_.echo_control_mobile->routing_mode()) 2215 : 0; 2216 2217 apm_config.agc_enabled = !!submodules_.gain_control; 2218 2219 apm_config.agc_mode = submodules_.gain_control 2220 ? static_cast<int>(submodules_.gain_control->mode()) 2221 : GainControl::kAdaptiveAnalog; 2222 apm_config.agc_limiter_enabled = 2223 submodules_.gain_control ? submodules_.gain_control->is_limiter_enabled() 2224 : false; 2225 apm_config.noise_robust_agc_enabled = !!submodules_.agc_manager; 2226 2227 apm_config.hpf_enabled = config_.high_pass_filter.enabled; 2228 2229 apm_config.ns_enabled = config_.noise_suppression.enabled; 2230 apm_config.ns_level = static_cast<int>(config_.noise_suppression.level); 2231 2232 apm_config.experiments_description = experiments_description; 2233 apm_config.pre_amplifier_enabled = config_.pre_amplifier.enabled; 2234 apm_config.pre_amplifier_fixed_gain_factor = 2235 config_.pre_amplifier.fixed_gain_factor; 2236 2237 if (!forced && apm_config == apm_config_for_aec_dump_) { 2238 return; 2239 } 2240 aec_dump_->WriteConfig(apm_config); 2241 apm_config_for_aec_dump_ = apm_config; 2242 } 2243 2244 void AudioProcessingImpl::RecordUnprocessedCaptureStream( 2245 const float* const* src) { 2246 RTC_DCHECK(aec_dump_); 2247 WriteAecDumpConfigMessage(false); 2248 2249 const size_t channel_size = formats_.api_format.input_stream().num_frames(); 2250 const size_t num_channels = formats_.api_format.input_stream().num_channels(); 2251 for (size_t ch = 0u; ch < num_channels; ++ch) { 2252 aec_dump_->AddCaptureStreamInput( 2253 MonoView<const float>(src[ch], channel_size)); 2254 } 2255 RecordAudioProcessingState(); 2256 } 2257 2258 void AudioProcessingImpl::RecordUnprocessedCaptureStream( 2259 const int16_t* const data, 2260 const StreamConfig& config) { 2261 RTC_DCHECK(aec_dump_); 2262 WriteAecDumpConfigMessage(false); 2263 2264 aec_dump_->AddCaptureStreamInput(data, config.num_channels(), 2265 config.num_frames()); 2266 RecordAudioProcessingState(); 2267 } 2268 2269 void AudioProcessingImpl::RecordProcessedCaptureStream( 2270 const float* const* processed_capture_stream) { 2271 RTC_DCHECK(aec_dump_); 2272 2273 const size_t channel_size = formats_.api_format.output_stream().num_frames(); 2274 const size_t num_channels = 2275 formats_.api_format.output_stream().num_channels(); 2276 for (size_t ch = 0u; ch < num_channels; ++ch) { 2277 aec_dump_->AddCaptureStreamOutput( 2278 MonoView<const float>(processed_capture_stream[ch], channel_size)); 2279 } 2280 2281 aec_dump_->WriteCaptureStreamMessage(); 2282 } 2283 2284 void AudioProcessingImpl::RecordProcessedCaptureStream( 2285 const int16_t* const data, 2286 const StreamConfig& config) { 2287 RTC_DCHECK(aec_dump_); 2288 2289 aec_dump_->AddCaptureStreamOutput(data, config.num_channels(), 2290 config.num_frames()); 2291 aec_dump_->WriteCaptureStreamMessage(); 2292 } 2293 2294 void AudioProcessingImpl::RecordAudioProcessingState() { 2295 RTC_DCHECK(aec_dump_); 2296 AecDump::AudioProcessingState audio_proc_state; 2297 audio_proc_state.delay = capture_nonlocked_.stream_delay_ms; 2298 audio_proc_state.drift = 0; 2299 audio_proc_state.applied_input_volume = capture_.applied_input_volume; 2300 audio_proc_state.keypress = capture_.key_pressed; 2301 aec_dump_->AddAudioProcessingState(audio_proc_state); 2302 } 2303 2304 AudioProcessingImpl::ApmCaptureState::ApmCaptureState() 2305 : was_stream_delay_set(false), 2306 capture_output_used(true), 2307 capture_output_used_last_frame(true), 2308 key_pressed(false), 2309 capture_processing_format(kSampleRate16kHz), 2310 split_rate(kSampleRate16kHz), 2311 echo_path_gain_change(false), 2312 prev_pre_adjustment_gain(-1.0f), 2313 playout_volume(-1), 2314 prev_playout_volume(-1), 2315 applied_input_volume_changed(false) {} 2316 2317 AudioProcessingImpl::ApmCaptureState::~ApmCaptureState() = default; 2318 2319 AudioProcessingImpl::ApmRenderState::ApmRenderState() = default; 2320 2321 AudioProcessingImpl::ApmRenderState::~ApmRenderState() = default; 2322 2323 AudioProcessingImpl::ApmStatsReporter::ApmStatsReporter() 2324 : stats_message_queue_(1) {} 2325 2326 AudioProcessingImpl::ApmStatsReporter::~ApmStatsReporter() = default; 2327 2328 AudioProcessingStats AudioProcessingImpl::ApmStatsReporter::GetStatistics() { 2329 MutexLock lock_stats(&mutex_stats_); 2330 bool new_stats_available = stats_message_queue_.Remove(&cached_stats_); 2331 // If the message queue is full, return the cached stats. 2332 static_cast<void>(new_stats_available); 2333 2334 return cached_stats_; 2335 } 2336 2337 void AudioProcessingImpl::ApmStatsReporter::UpdateStatistics( 2338 const AudioProcessingStats& new_stats) { 2339 AudioProcessingStats stats_to_queue = new_stats; 2340 bool stats_message_passed = stats_message_queue_.Insert(&stats_to_queue); 2341 // If the message queue is full, discard the new stats. 2342 static_cast<void>(stats_message_passed); 2343 } 2344 2345 } // namespace webrtc