blob: b1187fab1f2ec16e4fa9747a23fac6397ffb8b9e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org40654032012-01-30 20:51:15 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/audio_processing_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Michael Graczyk86c6d332015-07-23 11:41:39 -070013#include <algorithm>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <cstdint>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
alessiob3ec96df2017-05-22 06:57:06 -070016#include <string>
Yves Gerey988cc082018-10-23 12:03:01 +020017#include <type_traits>
18#include <utility>
niklase@google.com470e71d2011-07-07 08:21:25 +000019
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "absl/types/optional.h"
21#include "api/array_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "common_audio/audio_converter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "common_audio/include/audio_util.h"
Per Åhgren200feba2019-03-06 04:16:46 +010024#include "modules/audio_processing/aec3/echo_canceller3.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/audio_processing/agc/agc_manager_direct.h"
Alex Loikob5c9a792018-04-16 16:31:22 +020026#include "modules/audio_processing/agc2/gain_applier.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/audio_processing/audio_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "modules/audio_processing/common.h"
29#include "modules/audio_processing/echo_cancellation_impl.h"
30#include "modules/audio_processing/echo_control_mobile_impl.h"
Sam Zackrissonf0d1c032019-03-27 13:28:08 +010031#include "modules/audio_processing/gain_control_config_proxy.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "modules/audio_processing/gain_control_for_experimental_agc.h"
33#include "modules/audio_processing/gain_control_impl.h"
Alex Loikoe36e8bb2018-02-16 11:54:07 +010034#include "modules/audio_processing/gain_controller2.h"
Per Åhgren0aefbf02019-08-23 21:29:17 +020035#include "modules/audio_processing/high_pass_filter.h"
Yves Gerey988cc082018-10-23 12:03:01 +020036#include "modules/audio_processing/include/audio_frame_view.h"
Per Åhgrend2650d12018-10-02 17:00:59 +020037#include "modules/audio_processing/level_estimator_impl.h"
Per Åhgren13735822018-02-12 21:42:56 +010038#include "modules/audio_processing/logging/apm_data_dumper.h"
Per Åhgrend2650d12018-10-02 17:00:59 +020039#include "modules/audio_processing/noise_suppression_impl.h"
Sam Zackrisson23513132019-01-11 15:10:32 +010040#include "modules/audio_processing/noise_suppression_proxy.h"
Per Åhgrend2650d12018-10-02 17:00:59 +020041#include "modules/audio_processing/residual_echo_detector.h"
42#include "modules/audio_processing/transient/transient_suppressor.h"
43#include "modules/audio_processing/voice_detection_impl.h"
Steve Anton10542f22019-01-11 09:11:00 -080044#include "rtc_base/atomic_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020045#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080046#include "rtc_base/constructor_magic.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020047#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080048#include "rtc_base/ref_counted_object.h"
49#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020050#include "rtc_base/trace_event.h"
Sam Zackrissonfeee1e42019-09-20 07:50:35 +020051#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020052#include "system_wrappers/include/metrics.h"
andrew@webrtc.org7bf26462011-12-03 00:03:31 +000053
Michael Graczyk86c6d332015-07-23 11:41:39 -070054#define RETURN_ON_ERR(expr) \
55 do { \
56 int err = (expr); \
57 if (err != kNoError) { \
58 return err; \
59 } \
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000060 } while (0)
61
niklase@google.com470e71d2011-07-07 08:21:25 +000062namespace webrtc {
aluebsdf6416a2016-03-16 18:26:35 -070063
kwibergd59d3bb2016-09-13 07:49:33 -070064constexpr int AudioProcessing::kNativeSampleRatesHz[];
Alex Loiko73ec0192018-05-15 10:52:28 +020065constexpr int kRuntimeSettingQueueSize = 100;
aluebsdf6416a2016-03-16 18:26:35 -070066
Michael Graczyk86c6d332015-07-23 11:41:39 -070067namespace {
68
69static bool LayoutHasKeyboard(AudioProcessing::ChannelLayout layout) {
70 switch (layout) {
71 case AudioProcessing::kMono:
72 case AudioProcessing::kStereo:
73 return false;
74 case AudioProcessing::kMonoAndKeyboard:
75 case AudioProcessing::kStereoAndKeyboard:
76 return true;
77 }
78
kwiberg9e2be5f2016-09-14 05:23:22 -070079 RTC_NOTREACHED();
Michael Graczyk86c6d332015-07-23 11:41:39 -070080 return false;
81}
aluebsdf6416a2016-03-16 18:26:35 -070082
peah2ace3f92016-09-10 04:42:27 -070083bool SampleRateSupportsMultiBand(int sample_rate_hz) {
aluebsdf6416a2016-03-16 18:26:35 -070084 return sample_rate_hz == AudioProcessing::kSampleRate32kHz ||
85 sample_rate_hz == AudioProcessing::kSampleRate48kHz;
86}
87
Per Åhgrenc8626b62019-08-23 15:49:51 +020088// Identify the native processing rate that best handles a sample rate.
Per Åhgrenfcbe4072019-09-15 00:27:58 +020089int SuitableProcessRate(int minimum_rate,
90 int max_splitting_rate,
91 bool band_splitting_required) {
Per Åhgrenc8626b62019-08-23 15:49:51 +020092 const int uppermost_native_rate =
Per Åhgrenfcbe4072019-09-15 00:27:58 +020093 band_splitting_required ? max_splitting_rate : 48000;
Per Åhgrenc8626b62019-08-23 15:49:51 +020094 for (auto rate : {16000, 32000, 48000}) {
peah2ace3f92016-09-10 04:42:27 -070095 if (rate >= uppermost_native_rate) {
96 return uppermost_native_rate;
97 }
98 if (rate >= minimum_rate) {
aluebsdf6416a2016-03-16 18:26:35 -070099 return rate;
100 }
101 }
peah2ace3f92016-09-10 04:42:27 -0700102 RTC_NOTREACHED();
103 return uppermost_native_rate;
aluebsdf6416a2016-03-16 18:26:35 -0700104}
105
Sam Zackrisson23513132019-01-11 15:10:32 +0100106NoiseSuppression::Level NsConfigLevelToInterfaceLevel(
107 AudioProcessing::Config::NoiseSuppression::Level level) {
108 using NsConfig = AudioProcessing::Config::NoiseSuppression;
109 switch (level) {
110 case NsConfig::kLow:
111 return NoiseSuppression::kLow;
112 case NsConfig::kModerate:
113 return NoiseSuppression::kModerate;
114 case NsConfig::kHigh:
115 return NoiseSuppression::kHigh;
116 case NsConfig::kVeryHigh:
117 return NoiseSuppression::kVeryHigh;
118 default:
119 RTC_NOTREACHED();
120 }
121}
122
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100123GainControl::Mode Agc1ConfigModeToInterfaceMode(
124 AudioProcessing::Config::GainController1::Mode mode) {
125 using Agc1Config = AudioProcessing::Config::GainController1;
126 switch (mode) {
127 case Agc1Config::kAdaptiveAnalog:
128 return GainControl::kAdaptiveAnalog;
129 case Agc1Config::kAdaptiveDigital:
130 return GainControl::kAdaptiveDigital;
131 case Agc1Config::kFixedDigital:
132 return GainControl::kFixedDigital;
133 }
134}
135
peah9e6a2902017-05-15 07:19:21 -0700136// Maximum lengths that frame of samples being passed from the render side to
137// the capture side can have (does not apply to AEC3).
138static const size_t kMaxAllowedValuesOfSamplesPerBand = 160;
139static const size_t kMaxAllowedValuesOfSamplesPerFrame = 480;
140
peah764e3642016-10-22 05:04:30 -0700141// Maximum number of frames to buffer in the render queue.
142// TODO(peah): Decrease this once we properly handle hugely unbalanced
143// reverse and forward call numbers.
144static const size_t kMaxNumFramesToBuffer = 100;
Michael Graczyk86c6d332015-07-23 11:41:39 -0700145} // namespace
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000146
147// Throughout webrtc, it's assumed that success is represented by zero.
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000148static_assert(AudioProcessing::kNoError == 0, "kNoError must be zero");
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000149
Sam Zackrisson0beac582017-09-25 12:04:02 +0200150AudioProcessingImpl::ApmSubmoduleStates::ApmSubmoduleStates(
Alex Loiko5825aa62017-12-18 16:02:40 +0100151 bool capture_post_processor_enabled,
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200152 bool render_pre_processor_enabled,
153 bool capture_analyzer_enabled)
Alex Loiko5825aa62017-12-18 16:02:40 +0100154 : capture_post_processor_enabled_(capture_post_processor_enabled),
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200155 render_pre_processor_enabled_(render_pre_processor_enabled),
156 capture_analyzer_enabled_(capture_analyzer_enabled) {}
peah2ace3f92016-09-10 04:42:27 -0700157
158bool AudioProcessingImpl::ApmSubmoduleStates::Update(
Sam Zackrissoncb1b5562018-09-28 14:15:09 +0200159 bool high_pass_filter_enabled,
peah2ace3f92016-09-10 04:42:27 -0700160 bool echo_canceller_enabled,
161 bool mobile_echo_controller_enabled,
ivoc9f4a4a02016-10-28 05:39:16 -0700162 bool residual_echo_detector_enabled,
peah2ace3f92016-09-10 04:42:27 -0700163 bool noise_suppressor_enabled,
peah2ace3f92016-09-10 04:42:27 -0700164 bool adaptive_gain_controller_enabled,
alessiob3ec96df2017-05-22 06:57:06 -0700165 bool gain_controller2_enabled,
Alex Loikob5c9a792018-04-16 16:31:22 +0200166 bool pre_amplifier_enabled,
Gustaf Ullbergce045ac2017-10-16 13:49:04 +0200167 bool echo_controller_enabled,
peah2ace3f92016-09-10 04:42:27 -0700168 bool voice_activity_detector_enabled,
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100169 bool private_voice_detector_enabled,
peah2ace3f92016-09-10 04:42:27 -0700170 bool level_estimator_enabled,
171 bool transient_suppressor_enabled) {
172 bool changed = false;
Sam Zackrissoncb1b5562018-09-28 14:15:09 +0200173 changed |= (high_pass_filter_enabled != high_pass_filter_enabled_);
peah2ace3f92016-09-10 04:42:27 -0700174 changed |= (echo_canceller_enabled != echo_canceller_enabled_);
175 changed |=
176 (mobile_echo_controller_enabled != mobile_echo_controller_enabled_);
ivoc9f4a4a02016-10-28 05:39:16 -0700177 changed |=
178 (residual_echo_detector_enabled != residual_echo_detector_enabled_);
peah2ace3f92016-09-10 04:42:27 -0700179 changed |= (noise_suppressor_enabled != noise_suppressor_enabled_);
180 changed |=
peah2ace3f92016-09-10 04:42:27 -0700181 (adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_);
Per Åhgren6ee75fd2019-04-26 11:33:37 +0200182 changed |= (gain_controller2_enabled != gain_controller2_enabled_);
Alex Loikob5c9a792018-04-16 16:31:22 +0200183 changed |= (pre_amplifier_enabled_ != pre_amplifier_enabled);
Gustaf Ullbergce045ac2017-10-16 13:49:04 +0200184 changed |= (echo_controller_enabled != echo_controller_enabled_);
peah2ace3f92016-09-10 04:42:27 -0700185 changed |= (level_estimator_enabled != level_estimator_enabled_);
186 changed |=
187 (voice_activity_detector_enabled != voice_activity_detector_enabled_);
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100188 changed |=
189 (private_voice_detector_enabled != private_voice_detector_enabled_);
peah2ace3f92016-09-10 04:42:27 -0700190 changed |= (transient_suppressor_enabled != transient_suppressor_enabled_);
191 if (changed) {
Sam Zackrissoncb1b5562018-09-28 14:15:09 +0200192 high_pass_filter_enabled_ = high_pass_filter_enabled;
peah2ace3f92016-09-10 04:42:27 -0700193 echo_canceller_enabled_ = echo_canceller_enabled;
194 mobile_echo_controller_enabled_ = mobile_echo_controller_enabled;
ivoc9f4a4a02016-10-28 05:39:16 -0700195 residual_echo_detector_enabled_ = residual_echo_detector_enabled;
peah2ace3f92016-09-10 04:42:27 -0700196 noise_suppressor_enabled_ = noise_suppressor_enabled;
peah2ace3f92016-09-10 04:42:27 -0700197 adaptive_gain_controller_enabled_ = adaptive_gain_controller_enabled;
alessiob3ec96df2017-05-22 06:57:06 -0700198 gain_controller2_enabled_ = gain_controller2_enabled;
Alex Loikob5c9a792018-04-16 16:31:22 +0200199 pre_amplifier_enabled_ = pre_amplifier_enabled;
Gustaf Ullbergce045ac2017-10-16 13:49:04 +0200200 echo_controller_enabled_ = echo_controller_enabled;
peah2ace3f92016-09-10 04:42:27 -0700201 level_estimator_enabled_ = level_estimator_enabled;
202 voice_activity_detector_enabled_ = voice_activity_detector_enabled;
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100203 private_voice_detector_enabled_ = private_voice_detector_enabled;
peah2ace3f92016-09-10 04:42:27 -0700204 transient_suppressor_enabled_ = transient_suppressor_enabled;
205 }
206
207 changed |= first_update_;
208 first_update_ = false;
209 return changed;
210}
211
212bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandSubModulesActive()
213 const {
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100214 return CaptureMultiBandProcessingActive() ||
215 voice_activity_detector_enabled_ || private_voice_detector_enabled_;
peah2ace3f92016-09-10 04:42:27 -0700216}
217
218bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandProcessingActive()
219 const {
Sam Zackrissoncb1b5562018-09-28 14:15:09 +0200220 return high_pass_filter_enabled_ || echo_canceller_enabled_ ||
peah2ace3f92016-09-10 04:42:27 -0700221 mobile_echo_controller_enabled_ || noise_suppressor_enabled_ ||
Sam Zackrisson9394f6f2018-06-14 10:11:35 +0200222 adaptive_gain_controller_enabled_ || echo_controller_enabled_;
peah2ace3f92016-09-10 04:42:27 -0700223}
224
peah23ac8b42017-05-23 05:33:56 -0700225bool AudioProcessingImpl::ApmSubmoduleStates::CaptureFullBandProcessingActive()
226 const {
Alex Loikob5c9a792018-04-16 16:31:22 +0200227 return gain_controller2_enabled_ || capture_post_processor_enabled_ ||
228 pre_amplifier_enabled_;
peah23ac8b42017-05-23 05:33:56 -0700229}
230
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200231bool AudioProcessingImpl::ApmSubmoduleStates::CaptureAnalyzerActive() const {
232 return capture_analyzer_enabled_;
233}
234
peah2ace3f92016-09-10 04:42:27 -0700235bool AudioProcessingImpl::ApmSubmoduleStates::RenderMultiBandSubModulesActive()
236 const {
237 return RenderMultiBandProcessingActive() || echo_canceller_enabled_ ||
ivoc20270be2016-11-15 05:24:35 -0800238 mobile_echo_controller_enabled_ || adaptive_gain_controller_enabled_ ||
Gustaf Ullbergce045ac2017-10-16 13:49:04 +0200239 echo_controller_enabled_;
peah2ace3f92016-09-10 04:42:27 -0700240}
241
Alex Loiko5825aa62017-12-18 16:02:40 +0100242bool AudioProcessingImpl::ApmSubmoduleStates::RenderFullBandProcessingActive()
243 const {
244 return render_pre_processor_enabled_;
245}
246
peah2ace3f92016-09-10 04:42:27 -0700247bool AudioProcessingImpl::ApmSubmoduleStates::RenderMultiBandProcessingActive()
248 const {
peah2ace3f92016-09-10 04:42:27 -0700249 return false;
peah2ace3f92016-09-10 04:42:27 -0700250}
251
Per Åhgren0aefbf02019-08-23 21:29:17 +0200252bool AudioProcessingImpl::ApmSubmoduleStates::HighPassFilteringRequired()
253 const {
Sam Zackrissoncb1b5562018-09-28 14:15:09 +0200254 return high_pass_filter_enabled_ || echo_canceller_enabled_ ||
255 mobile_echo_controller_enabled_ || noise_suppressor_enabled_;
256}
257
solenberg5e465c32015-12-08 13:22:33 -0800258struct AudioProcessingImpl::ApmPublicSubmodules {
peahbfa97112016-03-10 21:09:04 -0800259 ApmPublicSubmodules() {}
solenberg5e465c32015-12-08 13:22:33 -0800260 // Accessed externally of APM without any lock acquired.
Sam Zackrisson23513132019-01-11 15:10:32 +0100261 // TODO(bugs.webrtc.org/9947): Move these submodules into private_submodules_
262 // when their pointer-to-submodule API functions are gone.
kwiberg88788ad2016-02-19 07:04:49 -0800263 std::unique_ptr<LevelEstimatorImpl> level_estimator;
264 std::unique_ptr<NoiseSuppressionImpl> noise_suppression;
Sam Zackrisson23513132019-01-11 15:10:32 +0100265 std::unique_ptr<NoiseSuppressionProxy> noise_suppression_proxy;
kwiberg88788ad2016-02-19 07:04:49 -0800266 std::unique_ptr<VoiceDetectionImpl> voice_detection;
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100267 std::unique_ptr<GainControlImpl> gain_control;
kwiberg88788ad2016-02-19 07:04:49 -0800268 std::unique_ptr<GainControlForExperimentalAgc>
peahbe615622016-02-13 16:40:47 -0800269 gain_control_for_experimental_agc;
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100270 std::unique_ptr<GainControlConfigProxy> gain_control_config_proxy;
solenberg5e465c32015-12-08 13:22:33 -0800271
272 // Accessed internally from both render and capture.
kwiberg88788ad2016-02-19 07:04:49 -0800273 std::unique_ptr<TransientSuppressor> transient_suppressor;
solenberg5e465c32015-12-08 13:22:33 -0800274};
275
276struct AudioProcessingImpl::ApmPrivateSubmodules {
Sam Zackrissondb389722018-06-21 10:12:24 +0200277 ApmPrivateSubmodules(std::unique_ptr<CustomProcessing> capture_post_processor,
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100278 std::unique_ptr<CustomProcessing> render_pre_processor,
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200279 rtc::scoped_refptr<EchoDetector> echo_detector,
280 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
Sam Zackrissondb389722018-06-21 10:12:24 +0200281 : echo_detector(std::move(echo_detector)),
Alex Loiko5825aa62017-12-18 16:02:40 +0100282 capture_post_processor(std::move(capture_post_processor)),
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200283 render_pre_processor(std::move(render_pre_processor)),
284 capture_analyzer(std::move(capture_analyzer)) {}
solenberg5e465c32015-12-08 13:22:33 -0800285 // Accessed internally from capture or during initialization
kwiberg88788ad2016-02-19 07:04:49 -0800286 std::unique_ptr<AgcManagerDirect> agc_manager;
alessiob3ec96df2017-05-22 06:57:06 -0700287 std::unique_ptr<GainController2> gain_controller2;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200288 std::unique_ptr<HighPassFilter> high_pass_filter;
Ivo Creusend1f970d2018-06-14 11:02:03 +0200289 rtc::scoped_refptr<EchoDetector> echo_detector;
Sam Zackrisson7f4dfa42018-11-01 08:59:29 +0100290 std::unique_ptr<EchoCancellationImpl> echo_cancellation;
Sam Zackrissonc22f5512018-11-05 16:10:00 +0100291 std::unique_ptr<EchoControl> echo_controller;
292 std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
Alex Loiko5825aa62017-12-18 16:02:40 +0100293 std::unique_ptr<CustomProcessing> capture_post_processor;
294 std::unique_ptr<CustomProcessing> render_pre_processor;
Alex Loikob5c9a792018-04-16 16:31:22 +0200295 std::unique_ptr<GainApplier> pre_amplifier;
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200296 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer;
Sam Zackrissonb24c00f2018-11-26 16:18:25 +0100297 std::unique_ptr<LevelEstimatorImpl> output_level_estimator;
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100298 std::unique_ptr<VoiceDetectionImpl> voice_detector;
solenberg5e465c32015-12-08 13:22:33 -0800299};
300
Ivo Creusen5ec7e122017-12-22 11:35:59 +0100301AudioProcessingBuilder::AudioProcessingBuilder() = default;
302AudioProcessingBuilder::~AudioProcessingBuilder() = default;
303
304AudioProcessingBuilder& AudioProcessingBuilder::SetCapturePostProcessing(
305 std::unique_ptr<CustomProcessing> capture_post_processing) {
306 capture_post_processing_ = std::move(capture_post_processing);
307 return *this;
308}
309
310AudioProcessingBuilder& AudioProcessingBuilder::SetRenderPreProcessing(
311 std::unique_ptr<CustomProcessing> render_pre_processing) {
312 render_pre_processing_ = std::move(render_pre_processing);
313 return *this;
314}
315
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200316AudioProcessingBuilder& AudioProcessingBuilder::SetCaptureAnalyzer(
317 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer) {
318 capture_analyzer_ = std::move(capture_analyzer);
319 return *this;
320}
321
Ivo Creusen5ec7e122017-12-22 11:35:59 +0100322AudioProcessingBuilder& AudioProcessingBuilder::SetEchoControlFactory(
323 std::unique_ptr<EchoControlFactory> echo_control_factory) {
324 echo_control_factory_ = std::move(echo_control_factory);
325 return *this;
326}
327
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100328AudioProcessingBuilder& AudioProcessingBuilder::SetEchoDetector(
Ivo Creusend1f970d2018-06-14 11:02:03 +0200329 rtc::scoped_refptr<EchoDetector> echo_detector) {
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100330 echo_detector_ = std::move(echo_detector);
331 return *this;
332}
333
Ivo Creusen5ec7e122017-12-22 11:35:59 +0100334AudioProcessing* AudioProcessingBuilder::Create() {
335 webrtc::Config config;
336 return Create(config);
337}
338
339AudioProcessing* AudioProcessingBuilder::Create(const webrtc::Config& config) {
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100340 AudioProcessingImpl* apm = new rtc::RefCountedObject<AudioProcessingImpl>(
341 config, std::move(capture_post_processing_),
342 std::move(render_pre_processing_), std::move(echo_control_factory_),
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200343 std::move(echo_detector_), std::move(capture_analyzer_));
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100344 if (apm->Initialize() != AudioProcessing::kNoError) {
345 delete apm;
346 apm = nullptr;
347 }
348 return apm;
Ivo Creusen5ec7e122017-12-22 11:35:59 +0100349}
350
peah88ac8532016-09-12 16:47:25 -0700351AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200352 : AudioProcessingImpl(config,
353 /*capture_post_processor=*/nullptr,
354 /*render_pre_processor=*/nullptr,
355 /*echo_control_factory=*/nullptr,
356 /*echo_detector=*/nullptr,
357 /*capture_analyzer=*/nullptr) {}
aluebs@webrtc.orgd82f55d2015-01-15 18:07:21 +0000358
Per Åhgren13735822018-02-12 21:42:56 +0100359int AudioProcessingImpl::instance_count_ = 0;
360
Sam Zackrisson0beac582017-09-25 12:04:02 +0200361AudioProcessingImpl::AudioProcessingImpl(
362 const webrtc::Config& config,
Alex Loiko5825aa62017-12-18 16:02:40 +0100363 std::unique_ptr<CustomProcessing> capture_post_processor,
364 std::unique_ptr<CustomProcessing> render_pre_processor,
Gustaf Ullberg002ef282017-10-12 15:13:17 +0200365 std::unique_ptr<EchoControlFactory> echo_control_factory,
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200366 rtc::scoped_refptr<EchoDetector> echo_detector,
367 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
Per Åhgren13735822018-02-12 21:42:56 +0100368 : data_dumper_(
369 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Alex Loiko73ec0192018-05-15 10:52:28 +0200370 capture_runtime_settings_(kRuntimeSettingQueueSize),
371 render_runtime_settings_(kRuntimeSettingQueueSize),
372 capture_runtime_settings_enqueuer_(&capture_runtime_settings_),
373 render_runtime_settings_enqueuer_(&render_runtime_settings_),
Gustaf Ullberg002ef282017-10-12 15:13:17 +0200374 echo_control_factory_(std::move(echo_control_factory)),
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200375 submodule_states_(!!capture_post_processor,
376 !!render_pre_processor,
377 !!capture_analyzer),
peah8271d042016-11-22 07:24:52 -0800378 public_submodules_(new ApmPublicSubmodules()),
Sam Zackrisson0beac582017-09-25 12:04:02 +0200379 private_submodules_(
Sam Zackrissondb389722018-06-21 10:12:24 +0200380 new ApmPrivateSubmodules(std::move(capture_post_processor),
Ivo Creusen09fa4b02018-01-11 16:08:54 +0100381 std::move(render_pre_processor),
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200382 std::move(echo_detector),
383 std::move(capture_analyzer))),
peahdf3efa82015-11-28 12:35:15 -0800384 constants_(config.Get<ExperimentalAgc>().startup_min_volume,
henrik.lundinbd681b92016-12-05 09:08:42 -0800385 config.Get<ExperimentalAgc>().clipped_level_min,
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000386#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
Alex Loikod9342442018-09-10 13:59:41 +0200387 /* enabled= */ false,
388 /* enabled_agc2_level_estimator= */ false,
389 /* digital_adaptive_disabled= */ false,
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200390 /* analyze_before_aec= */ false,
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000391#else
Alex Loiko64cb83b2018-07-02 13:38:19 +0200392 config.Get<ExperimentalAgc>().enabled,
393 config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
Alex Loikod9342442018-09-10 13:59:41 +0200394 config.Get<ExperimentalAgc>().digital_adaptive_disabled,
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200395 config.Get<ExperimentalAgc>().analyze_before_aec,
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000396#endif
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200397 !field_trial::IsEnabled(
398 "WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"),
399 !field_trial::IsEnabled(
400 "WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch")),
andrew1c7075f2015-06-24 18:14:14 -0700401#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
Sam Zackrisson9394f6f2018-06-14 10:11:35 +0200402 capture_(false),
andrew1c7075f2015-06-24 18:14:14 -0700403#else
Sam Zackrisson9394f6f2018-06-14 10:11:35 +0200404 capture_(config.Get<ExperimentalNs>().enabled),
andrew1c7075f2015-06-24 18:14:14 -0700405#endif
Alessio Bazzicacc22f512018-08-30 13:01:34 +0200406 capture_nonlocked_() {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100407 // Mark Echo Controller enabled if a factory is injected.
408 capture_nonlocked_.echo_controller_enabled =
409 static_cast<bool>(echo_control_factory_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100411 public_submodules_->gain_control.reset(new GainControlImpl());
Sam Zackrisson421c8592019-02-11 13:39:46 +0100412 public_submodules_->level_estimator.reset(
413 new LevelEstimatorImpl(&crit_capture_));
414 public_submodules_->noise_suppression.reset(
415 new NoiseSuppressionImpl(&crit_capture_));
416 public_submodules_->noise_suppression_proxy.reset(new NoiseSuppressionProxy(
417 this, public_submodules_->noise_suppression.get()));
418 public_submodules_->voice_detection.reset(
419 new VoiceDetectionImpl(&crit_capture_));
420 public_submodules_->gain_control_for_experimental_agc.reset(
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100421 new GainControlForExperimentalAgc(
422 public_submodules_->gain_control.get()));
423 public_submodules_->gain_control_config_proxy.reset(
424 new GainControlConfigProxy(&crit_capture_, this, agc1()));
Gustaf Ullbergce045ac2017-10-16 13:49:04 +0200425
Sam Zackrisson421c8592019-02-11 13:39:46 +0100426 // If no echo detector is injected, use the ResidualEchoDetector.
427 if (!private_submodules_->echo_detector) {
428 private_submodules_->echo_detector =
429 new rtc::RefCountedObject<ResidualEchoDetector>();
peahdf3efa82015-11-28 12:35:15 -0800430 }
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000431
Sam Zackrisson421c8592019-02-11 13:39:46 +0100432 // TODO(alessiob): Move the injected gain controller once injection is
433 // implemented.
434 private_submodules_->gain_controller2.reset(new GainController2());
435
436 RTC_LOG(LS_INFO) << "Capture analyzer activated: "
437 << !!private_submodules_->capture_analyzer
438 << "\nCapture post processor activated: "
439 << !!private_submodules_->capture_post_processor
440 << "\nRender pre processor activated: "
441 << !!private_submodules_->render_pre_processor;
442
andrew@webrtc.orge84978f2014-01-25 02:09:06 +0000443 SetExtraOptions(config);
niklase@google.com470e71d2011-07-07 08:21:25 +0000444}
445
446AudioProcessingImpl::~AudioProcessingImpl() {
peahdf3efa82015-11-28 12:35:15 -0800447 // Depends on gain_control_ and
peahbe615622016-02-13 16:40:47 -0800448 // public_submodules_->gain_control_for_experimental_agc.
peahdf3efa82015-11-28 12:35:15 -0800449 private_submodules_->agc_manager.reset();
450 // Depends on gain_control_.
peahbe615622016-02-13 16:40:47 -0800451 public_submodules_->gain_control_for_experimental_agc.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000452}
453
niklase@google.com470e71d2011-07-07 08:21:25 +0000454int AudioProcessingImpl::Initialize() {
peahdf3efa82015-11-28 12:35:15 -0800455 // Run in a single-threaded manner during initialization.
456 rtc::CritScope cs_render(&crit_render_);
457 rtc::CritScope cs_capture(&crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 return InitializeLocked();
459}
460
peahde65ddc2016-09-16 15:02:15 -0700461int AudioProcessingImpl::Initialize(int capture_input_sample_rate_hz,
462 int capture_output_sample_rate_hz,
463 int render_input_sample_rate_hz,
464 ChannelLayout capture_input_layout,
465 ChannelLayout capture_output_layout,
466 ChannelLayout render_input_layout) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700467 const ProcessingConfig processing_config = {
peahde65ddc2016-09-16 15:02:15 -0700468 {{capture_input_sample_rate_hz, ChannelsFromLayout(capture_input_layout),
469 LayoutHasKeyboard(capture_input_layout)},
470 {capture_output_sample_rate_hz,
471 ChannelsFromLayout(capture_output_layout),
472 LayoutHasKeyboard(capture_output_layout)},
473 {render_input_sample_rate_hz, ChannelsFromLayout(render_input_layout),
474 LayoutHasKeyboard(render_input_layout)},
475 {render_input_sample_rate_hz, ChannelsFromLayout(render_input_layout),
476 LayoutHasKeyboard(render_input_layout)}}};
Michael Graczyk86c6d332015-07-23 11:41:39 -0700477
478 return Initialize(processing_config);
479}
480
481int AudioProcessingImpl::Initialize(const ProcessingConfig& processing_config) {
peahdf3efa82015-11-28 12:35:15 -0800482 // Run in a single-threaded manner during initialization.
483 rtc::CritScope cs_render(&crit_render_);
484 rtc::CritScope cs_capture(&crit_capture_);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700485 return InitializeLocked(processing_config);
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000486}
487
peahdf3efa82015-11-28 12:35:15 -0800488int AudioProcessingImpl::MaybeInitializeRender(
peah81b9bfe2015-11-27 02:47:28 -0800489 const ProcessingConfig& processing_config) {
peahdf3efa82015-11-28 12:35:15 -0800490 // Called from both threads. Thread check is therefore not possible.
Oskar Sundbom4b276482019-05-23 14:28:00 +0200491 if (processing_config == formats_.api_format) {
peah192164e2015-11-17 02:16:45 -0800492 return kNoError;
493 }
peahdf3efa82015-11-28 12:35:15 -0800494
495 rtc::CritScope cs_capture(&crit_capture_);
peah192164e2015-11-17 02:16:45 -0800496 return InitializeLocked(processing_config);
497}
498
niklase@google.com470e71d2011-07-07 08:21:25 +0000499int AudioProcessingImpl::InitializeLocked() {
Per Åhgren4bdced52017-06-27 16:00:38 +0200500 UpdateActiveSubmoduleStates();
501
Per Åhgrend47941e2019-08-22 11:51:13 +0200502 const int render_audiobuffer_sample_rate_hz =
peahdf3efa82015-11-28 12:35:15 -0800503 formats_.api_format.reverse_output_stream().num_frames() == 0
Per Åhgrend47941e2019-08-22 11:51:13 +0200504 ? formats_.render_processing_format.sample_rate_hz()
505 : formats_.api_format.reverse_output_stream().sample_rate_hz();
peahdf3efa82015-11-28 12:35:15 -0800506 if (formats_.api_format.reverse_input_stream().num_channels() > 0) {
507 render_.render_audio.reset(new AudioBuffer(
Per Åhgrend47941e2019-08-22 11:51:13 +0200508 formats_.api_format.reverse_input_stream().sample_rate_hz(),
peahdf3efa82015-11-28 12:35:15 -0800509 formats_.api_format.reverse_input_stream().num_channels(),
Per Åhgrend47941e2019-08-22 11:51:13 +0200510 formats_.render_processing_format.sample_rate_hz(),
peahde65ddc2016-09-16 15:02:15 -0700511 formats_.render_processing_format.num_channels(),
Per Åhgrend47941e2019-08-22 11:51:13 +0200512 render_audiobuffer_sample_rate_hz,
513 formats_.render_processing_format.num_channels()));
peah2ace3f92016-09-10 04:42:27 -0700514 if (formats_.api_format.reverse_input_stream() !=
515 formats_.api_format.reverse_output_stream()) {
kwibergc2b785d2016-02-24 05:22:32 -0800516 render_.render_converter = AudioConverter::Create(
peahdf3efa82015-11-28 12:35:15 -0800517 formats_.api_format.reverse_input_stream().num_channels(),
518 formats_.api_format.reverse_input_stream().num_frames(),
519 formats_.api_format.reverse_output_stream().num_channels(),
kwibergc2b785d2016-02-24 05:22:32 -0800520 formats_.api_format.reverse_output_stream().num_frames());
ekmeyerson60d9b332015-08-14 10:35:55 -0700521 } else {
peahdf3efa82015-11-28 12:35:15 -0800522 render_.render_converter.reset(nullptr);
ekmeyerson60d9b332015-08-14 10:35:55 -0700523 }
Michael Graczyk86c6d332015-07-23 11:41:39 -0700524 } else {
peahdf3efa82015-11-28 12:35:15 -0800525 render_.render_audio.reset(nullptr);
526 render_.render_converter.reset(nullptr);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700527 }
peahce4d9152017-05-19 01:28:05 -0700528
Per Åhgrend47941e2019-08-22 11:51:13 +0200529 capture_.capture_audio.reset(new AudioBuffer(
530 formats_.api_format.input_stream().sample_rate_hz(),
531 formats_.api_format.input_stream().num_channels(),
532 capture_nonlocked_.capture_processing_format.sample_rate_hz(),
533 formats_.api_format.output_stream().num_channels(),
534 formats_.api_format.output_stream().sample_rate_hz(),
535 formats_.api_format.output_stream().num_channels()));
niklase@google.com470e71d2011-07-07 08:21:25 +0000536
peah764e3642016-10-22 05:04:30 -0700537 AllocateRenderQueue();
538
peah135259a2016-10-28 03:12:11 -0700539 public_submodules_->gain_control->Initialize(num_proc_channels(),
540 proc_sample_rate_hz());
peahde65ddc2016-09-16 15:02:15 -0700541 if (constants_.use_experimental_agc) {
542 if (!private_submodules_->agc_manager.get()) {
543 private_submodules_->agc_manager.reset(new AgcManagerDirect(
544 public_submodules_->gain_control.get(),
545 public_submodules_->gain_control_for_experimental_agc.get(),
Alex Loiko64cb83b2018-07-02 13:38:19 +0200546 constants_.agc_startup_min_volume, constants_.agc_clipped_level_min,
547 constants_.use_experimental_agc_agc2_level_estimation,
548 constants_.use_experimental_agc_agc2_digital_adaptive));
peahde65ddc2016-09-16 15:02:15 -0700549 }
550 private_submodules_->agc_manager->Initialize();
551 private_submodules_->agc_manager->SetCaptureMuted(
552 capture_.output_will_be_muted);
peah135259a2016-10-28 03:12:11 -0700553 public_submodules_->gain_control_for_experimental_agc->Initialize();
peahde65ddc2016-09-16 15:02:15 -0700554 }
Bjorn Volckeradc46c42015-04-15 11:42:40 +0200555 InitializeTransient();
Per Åhgren0aefbf02019-08-23 21:29:17 +0200556 InitializeHighPassFilter();
peahde65ddc2016-09-16 15:02:15 -0700557 public_submodules_->noise_suppression->Initialize(num_proc_channels(),
558 proc_sample_rate_hz());
559 public_submodules_->voice_detection->Initialize(proc_split_sample_rate_hz());
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100560 if (private_submodules_->voice_detector) {
561 private_submodules_->voice_detector->Initialize(
562 proc_split_sample_rate_hz());
563 }
peahde65ddc2016-09-16 15:02:15 -0700564 public_submodules_->level_estimator->Initialize();
ivoc9f4a4a02016-10-28 05:39:16 -0700565 InitializeResidualEchoDetector();
Gustaf Ullberg8eb9c7d2017-10-14 08:28:46 +0200566 InitializeEchoController();
alessiob3ec96df2017-05-22 06:57:06 -0700567 InitializeGainController2();
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +0200568 InitializeAnalyzer();
Sam Zackrisson0beac582017-09-25 12:04:02 +0200569 InitializePostProcessor();
Alex Loiko5825aa62017-12-18 16:02:40 +0100570 InitializePreProcessor();
solenberg70f99032015-12-08 11:07:32 -0800571
aleloi868f32f2017-05-23 07:20:05 -0700572 if (aec_dump_) {
Minyue Li656d6092018-08-10 15:38:52 +0200573 aec_dump_->WriteInitMessage(formats_.api_format, rtc::TimeUTCMillis());
aleloi868f32f2017-05-23 07:20:05 -0700574 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000575 return kNoError;
576}
577
Michael Graczyk86c6d332015-07-23 11:41:39 -0700578int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
Per Åhgren4bdced52017-06-27 16:00:38 +0200579 UpdateActiveSubmoduleStates();
580
Michael Graczyk86c6d332015-07-23 11:41:39 -0700581 for (const auto& stream : config.streams) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700582 if (stream.num_channels() > 0 && stream.sample_rate_hz() <= 0) {
583 return kBadSampleRateError;
584 }
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000585 }
Michael Graczyk86c6d332015-07-23 11:41:39 -0700586
Peter Kasting69558702016-01-12 16:26:35 -0800587 const size_t num_in_channels = config.input_stream().num_channels();
588 const size_t num_out_channels = config.output_stream().num_channels();
Michael Graczyk86c6d332015-07-23 11:41:39 -0700589
590 // Need at least one input channel.
591 // Need either one output channel or as many outputs as there are inputs.
592 if (num_in_channels == 0 ||
593 !(num_out_channels == 1 || num_out_channels == num_in_channels)) {
Michael Graczykc2047542015-07-22 21:06:11 -0700594 return kBadNumberChannelsError;
595 }
596
peahdf3efa82015-11-28 12:35:15 -0800597 formats_.api_format = config;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000598
Per Åhgrenfcbe4072019-09-15 00:27:58 +0200599 // Choose maximum rate to use for the split filtering.
600 RTC_DCHECK(config_.pipeline.maximum_internal_processing_rate == 48000 ||
601 config_.pipeline.maximum_internal_processing_rate == 32000);
602 int max_splitting_rate = 48000;
603 if (config_.pipeline.maximum_internal_processing_rate == 32000) {
604 max_splitting_rate = config_.pipeline.maximum_internal_processing_rate;
605 }
606
Per Åhgrenc8626b62019-08-23 15:49:51 +0200607 int capture_processing_rate = SuitableProcessRate(
peah423d2362016-04-09 16:06:52 -0700608 std::min(formats_.api_format.input_stream().sample_rate_hz(),
peah2ace3f92016-09-10 04:42:27 -0700609 formats_.api_format.output_stream().sample_rate_hz()),
Per Åhgrenfcbe4072019-09-15 00:27:58 +0200610 max_splitting_rate,
peah2ace3f92016-09-10 04:42:27 -0700611 submodule_states_.CaptureMultiBandSubModulesActive() ||
612 submodule_states_.RenderMultiBandSubModulesActive());
Per Åhgrenc8626b62019-08-23 15:49:51 +0200613 RTC_DCHECK_NE(8000, capture_processing_rate);
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000614
peahde65ddc2016-09-16 15:02:15 -0700615 capture_nonlocked_.capture_processing_format =
616 StreamConfig(capture_processing_rate);
peah2ace3f92016-09-10 04:42:27 -0700617
peah2ce640f2017-04-07 03:57:48 -0700618 int render_processing_rate;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200619 if (!capture_nonlocked_.echo_controller_enabled) {
Per Åhgrenc8626b62019-08-23 15:49:51 +0200620 render_processing_rate = SuitableProcessRate(
peah2ce640f2017-04-07 03:57:48 -0700621 std::min(formats_.api_format.reverse_input_stream().sample_rate_hz(),
622 formats_.api_format.reverse_output_stream().sample_rate_hz()),
Per Åhgrenfcbe4072019-09-15 00:27:58 +0200623 max_splitting_rate,
peah2ce640f2017-04-07 03:57:48 -0700624 submodule_states_.CaptureMultiBandSubModulesActive() ||
625 submodule_states_.RenderMultiBandSubModulesActive());
626 } else {
627 render_processing_rate = capture_processing_rate;
628 }
629
peahde65ddc2016-09-16 15:02:15 -0700630 // If the forward sample rate is 8 kHz, the render stream is also processed
aluebseb3603b2016-04-20 15:27:58 -0700631 // at this rate.
peahde65ddc2016-09-16 15:02:15 -0700632 if (capture_nonlocked_.capture_processing_format.sample_rate_hz() ==
633 kSampleRate8kHz) {
634 render_processing_rate = kSampleRate8kHz;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000635 } else {
peahde65ddc2016-09-16 15:02:15 -0700636 render_processing_rate =
637 std::max(render_processing_rate, static_cast<int>(kSampleRate16kHz));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000638 }
639
Per Åhgrenc8626b62019-08-23 15:49:51 +0200640 RTC_DCHECK_NE(8000, render_processing_rate);
641
peahce4d9152017-05-19 01:28:05 -0700642 if (submodule_states_.RenderMultiBandSubModulesActive()) {
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200643 // By default, downmix the render stream to mono for analysis. This has been
644 // demonstrated to work well for AEC in most practical scenarios.
645 const bool experimental_multi_channel_render =
646 config_.pipeline.experimental_multi_channel &&
647 constants_.experimental_multi_channel_render_support;
648 int render_processing_num_channels =
649 experimental_multi_channel_render
650 ? formats_.api_format.reverse_input_stream().num_channels()
651 : 1;
652 formats_.render_processing_format =
653 StreamConfig(render_processing_rate, render_processing_num_channels);
peahce4d9152017-05-19 01:28:05 -0700654 } else {
655 formats_.render_processing_format = StreamConfig(
656 formats_.api_format.reverse_input_stream().sample_rate_hz(),
657 formats_.api_format.reverse_input_stream().num_channels());
658 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000659
peahde65ddc2016-09-16 15:02:15 -0700660 if (capture_nonlocked_.capture_processing_format.sample_rate_hz() ==
661 kSampleRate32kHz ||
662 capture_nonlocked_.capture_processing_format.sample_rate_hz() ==
663 kSampleRate48kHz) {
peahdf3efa82015-11-28 12:35:15 -0800664 capture_nonlocked_.split_rate = kSampleRate16kHz;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000665 } else {
peahdf3efa82015-11-28 12:35:15 -0800666 capture_nonlocked_.split_rate =
peahde65ddc2016-09-16 15:02:15 -0700667 capture_nonlocked_.capture_processing_format.sample_rate_hz();
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000668 }
669
670 return InitializeLocked();
671}
672
peah88ac8532016-09-12 16:47:25 -0700673void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
peah88ac8532016-09-12 16:47:25 -0700674 // Run in a single-threaded manner when applying the settings.
675 rtc::CritScope cs_render(&crit_render_);
676 rtc::CritScope cs_capture(&crit_capture_);
677
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200678 const bool pipeline_config_changed =
679 config_.pipeline.experimental_multi_channel !=
680 config.pipeline.experimental_multi_channel;
681
Per Åhgren200feba2019-03-06 04:16:46 +0100682 const bool aec_config_changed =
683 config_.echo_canceller.enabled != config.echo_canceller.enabled ||
684 config_.echo_canceller.use_legacy_aec !=
685 config.echo_canceller.use_legacy_aec ||
686 config_.echo_canceller.mobile_mode != config.echo_canceller.mobile_mode ||
687 (config_.echo_canceller.enabled && config.echo_canceller.use_legacy_aec &&
688 config_.echo_canceller.legacy_moderate_suppression_level !=
689 config.echo_canceller.legacy_moderate_suppression_level);
690
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100691 const bool agc1_config_changed =
692 config_.gain_controller1.enabled != config.gain_controller1.enabled ||
693 config_.gain_controller1.mode != config.gain_controller1.mode ||
694 config_.gain_controller1.target_level_dbfs !=
695 config.gain_controller1.target_level_dbfs ||
696 config_.gain_controller1.compression_gain_db !=
697 config.gain_controller1.compression_gain_db ||
698 config_.gain_controller1.enable_limiter !=
699 config.gain_controller1.enable_limiter ||
700 config_.gain_controller1.analog_level_minimum !=
701 config.gain_controller1.analog_level_minimum ||
702 config_.gain_controller1.analog_level_maximum !=
703 config.gain_controller1.analog_level_maximum;
704
Yves Gerey499bc6c2018-10-10 18:29:07 +0200705 config_ = config;
706
Per Åhgren200feba2019-03-06 04:16:46 +0100707 if (aec_config_changed) {
708 InitializeEchoController();
709 }
Sam Zackrissoncdf0e6d2018-09-17 11:05:17 +0200710
Sam Zackrisson23513132019-01-11 15:10:32 +0100711 public_submodules_->noise_suppression->Enable(
712 config.noise_suppression.enabled);
713 public_submodules_->noise_suppression->set_level(
714 NsConfigLevelToInterfaceLevel(config.noise_suppression.level));
715
Per Åhgren0aefbf02019-08-23 21:29:17 +0200716 InitializeHighPassFilter();
peah8271d042016-11-22 07:24:52 -0800717
Mirko Bonadei675513b2017-11-09 11:09:25 +0100718 RTC_LOG(LS_INFO) << "Highpass filter activated: "
719 << config_.high_pass_filter.enabled;
peahe0eae3c2016-12-14 01:16:23 -0800720
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100721 if (agc1_config_changed) {
722 ApplyAgc1Config(config_.gain_controller1);
723 }
724
Sam Zackrissonab1aee02018-03-05 15:59:06 +0100725 const bool config_ok = GainController2::Validate(config_.gain_controller2);
alessiob3ec96df2017-05-22 06:57:06 -0700726 if (!config_ok) {
Jonas Olsson645b0272018-02-15 15:16:27 +0100727 RTC_LOG(LS_ERROR) << "AudioProcessing module config error\n"
728 "Gain Controller 2: "
Mirko Bonadei675513b2017-11-09 11:09:25 +0100729 << GainController2::ToString(config_.gain_controller2)
Jonas Olsson645b0272018-02-15 15:16:27 +0100730 << "\nReverting to default parameter set";
alessiob3ec96df2017-05-22 06:57:06 -0700731 config_.gain_controller2 = AudioProcessing::Config::GainController2();
732 }
Alessio Bazzica270f7b52017-10-13 11:05:17 +0200733 InitializeGainController2();
Alex Loikob5c9a792018-04-16 16:31:22 +0200734 InitializePreAmplifier();
Alessio Bazzica270f7b52017-10-13 11:05:17 +0200735 private_submodules_->gain_controller2->ApplyConfig(config_.gain_controller2);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100736 RTC_LOG(LS_INFO) << "Gain Controller 2 activated: "
737 << config_.gain_controller2.enabled;
Alex Loiko5feb30e2018-04-16 13:52:32 +0200738 RTC_LOG(LS_INFO) << "Pre-amplifier activated: "
739 << config_.pre_amplifier.enabled;
Sam Zackrissonb24c00f2018-11-26 16:18:25 +0100740
741 if (config_.level_estimation.enabled &&
742 !private_submodules_->output_level_estimator) {
743 private_submodules_->output_level_estimator.reset(
744 new LevelEstimatorImpl(&crit_capture_));
745 private_submodules_->output_level_estimator->Enable(true);
746 }
Sam Zackrisson4db667b2018-12-21 16:29:27 +0100747
748 if (config_.voice_detection.enabled && !private_submodules_->voice_detector) {
749 private_submodules_->voice_detector.reset(
750 new VoiceDetectionImpl(&crit_capture_));
751 private_submodules_->voice_detector->Enable(true);
752 private_submodules_->voice_detector->set_likelihood(
753 VoiceDetection::kVeryLowLikelihood);
754 private_submodules_->voice_detector->Initialize(
755 proc_split_sample_rate_hz());
756 }
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200757
758 // Reinitialization must happen after all submodule configuration to avoid
759 // additional reinitializations on the next capture / render processing call.
760 if (pipeline_config_changed) {
761 InitializeLocked(formats_.api_format);
762 }
peah88ac8532016-09-12 16:47:25 -0700763}
764
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100765void AudioProcessingImpl::ApplyAgc1Config(
766 const Config::GainController1& config) {
767 GainControl* agc = agc1();
768 int error = agc->Enable(config.enabled);
769 RTC_DCHECK_EQ(kNoError, error);
770 error = agc->set_mode(Agc1ConfigModeToInterfaceMode(config.mode));
771 RTC_DCHECK_EQ(kNoError, error);
772 error = agc->set_target_level_dbfs(config.target_level_dbfs);
773 RTC_DCHECK_EQ(kNoError, error);
774 error = agc->set_compression_gain_db(config.compression_gain_db);
775 RTC_DCHECK_EQ(kNoError, error);
776 error = agc->enable_limiter(config.enable_limiter);
777 RTC_DCHECK_EQ(kNoError, error);
778 error = agc->set_analog_level_limits(config.analog_level_minimum,
779 config.analog_level_maximum);
780 RTC_DCHECK_EQ(kNoError, error);
781}
782
783GainControl* AudioProcessingImpl::agc1() {
784 if (constants_.use_experimental_agc) {
785 return public_submodules_->gain_control_for_experimental_agc.get();
786 }
787 return public_submodules_->gain_control.get();
788}
789
790const GainControl* AudioProcessingImpl::agc1() const {
791 if (constants_.use_experimental_agc) {
792 return public_submodules_->gain_control_for_experimental_agc.get();
793 }
794 return public_submodules_->gain_control.get();
795}
796
peah88ac8532016-09-12 16:47:25 -0700797void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
peahdf3efa82015-11-28 12:35:15 -0800798 // Run in a single-threaded manner when setting the extra options.
799 rtc::CritScope cs_render(&crit_render_);
800 rtc::CritScope cs_capture(&crit_capture_);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000801
Per Åhgrenf204faf2019-04-25 15:18:06 +0200802 capture_nonlocked_.use_aec2_extended_filter =
803 config.Get<ExtendedFilter>().enabled;
804 capture_nonlocked_.use_aec2_delay_agnostic =
805 config.Get<DelayAgnostic>().enabled;
806 capture_nonlocked_.use_aec2_refined_adaptive_filter =
807 config.Get<RefinedAdaptiveFilter>().enabled;
peahb624d8c2016-03-05 03:01:14 -0800808
peahdf3efa82015-11-28 12:35:15 -0800809 if (capture_.transient_suppressor_enabled !=
810 config.Get<ExperimentalNs>().enabled) {
811 capture_.transient_suppressor_enabled =
812 config.Get<ExperimentalNs>().enabled;
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000813 InitializeTransient();
814 }
andrew@webrtc.org61e596f2013-07-25 18:28:29 +0000815}
816
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000817int AudioProcessingImpl::proc_sample_rate_hz() const {
peahdf3efa82015-11-28 12:35:15 -0800818 // Used as callback from submodules, hence locking is not allowed.
peahde65ddc2016-09-16 15:02:15 -0700819 return capture_nonlocked_.capture_processing_format.sample_rate_hz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000820}
821
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000822int AudioProcessingImpl::proc_split_sample_rate_hz() const {
peahdf3efa82015-11-28 12:35:15 -0800823 // Used as callback from submodules, hence locking is not allowed.
824 return capture_nonlocked_.split_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000825}
826
Peter Kasting69558702016-01-12 16:26:35 -0800827size_t AudioProcessingImpl::num_reverse_channels() const {
peahdf3efa82015-11-28 12:35:15 -0800828 // Used as callback from submodules, hence locking is not allowed.
peahde65ddc2016-09-16 15:02:15 -0700829 return formats_.render_processing_format.num_channels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000830}
831
Peter Kasting69558702016-01-12 16:26:35 -0800832size_t AudioProcessingImpl::num_input_channels() const {
peahdf3efa82015-11-28 12:35:15 -0800833 // Used as callback from submodules, hence locking is not allowed.
834 return formats_.api_format.input_stream().num_channels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000835}
836
Peter Kasting69558702016-01-12 16:26:35 -0800837size_t AudioProcessingImpl::num_proc_channels() const {
aluebsb2328d12016-01-11 20:32:29 -0800838 // Used as callback from submodules, hence locking is not allowed.
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200839 const bool experimental_multi_channel_capture =
840 config_.pipeline.experimental_multi_channel &&
841 constants_.experimental_multi_channel_capture_support;
842 if (capture_nonlocked_.echo_controller_enabled &&
843 !experimental_multi_channel_capture) {
844 return 1;
845 }
846 return num_output_channels();
aluebsb2328d12016-01-11 20:32:29 -0800847}
848
Peter Kasting69558702016-01-12 16:26:35 -0800849size_t AudioProcessingImpl::num_output_channels() const {
peahdf3efa82015-11-28 12:35:15 -0800850 // Used as callback from submodules, hence locking is not allowed.
851 return formats_.api_format.output_stream().num_channels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000852}
853
andrew@webrtc.org17342e52014-02-12 22:28:31 +0000854void AudioProcessingImpl::set_output_will_be_muted(bool muted) {
peahdf3efa82015-11-28 12:35:15 -0800855 rtc::CritScope cs(&crit_capture_);
856 capture_.output_will_be_muted = muted;
857 if (private_submodules_->agc_manager.get()) {
858 private_submodules_->agc_manager->SetCaptureMuted(
859 capture_.output_will_be_muted);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000860 }
andrew@webrtc.org17342e52014-02-12 22:28:31 +0000861}
862
Alessio Bazzicac054e782018-04-16 12:10:09 +0200863void AudioProcessingImpl::SetRuntimeSetting(RuntimeSetting setting) {
Alex Loiko73ec0192018-05-15 10:52:28 +0200864 switch (setting.type()) {
865 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting:
866 render_runtime_settings_enqueuer_.Enqueue(setting);
867 return;
868 case RuntimeSetting::Type::kNotSpecified:
869 RTC_NOTREACHED();
870 return;
871 case RuntimeSetting::Type::kCapturePreGain:
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100872 case RuntimeSetting::Type::kCaptureCompressionGain:
Per Åhgren6ee75fd2019-04-26 11:33:37 +0200873 case RuntimeSetting::Type::kCaptureFixedPostGain:
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200874 case RuntimeSetting::Type::kPlayoutVolumeChange:
Alex Loiko73ec0192018-05-15 10:52:28 +0200875 capture_runtime_settings_enqueuer_.Enqueue(setting);
876 return;
877 }
878 // The language allows the enum to have a non-enumerator
879 // value. Check that this doesn't happen.
880 RTC_NOTREACHED();
Alessio Bazzicac054e782018-04-16 12:10:09 +0200881}
882
883AudioProcessingImpl::RuntimeSettingEnqueuer::RuntimeSettingEnqueuer(
884 SwapQueue<RuntimeSetting>* runtime_settings)
Alessio Bazzica33444dc2018-04-20 13:16:55 +0200885 : runtime_settings_(*runtime_settings) {
886 RTC_DCHECK(runtime_settings);
Alessio Bazzicac054e782018-04-16 12:10:09 +0200887}
888
889AudioProcessingImpl::RuntimeSettingEnqueuer::~RuntimeSettingEnqueuer() =
890 default;
891
892void AudioProcessingImpl::RuntimeSettingEnqueuer::Enqueue(
893 RuntimeSetting setting) {
894 size_t remaining_attempts = 10;
Alessio Bazzica33444dc2018-04-20 13:16:55 +0200895 while (!runtime_settings_.Insert(&setting) && remaining_attempts-- > 0) {
Alessio Bazzicac054e782018-04-16 12:10:09 +0200896 RuntimeSetting setting_to_discard;
Alessio Bazzica33444dc2018-04-20 13:16:55 +0200897 if (runtime_settings_.Remove(&setting_to_discard))
Alessio Bazzicac054e782018-04-16 12:10:09 +0200898 RTC_LOG(LS_ERROR)
899 << "The runtime settings queue is full. Oldest setting discarded.";
900 }
901 if (remaining_attempts == 0)
902 RTC_LOG(LS_ERROR) << "Cannot enqueue a new runtime setting.";
903}
andrew@webrtc.org17342e52014-02-12 22:28:31 +0000904
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000905int AudioProcessingImpl::ProcessStream(const float* const* src,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700906 size_t samples_per_channel,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000907 int input_sample_rate_hz,
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000908 ChannelLayout input_layout,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000909 int output_sample_rate_hz,
910 ChannelLayout output_layout,
911 float* const* dest) {
peah369f8282015-12-17 06:42:29 -0800912 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_ChannelLayout");
peahdf3efa82015-11-28 12:35:15 -0800913 StreamConfig input_stream;
914 StreamConfig output_stream;
915 {
916 // Access the formats_.api_format.input_stream beneath the capture lock.
917 // The lock must be released as it is later required in the call
918 // to ProcessStream(,,,);
919 rtc::CritScope cs(&crit_capture_);
920 input_stream = formats_.api_format.input_stream();
921 output_stream = formats_.api_format.output_stream();
922 }
923
Michael Graczyk86c6d332015-07-23 11:41:39 -0700924 input_stream.set_sample_rate_hz(input_sample_rate_hz);
925 input_stream.set_num_channels(ChannelsFromLayout(input_layout));
926 input_stream.set_has_keyboard(LayoutHasKeyboard(input_layout));
Michael Graczyk86c6d332015-07-23 11:41:39 -0700927 output_stream.set_sample_rate_hz(output_sample_rate_hz);
928 output_stream.set_num_channels(ChannelsFromLayout(output_layout));
929 output_stream.set_has_keyboard(LayoutHasKeyboard(output_layout));
930
931 if (samples_per_channel != input_stream.num_frames()) {
932 return kBadDataLengthError;
933 }
934 return ProcessStream(src, input_stream, output_stream, dest);
935}
936
937int AudioProcessingImpl::ProcessStream(const float* const* src,
938 const StreamConfig& input_config,
939 const StreamConfig& output_config,
940 float* const* dest) {
peah369f8282015-12-17 06:42:29 -0800941 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_StreamConfig");
peahdf3efa82015-11-28 12:35:15 -0800942 ProcessingConfig processing_config;
peah2ace3f92016-09-10 04:42:27 -0700943 bool reinitialization_required = false;
peahdf3efa82015-11-28 12:35:15 -0800944 {
945 // Acquire the capture lock in order to safely call the function
946 // that retrieves the render side data. This function accesses apm
947 // getters that need the capture lock held when being called.
948 rtc::CritScope cs_capture(&crit_capture_);
peah764e3642016-10-22 05:04:30 -0700949 EmptyQueuedRenderAudio();
peahdf3efa82015-11-28 12:35:15 -0800950
951 if (!src || !dest) {
952 return kNullPointerError;
953 }
954
955 processing_config = formats_.api_format;
peah2ace3f92016-09-10 04:42:27 -0700956 reinitialization_required = UpdateActiveSubmoduleStates();
niklase@google.com470e71d2011-07-07 08:21:25 +0000957 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000958
Oskar Sundbom4b276482019-05-23 14:28:00 +0200959 if (processing_config.input_stream() != input_config) {
960 processing_config.input_stream() = input_config;
961 reinitialization_required = true;
peahdf3efa82015-11-28 12:35:15 -0800962 }
Oskar Sundbom4b276482019-05-23 14:28:00 +0200963
964 if (processing_config.output_stream() != output_config) {
965 processing_config.output_stream() = output_config;
966 reinitialization_required = true;
967 }
968
969 if (reinitialization_required) {
970 // Reinitialize.
971 rtc::CritScope cs_render(&crit_render_);
972 rtc::CritScope cs_capture(&crit_capture_);
973 RETURN_ON_ERR(InitializeLocked(processing_config));
974 }
975
peahdf3efa82015-11-28 12:35:15 -0800976 rtc::CritScope cs_capture(&crit_capture_);
kwiberg9e2be5f2016-09-14 05:23:22 -0700977 RTC_DCHECK_EQ(processing_config.input_stream().num_frames(),
978 formats_.api_format.input_stream().num_frames());
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000979
aleloi868f32f2017-05-23 07:20:05 -0700980 if (aec_dump_) {
981 RecordUnprocessedCaptureStream(src);
982 }
983
Per Åhgrena1351272019-08-15 12:15:46 +0200984 capture_.keyboard_info.Extract(src, formats_.api_format.input_stream());
peahdf3efa82015-11-28 12:35:15 -0800985 capture_.capture_audio->CopyFrom(src, formats_.api_format.input_stream());
peahde65ddc2016-09-16 15:02:15 -0700986 RETURN_ON_ERR(ProcessCaptureStreamLocked());
peahdf3efa82015-11-28 12:35:15 -0800987 capture_.capture_audio->CopyTo(formats_.api_format.output_stream(), dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000988
aleloi868f32f2017-05-23 07:20:05 -0700989 if (aec_dump_) {
990 RecordProcessedCaptureStream(dest);
991 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000992 return kNoError;
993}
994
Alex Loiko73ec0192018-05-15 10:52:28 +0200995void AudioProcessingImpl::HandleCaptureRuntimeSettings() {
Alessio Bazzicac054e782018-04-16 12:10:09 +0200996 RuntimeSetting setting;
Alex Loiko73ec0192018-05-15 10:52:28 +0200997 while (capture_runtime_settings_.Remove(&setting)) {
Alex Loiko62347222018-09-10 10:18:07 +0200998 if (aec_dump_) {
999 aec_dump_->WriteRuntimeSetting(setting);
1000 }
Alessio Bazzicac054e782018-04-16 12:10:09 +02001001 switch (setting.type()) {
1002 case RuntimeSetting::Type::kCapturePreGain:
Alex Loikob5c9a792018-04-16 16:31:22 +02001003 if (config_.pre_amplifier.enabled) {
1004 float value;
1005 setting.GetFloat(&value);
1006 private_submodules_->pre_amplifier->SetGainFactor(value);
1007 }
1008 // TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump.
Alessio Bazzicac054e782018-04-16 12:10:09 +02001009 break;
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001010 case RuntimeSetting::Type::kCaptureCompressionGain: {
1011 float value;
1012 setting.GetFloat(&value);
1013 int int_value = static_cast<int>(value + .5f);
1014 config_.gain_controller1.compression_gain_db = int_value;
1015 int error = agc1()->set_compression_gain_db(int_value);
1016 RTC_DCHECK_EQ(kNoError, error);
1017 break;
1018 }
Per Åhgren6ee75fd2019-04-26 11:33:37 +02001019 case RuntimeSetting::Type::kCaptureFixedPostGain: {
1020 if (config_.gain_controller2.enabled) {
1021 float value;
1022 setting.GetFloat(&value);
1023 config_.gain_controller2.fixed_digital.gain_db = value;
1024 private_submodules_->gain_controller2->ApplyConfig(
1025 config_.gain_controller2);
1026 }
1027 break;
1028 }
Fredrik Hernqvistca362852019-05-10 15:50:02 +02001029 case RuntimeSetting::Type::kPlayoutVolumeChange: {
1030 int value;
1031 setting.GetInt(&value);
1032 capture_.playout_volume = value;
1033 break;
1034 }
Alex Loiko73ec0192018-05-15 10:52:28 +02001035 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting:
1036 RTC_NOTREACHED();
1037 break;
1038 case RuntimeSetting::Type::kNotSpecified:
1039 RTC_NOTREACHED();
1040 break;
1041 }
1042 }
1043}
1044
1045void AudioProcessingImpl::HandleRenderRuntimeSettings() {
1046 RuntimeSetting setting;
1047 while (render_runtime_settings_.Remove(&setting)) {
Alex Loiko62347222018-09-10 10:18:07 +02001048 if (aec_dump_) {
1049 aec_dump_->WriteRuntimeSetting(setting);
1050 }
Alex Loiko73ec0192018-05-15 10:52:28 +02001051 switch (setting.type()) {
1052 case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting:
1053 if (private_submodules_->render_pre_processor) {
1054 private_submodules_->render_pre_processor->SetRuntimeSetting(setting);
1055 }
1056 break;
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001057 case RuntimeSetting::Type::kCapturePreGain: // fall-through
1058 case RuntimeSetting::Type::kCaptureCompressionGain: // fall-through
Per Åhgren6ee75fd2019-04-26 11:33:37 +02001059 case RuntimeSetting::Type::kCaptureFixedPostGain: // fall-through
Fredrik Hernqvistca362852019-05-10 15:50:02 +02001060 case RuntimeSetting::Type::kPlayoutVolumeChange: // fall-through
Alessio Bazzica33444dc2018-04-20 13:16:55 +02001061 case RuntimeSetting::Type::kNotSpecified:
Alessio Bazzicac054e782018-04-16 12:10:09 +02001062 RTC_NOTREACHED();
1063 break;
1064 }
1065 }
1066}
1067
peah9e6a2902017-05-15 07:19:21 -07001068void AudioProcessingImpl::QueueBandedRenderAudio(AudioBuffer* audio) {
kwibergaf476c72016-11-28 15:21:39 -08001069 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peah764e3642016-10-22 05:04:30 -07001070
1071 // Insert the samples into the queue.
Per Åhgrenf204faf2019-04-25 15:18:06 +02001072 if (private_submodules_->echo_cancellation) {
1073 RTC_DCHECK(aec_render_signal_queue_);
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001074 EchoCancellationImpl::PackRenderAudioBuffer(audio, num_output_channels(),
1075 num_reverse_channels(),
1076 &aec_render_queue_buffer_);
1077
Per Åhgrenf204faf2019-04-25 15:18:06 +02001078 if (!aec_render_signal_queue_->Insert(&aec_render_queue_buffer_)) {
1079 // The data queue is full and needs to be emptied.
1080 EmptyQueuedRenderAudio();
peah764e3642016-10-22 05:04:30 -07001081
Per Åhgrenf204faf2019-04-25 15:18:06 +02001082 // Retry the insert (should always work).
1083 bool result = aec_render_signal_queue_->Insert(&aec_render_queue_buffer_);
1084 RTC_DCHECK(result);
1085 }
peaha0624602016-10-25 04:45:24 -07001086 }
1087
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001088 if (private_submodules_->echo_control_mobile) {
1089 EchoControlMobileImpl::PackRenderAudioBuffer(audio, num_output_channels(),
1090 num_reverse_channels(),
1091 &aecm_render_queue_buffer_);
1092 RTC_DCHECK(aecm_render_signal_queue_);
1093 // Insert the samples into the queue.
1094 if (!aecm_render_signal_queue_->Insert(&aecm_render_queue_buffer_)) {
1095 // The data queue is full and needs to be emptied.
1096 EmptyQueuedRenderAudio();
peaha0624602016-10-25 04:45:24 -07001097
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001098 // Retry the insert (should always work).
1099 bool result =
1100 aecm_render_signal_queue_->Insert(&aecm_render_queue_buffer_);
1101 RTC_DCHECK(result);
1102 }
peah764e3642016-10-22 05:04:30 -07001103 }
peah701d6282016-10-25 05:42:20 -07001104
1105 if (!constants_.use_experimental_agc) {
1106 GainControlImpl::PackRenderAudioBuffer(audio, &agc_render_queue_buffer_);
1107 // Insert the samples into the queue.
1108 if (!agc_render_signal_queue_->Insert(&agc_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 = agc_render_signal_queue_->Insert(&agc_render_queue_buffer_);
1114 RTC_DCHECK(result);
1115 }
1116 }
peah9e6a2902017-05-15 07:19:21 -07001117}
ivoc9f4a4a02016-10-28 05:39:16 -07001118
peah9e6a2902017-05-15 07:19:21 -07001119void AudioProcessingImpl::QueueNonbandedRenderAudio(AudioBuffer* audio) {
ivoc9f4a4a02016-10-28 05:39:16 -07001120 ResidualEchoDetector::PackRenderAudioBuffer(audio, &red_render_queue_buffer_);
1121
1122 // Insert the samples into the queue.
1123 if (!red_render_signal_queue_->Insert(&red_render_queue_buffer_)) {
1124 // The data queue is full and needs to be emptied.
1125 EmptyQueuedRenderAudio();
1126
1127 // Retry the insert (should always work).
1128 bool result = red_render_signal_queue_->Insert(&red_render_queue_buffer_);
1129 RTC_DCHECK(result);
1130 }
peah764e3642016-10-22 05:04:30 -07001131}
1132
1133void AudioProcessingImpl::AllocateRenderQueue() {
peah701d6282016-10-25 05:42:20 -07001134 const size_t new_agc_render_queue_element_max_size =
peah9e6a2902017-05-15 07:19:21 -07001135 std::max(static_cast<size_t>(1), kMaxAllowedValuesOfSamplesPerBand);
peah701d6282016-10-25 05:42:20 -07001136
ivoc9f4a4a02016-10-28 05:39:16 -07001137 const size_t new_red_render_queue_element_max_size =
1138 std::max(static_cast<size_t>(1), kMaxAllowedValuesOfSamplesPerFrame);
1139
peaha0624602016-10-25 04:45:24 -07001140 // Reallocate the queues if the queue item sizes are too small to fit the
1141 // data to put in the queues.
peah701d6282016-10-25 05:42:20 -07001142
1143 if (agc_render_queue_element_max_size_ <
1144 new_agc_render_queue_element_max_size) {
1145 agc_render_queue_element_max_size_ = new_agc_render_queue_element_max_size;
1146
1147 std::vector<int16_t> template_queue_element(
1148 agc_render_queue_element_max_size_);
1149
1150 agc_render_signal_queue_.reset(
1151 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
1152 kMaxNumFramesToBuffer, template_queue_element,
1153 RenderQueueItemVerifier<int16_t>(
1154 agc_render_queue_element_max_size_)));
1155
1156 agc_render_queue_buffer_.resize(agc_render_queue_element_max_size_);
1157 agc_capture_queue_buffer_.resize(agc_render_queue_element_max_size_);
1158 } else {
1159 agc_render_signal_queue_->Clear();
peah764e3642016-10-22 05:04:30 -07001160 }
ivoc9f4a4a02016-10-28 05:39:16 -07001161
1162 if (red_render_queue_element_max_size_ <
1163 new_red_render_queue_element_max_size) {
1164 red_render_queue_element_max_size_ = new_red_render_queue_element_max_size;
1165
1166 std::vector<float> template_queue_element(
1167 red_render_queue_element_max_size_);
1168
1169 red_render_signal_queue_.reset(
1170 new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>(
1171 kMaxNumFramesToBuffer, template_queue_element,
1172 RenderQueueItemVerifier<float>(
1173 red_render_queue_element_max_size_)));
1174
1175 red_render_queue_buffer_.resize(red_render_queue_element_max_size_);
1176 red_capture_queue_buffer_.resize(red_render_queue_element_max_size_);
1177 } else {
1178 red_render_signal_queue_->Clear();
1179 }
peah764e3642016-10-22 05:04:30 -07001180}
1181
1182void AudioProcessingImpl::EmptyQueuedRenderAudio() {
1183 rtc::CritScope cs_capture(&crit_capture_);
Per Åhgrenf204faf2019-04-25 15:18:06 +02001184 if (private_submodules_->echo_cancellation) {
1185 RTC_DCHECK(aec_render_signal_queue_);
1186 while (aec_render_signal_queue_->Remove(&aec_capture_queue_buffer_)) {
1187 private_submodules_->echo_cancellation->ProcessRenderAudio(
1188 aec_capture_queue_buffer_);
1189 }
peaha0624602016-10-25 04:45:24 -07001190 }
1191
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001192 if (private_submodules_->echo_control_mobile) {
1193 RTC_DCHECK(aecm_render_signal_queue_);
1194 while (aecm_render_signal_queue_->Remove(&aecm_capture_queue_buffer_)) {
1195 private_submodules_->echo_control_mobile->ProcessRenderAudio(
1196 aecm_capture_queue_buffer_);
1197 }
peah701d6282016-10-25 05:42:20 -07001198 }
1199
1200 while (agc_render_signal_queue_->Remove(&agc_capture_queue_buffer_)) {
1201 public_submodules_->gain_control->ProcessRenderAudio(
1202 agc_capture_queue_buffer_);
peah764e3642016-10-22 05:04:30 -07001203 }
ivoc9f4a4a02016-10-28 05:39:16 -07001204
1205 while (red_render_signal_queue_->Remove(&red_capture_queue_buffer_)) {
Ivo Creusen09fa4b02018-01-11 16:08:54 +01001206 RTC_DCHECK(private_submodules_->echo_detector);
1207 private_submodules_->echo_detector->AnalyzeRenderAudio(
ivoc9f4a4a02016-10-28 05:39:16 -07001208 red_capture_queue_buffer_);
1209 }
peah764e3642016-10-22 05:04:30 -07001210}
1211
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001212int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
peah369f8282015-12-17 06:42:29 -08001213 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_AudioFrame");
peahdf3efa82015-11-28 12:35:15 -08001214 {
1215 // Acquire the capture lock in order to safely call the function
Alessio Bazzicad2b97402018-08-09 14:23:11 +02001216 // that retrieves the render side data. This function accesses APM
peahdf3efa82015-11-28 12:35:15 -08001217 // getters that need the capture lock held when being called.
peahdf3efa82015-11-28 12:35:15 -08001218 rtc::CritScope cs_capture(&crit_capture_);
peah764e3642016-10-22 05:04:30 -07001219 EmptyQueuedRenderAudio();
peahdf3efa82015-11-28 12:35:15 -08001220 }
peahfa6228e2015-11-16 16:27:42 -08001221
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001222 if (!frame) {
1223 return kNullPointerError;
1224 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +00001225 // Must be a native rate.
1226 if (frame->sample_rate_hz_ != kSampleRate8kHz &&
1227 frame->sample_rate_hz_ != kSampleRate16kHz &&
aluebs@webrtc.org087da132014-11-17 23:01:23 +00001228 frame->sample_rate_hz_ != kSampleRate32kHz &&
1229 frame->sample_rate_hz_ != kSampleRate48kHz) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +00001230 return kBadSampleRateError;
1231 }
peah192164e2015-11-17 02:16:45 -08001232
peahdf3efa82015-11-28 12:35:15 -08001233 ProcessingConfig processing_config;
peah2ace3f92016-09-10 04:42:27 -07001234 bool reinitialization_required = false;
peahdf3efa82015-11-28 12:35:15 -08001235 {
1236 // Aquire lock for the access of api_format.
1237 // The lock is released immediately due to the conditional
1238 // reinitialization.
1239 rtc::CritScope cs_capture(&crit_capture_);
1240 // TODO(ajm): The input and output rates and channels are currently
1241 // constrained to be identical in the int16 interface.
1242 processing_config = formats_.api_format;
peah2ace3f92016-09-10 04:42:27 -07001243
1244 reinitialization_required = UpdateActiveSubmoduleStates();
peahdf3efa82015-11-28 12:35:15 -08001245 }
Michael Graczyk86c6d332015-07-23 11:41:39 -07001246
Oskar Sundbom4b276482019-05-23 14:28:00 +02001247 reinitialization_required =
1248 reinitialization_required ||
1249 processing_config.input_stream().sample_rate_hz() !=
1250 frame->sample_rate_hz_ ||
1251 processing_config.input_stream().num_channels() != frame->num_channels_ ||
1252 processing_config.output_stream().sample_rate_hz() !=
1253 frame->sample_rate_hz_ ||
1254 processing_config.output_stream().num_channels() != frame->num_channels_;
1255
1256 if (reinitialization_required) {
1257 processing_config.input_stream().set_sample_rate_hz(frame->sample_rate_hz_);
1258 processing_config.input_stream().set_num_channels(frame->num_channels_);
1259 processing_config.output_stream().set_sample_rate_hz(
1260 frame->sample_rate_hz_);
1261 processing_config.output_stream().set_num_channels(frame->num_channels_);
1262
1263 // Reinitialize.
peahdf3efa82015-11-28 12:35:15 -08001264 rtc::CritScope cs_render(&crit_render_);
Oskar Sundbom4b276482019-05-23 14:28:00 +02001265 rtc::CritScope cs_capture(&crit_capture_);
1266 RETURN_ON_ERR(InitializeLocked(processing_config));
peahdf3efa82015-11-28 12:35:15 -08001267 }
Oskar Sundbom4b276482019-05-23 14:28:00 +02001268
peahdf3efa82015-11-28 12:35:15 -08001269 rtc::CritScope cs_capture(&crit_capture_);
peah192164e2015-11-17 02:16:45 -08001270 if (frame->samples_per_channel_ !=
peahdf3efa82015-11-28 12:35:15 -08001271 formats_.api_format.input_stream().num_frames()) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001272 return kBadDataLengthError;
1273 }
1274
aleloi868f32f2017-05-23 07:20:05 -07001275 if (aec_dump_) {
1276 RecordUnprocessedCaptureStream(*frame);
1277 }
1278
Per Åhgrena1351272019-08-15 12:15:46 +02001279 capture_.vad_activity = frame->vad_activity_;
Per Åhgrend47941e2019-08-22 11:51:13 +02001280 capture_.capture_audio->CopyFrom(frame);
peahde65ddc2016-09-16 15:02:15 -07001281 RETURN_ON_ERR(ProcessCaptureStreamLocked());
Per Åhgrena1351272019-08-15 12:15:46 +02001282 if (submodule_states_.CaptureMultiBandProcessingActive() ||
1283 submodule_states_.CaptureFullBandProcessingActive()) {
Per Åhgrend47941e2019-08-22 11:51:13 +02001284 capture_.capture_audio->CopyTo(frame);
Per Åhgrena1351272019-08-15 12:15:46 +02001285 }
1286 frame->vad_activity_ = capture_.vad_activity;
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001287
aleloi868f32f2017-05-23 07:20:05 -07001288 if (aec_dump_) {
1289 RecordProcessedCaptureStream(*frame);
1290 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001291
1292 return kNoError;
1293}
1294
peahde65ddc2016-09-16 15:02:15 -07001295int AudioProcessingImpl::ProcessCaptureStreamLocked() {
Alex Loiko73ec0192018-05-15 10:52:28 +02001296 HandleCaptureRuntimeSettings();
Alessio Bazzicac054e782018-04-16 12:10:09 +02001297
peahb58a1582016-03-15 09:34:24 -07001298 // Ensure that not both the AEC and AECM are active at the same time.
Sam Zackrisson2a959d92018-07-23 14:48:07 +00001299 // TODO(peah): Simplify once the public API Enable functions for these
1300 // are moved to APM.
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001301 RTC_DCHECK_LE(!!private_submodules_->echo_controller +
1302 !!private_submodules_->echo_cancellation +
1303 !!private_submodules_->echo_control_mobile,
1304 1);
peahb58a1582016-03-15 09:34:24 -07001305
peahde65ddc2016-09-16 15:02:15 -07001306 AudioBuffer* capture_buffer = capture_.capture_audio.get(); // For brevity.
ekmeyerson60d9b332015-08-14 10:35:55 -07001307
Alex Loikob5c9a792018-04-16 16:31:22 +02001308 if (private_submodules_->pre_amplifier) {
1309 private_submodules_->pre_amplifier->ApplyGain(AudioFrameView<float>(
Per Åhgrend47941e2019-08-22 11:51:13 +02001310 capture_buffer->channels(), capture_buffer->num_channels(),
Alex Loikob5c9a792018-04-16 16:31:22 +02001311 capture_buffer->num_frames()));
1312 }
1313
Per Åhgren928146f2019-08-20 09:19:21 +02001314 capture_input_rms_.Analyze(rtc::ArrayView<const float>(
Per Åhgrend47941e2019-08-22 11:51:13 +02001315 capture_buffer->channels_const()[0],
henrik.lundin290d43a2016-11-29 08:09:09 -08001316 capture_nonlocked_.capture_processing_format.num_frames()));
peah1b08dc32016-12-20 13:45:58 -08001317 const bool log_rms = ++capture_rms_interval_counter_ >= 1000;
1318 if (log_rms) {
1319 capture_rms_interval_counter_ = 0;
1320 RmsLevel::Levels levels = capture_input_rms_.AverageAndPeak();
henrik.lundin45bb5132016-12-06 04:28:04 -08001321 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelAverageRms",
1322 levels.average, 1, RmsLevel::kMinLevelDb, 64);
1323 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelPeakRms",
1324 levels.peak, 1, RmsLevel::kMinLevelDb, 64);
henrik.lundin290d43a2016-11-29 08:09:09 -08001325 }
1326
Sam Zackrisson2a959d92018-07-23 14:48:07 +00001327 if (private_submodules_->echo_controller) {
Per Åhgren88cf0502018-07-16 17:08:41 +02001328 // Detect and flag any change in the analog gain.
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001329 int analog_mic_level = agc1()->stream_analog_level();
Per Åhgren88cf0502018-07-16 17:08:41 +02001330 capture_.echo_path_gain_change =
1331 capture_.prev_analog_mic_level != analog_mic_level &&
1332 capture_.prev_analog_mic_level != -1;
1333 capture_.prev_analog_mic_level = analog_mic_level;
1334
Per Åhgrend2650d12018-10-02 17:00:59 +02001335 // Detect and flag any change in the pre-amplifier gain.
1336 if (private_submodules_->pre_amplifier) {
1337 float pre_amp_gain = private_submodules_->pre_amplifier->GetGainFactor();
1338 capture_.echo_path_gain_change =
1339 capture_.echo_path_gain_change ||
1340 (capture_.prev_pre_amp_gain != pre_amp_gain &&
Per Åhgrene8a55692018-10-02 23:10:38 +02001341 capture_.prev_pre_amp_gain >= 0.f);
Per Åhgrend2650d12018-10-02 17:00:59 +02001342 capture_.prev_pre_amp_gain = pre_amp_gain;
1343 }
Fredrik Hernqvistca362852019-05-10 15:50:02 +02001344
1345 // Detect volume change.
1346 capture_.echo_path_gain_change =
1347 capture_.echo_path_gain_change ||
1348 (capture_.prev_playout_volume != capture_.playout_volume &&
1349 capture_.prev_playout_volume >= 0);
1350 capture_.prev_playout_volume = capture_.playout_volume;
1351
Gustaf Ullberg59ff0e22017-10-09 10:20:34 +02001352 private_submodules_->echo_controller->AnalyzeCapture(capture_buffer);
peahe0eae3c2016-12-14 01:16:23 -08001353 }
1354
peahbe615622016-02-13 16:40:47 -08001355 if (constants_.use_experimental_agc &&
peahdf3efa82015-11-28 12:35:15 -08001356 public_submodules_->gain_control->is_enabled()) {
1357 private_submodules_->agc_manager->AnalyzePreProcess(
Per Åhgren928146f2019-08-20 09:19:21 +02001358 capture_buffer->channels_f()[0], capture_buffer->num_channels(),
peahde65ddc2016-09-16 15:02:15 -07001359 capture_nonlocked_.capture_processing_format.num_frames());
Alex Loikod9342442018-09-10 13:59:41 +02001360
1361 if (constants_.use_experimental_agc_process_before_aec) {
1362 private_submodules_->agc_manager->Process(
Per Åhgrend47941e2019-08-22 11:51:13 +02001363 capture_buffer->channels_const()[0],
Alex Loikod9342442018-09-10 13:59:41 +02001364 capture_nonlocked_.capture_processing_format.num_frames(),
1365 capture_nonlocked_.capture_processing_format.sample_rate_hz());
1366 }
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001367 }
1368
peah2ace3f92016-09-10 04:42:27 -07001369 if (submodule_states_.CaptureMultiBandSubModulesActive() &&
1370 SampleRateSupportsMultiBand(
peahde65ddc2016-09-16 15:02:15 -07001371 capture_nonlocked_.capture_processing_format.sample_rate_hz())) {
1372 capture_buffer->SplitIntoFrequencyBands();
niklase@google.com470e71d2011-07-07 08:21:25 +00001373 }
1374
Sam Zackrissonfeee1e42019-09-20 07:50:35 +02001375 const bool experimental_multi_channel_capture =
1376 config_.pipeline.experimental_multi_channel &&
1377 constants_.experimental_multi_channel_capture_support;
1378 if (private_submodules_->echo_controller &&
1379 !experimental_multi_channel_capture) {
peah522d71b2017-02-23 05:16:26 -08001380 // Force down-mixing of the number of channels after the detection of
1381 // capture signal saturation.
1382 // TODO(peah): Look into ensuring that this kind of tampering with the
1383 // AudioBuffer functionality should not be needed.
1384 capture_buffer->set_num_channels(1);
1385 }
1386
Per Åhgren0aefbf02019-08-23 21:29:17 +02001387 if (private_submodules_->high_pass_filter) {
1388 private_submodules_->high_pass_filter->Process(capture_buffer);
peah8271d042016-11-22 07:24:52 -08001389 }
peahde65ddc2016-09-16 15:02:15 -07001390 RETURN_ON_ERR(
1391 public_submodules_->gain_control->AnalyzeCaptureAudio(capture_buffer));
1392 public_submodules_->noise_suppression->AnalyzeCaptureAudio(capture_buffer);
peahb58a1582016-03-15 09:34:24 -07001393
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001394 if (private_submodules_->echo_control_mobile) {
1395 // Ensure that the stream delay was set before the call to the
1396 // AECM ProcessCaptureAudio function.
1397 if (!was_stream_delay_set()) {
1398 return AudioProcessing::kStreamParameterNotSetError;
Per Åhgrend0fa8202018-04-18 09:35:13 +02001399 }
1400
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001401 if (public_submodules_->noise_suppression->is_enabled()) {
Per Åhgrena1351272019-08-15 12:15:46 +02001402 private_submodules_->echo_control_mobile->CopyLowPassReference(
1403 capture_buffer);
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001404 }
peahe0eae3c2016-12-14 01:16:23 -08001405
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001406 public_submodules_->noise_suppression->ProcessCaptureAudio(capture_buffer);
peah253534d2016-03-15 04:32:28 -07001407
Sam Zackrissonc22f5512018-11-05 16:10:00 +01001408 RETURN_ON_ERR(private_submodules_->echo_control_mobile->ProcessCaptureAudio(
Per Åhgren46537a32017-06-07 10:08:10 +02001409 capture_buffer, stream_delay_ms()));
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001410 } else {
1411 if (private_submodules_->echo_controller) {
1412 data_dumper_->DumpRaw("stream_delay", stream_delay_ms());
1413
1414 if (was_stream_delay_set()) {
1415 private_submodules_->echo_controller->SetAudioBufferDelay(
1416 stream_delay_ms());
1417 }
1418
1419 private_submodules_->echo_controller->ProcessCapture(
1420 capture_buffer, capture_.echo_path_gain_change);
1421 } else if (private_submodules_->echo_cancellation) {
1422 // Ensure that the stream delay was set before the call to the
1423 // AEC ProcessCaptureAudio function.
1424 if (!was_stream_delay_set()) {
1425 return AudioProcessing::kStreamParameterNotSetError;
1426 }
1427
1428 RETURN_ON_ERR(private_submodules_->echo_cancellation->ProcessCaptureAudio(
1429 capture_buffer, stream_delay_ms()));
1430 }
1431
1432 public_submodules_->noise_suppression->ProcessCaptureAudio(capture_buffer);
Per Åhgren46537a32017-06-07 10:08:10 +02001433 }
ivoc9f4a4a02016-10-28 05:39:16 -07001434
Per Åhgrena1351272019-08-15 12:15:46 +02001435 if (public_submodules_->voice_detection->is_enabled() &&
1436 !public_submodules_->voice_detection->using_external_vad()) {
1437 bool voice_active =
1438 public_submodules_->voice_detection->ProcessCaptureAudio(
1439 capture_buffer);
1440 capture_.vad_activity =
1441 voice_active ? AudioFrame::kVadActive : AudioFrame::kVadPassive;
1442 }
1443
Sam Zackrisson4db667b2018-12-21 16:29:27 +01001444 if (config_.voice_detection.enabled) {
1445 private_submodules_->voice_detector->ProcessCaptureAudio(capture_buffer);
1446 capture_.stats.voice_detected =
1447 private_submodules_->voice_detector->stream_has_voice();
1448 } else {
1449 capture_.stats.voice_detected = absl::nullopt;
1450 }
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001451
peahbe615622016-02-13 16:40:47 -08001452 if (constants_.use_experimental_agc &&
Alex Loikod9342442018-09-10 13:59:41 +02001453 public_submodules_->gain_control->is_enabled() &&
1454 !constants_.use_experimental_agc_process_before_aec) {
peahdf3efa82015-11-28 12:35:15 -08001455 private_submodules_->agc_manager->Process(
Per Åhgren928146f2019-08-20 09:19:21 +02001456 capture_buffer->split_bands_const_f(0)[kBand0To8kHz],
peahde65ddc2016-09-16 15:02:15 -07001457 capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate);
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001458 }
Per Åhgren200feba2019-03-06 04:16:46 +01001459 // TODO(peah): Add reporting from AEC3 whether there is echo.
peahb8fbb542016-03-15 02:28:08 -07001460 RETURN_ON_ERR(public_submodules_->gain_control->ProcessCaptureAudio(
Sam Zackrissoncdf0e6d2018-09-17 11:05:17 +02001461 capture_buffer,
Per Åhgrenf204faf2019-04-25 15:18:06 +02001462 private_submodules_->echo_cancellation &&
1463 private_submodules_->echo_cancellation->stream_has_echo()));
niklase@google.com470e71d2011-07-07 08:21:25 +00001464
peah2ace3f92016-09-10 04:42:27 -07001465 if (submodule_states_.CaptureMultiBandProcessingActive() &&
1466 SampleRateSupportsMultiBand(
peahde65ddc2016-09-16 15:02:15 -07001467 capture_nonlocked_.capture_processing_format.sample_rate_hz())) {
1468 capture_buffer->MergeFrequencyBands();
niklase@google.com470e71d2011-07-07 08:21:25 +00001469 }
1470
peah9e6a2902017-05-15 07:19:21 -07001471 if (config_.residual_echo_detector.enabled) {
Ivo Creusen09fa4b02018-01-11 16:08:54 +01001472 RTC_DCHECK(private_submodules_->echo_detector);
1473 private_submodules_->echo_detector->AnalyzeCaptureAudio(
Per Åhgrend47941e2019-08-22 11:51:13 +02001474 rtc::ArrayView<const float>(capture_buffer->channels()[0],
peah9e6a2902017-05-15 07:19:21 -07001475 capture_buffer->num_frames()));
1476 }
1477
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001478 // TODO(aluebs): Investigate if the transient suppression placement should be
1479 // before or after the AGC.
peahdf3efa82015-11-28 12:35:15 -08001480 if (capture_.transient_suppressor_enabled) {
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001481 float voice_probability =
peahdf3efa82015-11-28 12:35:15 -08001482 private_submodules_->agc_manager.get()
1483 ? private_submodules_->agc_manager->voice_probability()
1484 : 1.f;
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001485
peahdf3efa82015-11-28 12:35:15 -08001486 public_submodules_->transient_suppressor->Suppress(
Per Åhgrend47941e2019-08-22 11:51:13 +02001487 capture_buffer->channels()[0], capture_buffer->num_frames(),
peahde65ddc2016-09-16 15:02:15 -07001488 capture_buffer->num_channels(),
Per Åhgrend47941e2019-08-22 11:51:13 +02001489 capture_buffer->split_bands_const(0)[kBand0To8kHz],
Per Åhgrena1351272019-08-15 12:15:46 +02001490 capture_buffer->num_frames_per_band(),
1491 capture_.keyboard_info.keyboard_data,
1492 capture_.keyboard_info.num_keyboard_frames, voice_probability,
peahdf3efa82015-11-28 12:35:15 -08001493 capture_.key_pressed);
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001494 }
1495
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +02001496 // Experimental APM sub-module that analyzes |capture_buffer|.
1497 if (private_submodules_->capture_analyzer) {
1498 private_submodules_->capture_analyzer->Analyze(capture_buffer);
1499 }
1500
Alessio Bazzica270f7b52017-10-13 11:05:17 +02001501 if (config_.gain_controller2.enabled) {
Alex Loikoa837dd72018-08-06 16:32:12 +02001502 private_submodules_->gain_controller2->NotifyAnalogLevel(
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001503 agc1()->stream_analog_level());
alessiob3ec96df2017-05-22 06:57:06 -07001504 private_submodules_->gain_controller2->Process(capture_buffer);
1505 }
1506
Sam Zackrisson0beac582017-09-25 12:04:02 +02001507 if (private_submodules_->capture_post_processor) {
1508 private_submodules_->capture_post_processor->Process(capture_buffer);
1509 }
1510
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001511 // The level estimator operates on the recombined data.
Per Åhgrend47941e2019-08-22 11:51:13 +02001512 public_submodules_->level_estimator->ProcessStream(*capture_buffer);
Sam Zackrissonb24c00f2018-11-26 16:18:25 +01001513 if (config_.level_estimation.enabled) {
Per Åhgrend47941e2019-08-22 11:51:13 +02001514 private_submodules_->output_level_estimator->ProcessStream(*capture_buffer);
Sam Zackrissonb24c00f2018-11-26 16:18:25 +01001515 capture_.stats.output_rms_dbfs =
1516 private_submodules_->output_level_estimator->RMS();
1517 } else {
1518 capture_.stats.output_rms_dbfs = absl::nullopt;
1519 }
ajm@google.com808e0e02011-08-03 21:08:51 +00001520
Per Åhgren928146f2019-08-20 09:19:21 +02001521 capture_output_rms_.Analyze(rtc::ArrayView<const float>(
Per Åhgrend47941e2019-08-22 11:51:13 +02001522 capture_buffer->channels_const()[0],
peah1b08dc32016-12-20 13:45:58 -08001523 capture_nonlocked_.capture_processing_format.num_frames()));
1524 if (log_rms) {
1525 RmsLevel::Levels levels = capture_output_rms_.AverageAndPeak();
1526 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureOutputLevelAverageRms",
1527 levels.average, 1, RmsLevel::kMinLevelDb, 64);
1528 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureOutputLevelPeakRms",
1529 levels.peak, 1, RmsLevel::kMinLevelDb, 64);
1530 }
1531
peahdf3efa82015-11-28 12:35:15 -08001532 capture_.was_stream_delay_set = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001533 return kNoError;
1534}
1535
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001536int AudioProcessingImpl::AnalyzeReverseStream(const float* const* data,
Peter Kastingdce40cf2015-08-24 14:52:23 -07001537 size_t samples_per_channel,
peahde65ddc2016-09-16 15:02:15 -07001538 int sample_rate_hz,
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001539 ChannelLayout layout) {
peah369f8282015-12-17 06:42:29 -08001540 TRACE_EVENT0("webrtc", "AudioProcessing::AnalyzeReverseStream_ChannelLayout");
peahdf3efa82015-11-28 12:35:15 -08001541 rtc::CritScope cs(&crit_render_);
Michael Graczyk86c6d332015-07-23 11:41:39 -07001542 const StreamConfig reverse_config = {
Jonas Olssona4d87372019-07-05 19:08:33 +02001543 sample_rate_hz,
1544 ChannelsFromLayout(layout),
1545 LayoutHasKeyboard(layout),
Michael Graczyk86c6d332015-07-23 11:41:39 -07001546 };
1547 if (samples_per_channel != reverse_config.num_frames()) {
1548 return kBadDataLengthError;
1549 }
peahdf3efa82015-11-28 12:35:15 -08001550 return AnalyzeReverseStreamLocked(data, reverse_config, reverse_config);
ekmeyerson60d9b332015-08-14 10:35:55 -07001551}
1552
peahde65ddc2016-09-16 15:02:15 -07001553int AudioProcessingImpl::ProcessReverseStream(const float* const* src,
1554 const StreamConfig& input_config,
1555 const StreamConfig& output_config,
1556 float* const* dest) {
peah369f8282015-12-17 06:42:29 -08001557 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_StreamConfig");
peahdf3efa82015-11-28 12:35:15 -08001558 rtc::CritScope cs(&crit_render_);
peahde65ddc2016-09-16 15:02:15 -07001559 RETURN_ON_ERR(AnalyzeReverseStreamLocked(src, input_config, output_config));
Alex Loiko5825aa62017-12-18 16:02:40 +01001560 if (submodule_states_.RenderMultiBandProcessingActive() ||
1561 submodule_states_.RenderFullBandProcessingActive()) {
peahdf3efa82015-11-28 12:35:15 -08001562 render_.render_audio->CopyTo(formats_.api_format.reverse_output_stream(),
1563 dest);
peah2ace3f92016-09-10 04:42:27 -07001564 } else if (formats_.api_format.reverse_input_stream() !=
1565 formats_.api_format.reverse_output_stream()) {
peahde65ddc2016-09-16 15:02:15 -07001566 render_.render_converter->Convert(src, input_config.num_samples(), dest,
1567 output_config.num_samples());
ekmeyerson60d9b332015-08-14 10:35:55 -07001568 } else {
peahde65ddc2016-09-16 15:02:15 -07001569 CopyAudioIfNeeded(src, input_config.num_frames(),
1570 input_config.num_channels(), dest);
ekmeyerson60d9b332015-08-14 10:35:55 -07001571 }
1572
1573 return kNoError;
Michael Graczyk86c6d332015-07-23 11:41:39 -07001574}
1575
peahdf3efa82015-11-28 12:35:15 -08001576int AudioProcessingImpl::AnalyzeReverseStreamLocked(
ekmeyerson60d9b332015-08-14 10:35:55 -07001577 const float* const* src,
peahde65ddc2016-09-16 15:02:15 -07001578 const StreamConfig& input_config,
1579 const StreamConfig& output_config) {
peahdf3efa82015-11-28 12:35:15 -08001580 if (src == nullptr) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001581 return kNullPointerError;
1582 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001583
peahde65ddc2016-09-16 15:02:15 -07001584 if (input_config.num_channels() == 0) {
Michael Graczyk86c6d332015-07-23 11:41:39 -07001585 return kBadNumberChannelsError;
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001586 }
1587
peahdf3efa82015-11-28 12:35:15 -08001588 ProcessingConfig processing_config = formats_.api_format;
peahde65ddc2016-09-16 15:02:15 -07001589 processing_config.reverse_input_stream() = input_config;
1590 processing_config.reverse_output_stream() = output_config;
Michael Graczyk86c6d332015-07-23 11:41:39 -07001591
peahdf3efa82015-11-28 12:35:15 -08001592 RETURN_ON_ERR(MaybeInitializeRender(processing_config));
Fredrik Solenbergbbf21a32018-04-12 22:44:09 +02001593 RTC_DCHECK_EQ(input_config.num_frames(),
1594 formats_.api_format.reverse_input_stream().num_frames());
Michael Graczyk86c6d332015-07-23 11:41:39 -07001595
aleloi868f32f2017-05-23 07:20:05 -07001596 if (aec_dump_) {
1597 const size_t channel_size =
1598 formats_.api_format.reverse_input_stream().num_frames();
1599 const size_t num_channels =
1600 formats_.api_format.reverse_input_stream().num_channels();
1601 aec_dump_->WriteRenderStreamMessage(
Alex Loikoe36e8bb2018-02-16 11:54:07 +01001602 AudioFrameView<const float>(src, num_channels, channel_size));
aleloi868f32f2017-05-23 07:20:05 -07001603 }
peahdf3efa82015-11-28 12:35:15 -08001604 render_.render_audio->CopyFrom(src,
1605 formats_.api_format.reverse_input_stream());
peahde65ddc2016-09-16 15:02:15 -07001606 return ProcessRenderStreamLocked();
ekmeyerson60d9b332015-08-14 10:35:55 -07001607}
1608
1609int AudioProcessingImpl::ProcessReverseStream(AudioFrame* frame) {
peah369f8282015-12-17 06:42:29 -08001610 TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_AudioFrame");
peahdf3efa82015-11-28 12:35:15 -08001611 rtc::CritScope cs(&crit_render_);
peahdf3efa82015-11-28 12:35:15 -08001612 if (frame == nullptr) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001613 return kNullPointerError;
1614 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +00001615 // Must be a native rate.
1616 if (frame->sample_rate_hz_ != kSampleRate8kHz &&
1617 frame->sample_rate_hz_ != kSampleRate16kHz &&
aluebs@webrtc.org087da132014-11-17 23:01:23 +00001618 frame->sample_rate_hz_ != kSampleRate32kHz &&
1619 frame->sample_rate_hz_ != kSampleRate48kHz) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +00001620 return kBadSampleRateError;
1621 }
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001622
Michael Graczyk86c6d332015-07-23 11:41:39 -07001623 if (frame->num_channels_ <= 0) {
1624 return kBadNumberChannelsError;
1625 }
1626
peahdf3efa82015-11-28 12:35:15 -08001627 ProcessingConfig processing_config = formats_.api_format;
ekmeyerson60d9b332015-08-14 10:35:55 -07001628 processing_config.reverse_input_stream().set_sample_rate_hz(
1629 frame->sample_rate_hz_);
1630 processing_config.reverse_input_stream().set_num_channels(
1631 frame->num_channels_);
1632 processing_config.reverse_output_stream().set_sample_rate_hz(
1633 frame->sample_rate_hz_);
1634 processing_config.reverse_output_stream().set_num_channels(
1635 frame->num_channels_);
Michael Graczyk86c6d332015-07-23 11:41:39 -07001636
peahdf3efa82015-11-28 12:35:15 -08001637 RETURN_ON_ERR(MaybeInitializeRender(processing_config));
Michael Graczyk86c6d332015-07-23 11:41:39 -07001638 if (frame->samples_per_channel_ !=
peahdf3efa82015-11-28 12:35:15 -08001639 formats_.api_format.reverse_input_stream().num_frames()) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001640 return kBadDataLengthError;
1641 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001642
aleloi868f32f2017-05-23 07:20:05 -07001643 if (aec_dump_) {
1644 aec_dump_->WriteRenderStreamMessage(*frame);
1645 }
1646
Per Åhgrend47941e2019-08-22 11:51:13 +02001647 render_.render_audio->CopyFrom(frame);
peahde65ddc2016-09-16 15:02:15 -07001648 RETURN_ON_ERR(ProcessRenderStreamLocked());
Per Åhgrena1351272019-08-15 12:15:46 +02001649 if (submodule_states_.RenderMultiBandProcessingActive() ||
1650 submodule_states_.RenderFullBandProcessingActive()) {
Per Åhgrend47941e2019-08-22 11:51:13 +02001651 render_.render_audio->CopyTo(frame);
Per Åhgrena1351272019-08-15 12:15:46 +02001652 }
aluebsb0319552016-03-17 20:39:53 -07001653 return kNoError;
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001654}
niklase@google.com470e71d2011-07-07 08:21:25 +00001655
peahde65ddc2016-09-16 15:02:15 -07001656int AudioProcessingImpl::ProcessRenderStreamLocked() {
1657 AudioBuffer* render_buffer = render_.render_audio.get(); // For brevity.
peah9e6a2902017-05-15 07:19:21 -07001658
Alex Loiko73ec0192018-05-15 10:52:28 +02001659 HandleRenderRuntimeSettings();
1660
Alex Loiko5825aa62017-12-18 16:02:40 +01001661 if (private_submodules_->render_pre_processor) {
1662 private_submodules_->render_pre_processor->Process(render_buffer);
1663 }
1664
Alessio Bazzicad2b97402018-08-09 14:23:11 +02001665 QueueNonbandedRenderAudio(render_buffer);
1666
peah2ace3f92016-09-10 04:42:27 -07001667 if (submodule_states_.RenderMultiBandSubModulesActive() &&
peahde65ddc2016-09-16 15:02:15 -07001668 SampleRateSupportsMultiBand(
1669 formats_.render_processing_format.sample_rate_hz())) {
1670 render_buffer->SplitIntoFrequencyBands();
niklase@google.com470e71d2011-07-07 08:21:25 +00001671 }
1672
peahce4d9152017-05-19 01:28:05 -07001673 if (submodule_states_.RenderMultiBandSubModulesActive()) {
1674 QueueBandedRenderAudio(render_buffer);
1675 }
1676
Alessio Bazzicad2b97402018-08-09 14:23:11 +02001677 // TODO(peah): Perform the queuing inside QueueRenderAudiuo().
Sam Zackrisson2a959d92018-07-23 14:48:07 +00001678 if (private_submodules_->echo_controller) {
Gustaf Ullberg59ff0e22017-10-09 10:20:34 +02001679 private_submodules_->echo_controller->AnalyzeRender(render_buffer);
peahe0eae3c2016-12-14 01:16:23 -08001680 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001681
peah2ace3f92016-09-10 04:42:27 -07001682 if (submodule_states_.RenderMultiBandProcessingActive() &&
peahde65ddc2016-09-16 15:02:15 -07001683 SampleRateSupportsMultiBand(
1684 formats_.render_processing_format.sample_rate_hz())) {
1685 render_buffer->MergeFrequencyBands();
ekmeyerson60d9b332015-08-14 10:35:55 -07001686 }
1687
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001688 return kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +00001689}
1690
1691int AudioProcessingImpl::set_stream_delay_ms(int delay) {
peahdf3efa82015-11-28 12:35:15 -08001692 rtc::CritScope cs(&crit_capture_);
andrew@webrtc.org5f23d642012-05-29 21:14:06 +00001693 Error retval = kNoError;
peahdf3efa82015-11-28 12:35:15 -08001694 capture_.was_stream_delay_set = true;
1695 delay += capture_.delay_offset_ms;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +00001696
niklase@google.com470e71d2011-07-07 08:21:25 +00001697 if (delay < 0) {
andrew@webrtc.org5f23d642012-05-29 21:14:06 +00001698 delay = 0;
1699 retval = kBadStreamParameterWarning;
niklase@google.com470e71d2011-07-07 08:21:25 +00001700 }
1701
1702 // TODO(ajm): the max is rather arbitrarily chosen; investigate.
1703 if (delay > 500) {
andrew@webrtc.org5f23d642012-05-29 21:14:06 +00001704 delay = 500;
1705 retval = kBadStreamParameterWarning;
niklase@google.com470e71d2011-07-07 08:21:25 +00001706 }
1707
peahdf3efa82015-11-28 12:35:15 -08001708 capture_nonlocked_.stream_delay_ms = delay;
andrew@webrtc.org5f23d642012-05-29 21:14:06 +00001709 return retval;
niklase@google.com470e71d2011-07-07 08:21:25 +00001710}
1711
1712int AudioProcessingImpl::stream_delay_ms() const {
peahdf3efa82015-11-28 12:35:15 -08001713 // Used as callback from submodules, hence locking is not allowed.
1714 return capture_nonlocked_.stream_delay_ms;
niklase@google.com470e71d2011-07-07 08:21:25 +00001715}
1716
1717bool AudioProcessingImpl::was_stream_delay_set() const {
peahdf3efa82015-11-28 12:35:15 -08001718 // Used as callback from submodules, hence locking is not allowed.
1719 return capture_.was_stream_delay_set;
niklase@google.com470e71d2011-07-07 08:21:25 +00001720}
1721
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001722void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) {
peahdf3efa82015-11-28 12:35:15 -08001723 rtc::CritScope cs(&crit_capture_);
1724 capture_.key_pressed = key_pressed;
andrew@webrtc.org17e40642014-03-04 20:58:13 +00001725}
1726
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +00001727void AudioProcessingImpl::set_delay_offset_ms(int offset) {
peahdf3efa82015-11-28 12:35:15 -08001728 rtc::CritScope cs(&crit_capture_);
1729 capture_.delay_offset_ms = offset;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +00001730}
1731
1732int AudioProcessingImpl::delay_offset_ms() const {
peahdf3efa82015-11-28 12:35:15 -08001733 rtc::CritScope cs(&crit_capture_);
1734 return capture_.delay_offset_ms;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +00001735}
1736
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001737void AudioProcessingImpl::set_stream_analog_level(int level) {
1738 rtc::CritScope cs_capture(&crit_capture_);
1739 int error = agc1()->set_stream_analog_level(level);
1740 RTC_DCHECK_EQ(kNoError, error);
1741}
1742
1743int AudioProcessingImpl::recommended_stream_analog_level() const {
1744 rtc::CritScope cs_capture(&crit_capture_);
1745 return agc1()->stream_analog_level();
1746}
1747
aleloi868f32f2017-05-23 07:20:05 -07001748void AudioProcessingImpl::AttachAecDump(std::unique_ptr<AecDump> aec_dump) {
1749 RTC_DCHECK(aec_dump);
1750 rtc::CritScope cs_render(&crit_render_);
1751 rtc::CritScope cs_capture(&crit_capture_);
1752
1753 // The previously attached AecDump will be destroyed with the
1754 // 'aec_dump' parameter, which is after locks are released.
1755 aec_dump_.swap(aec_dump);
1756 WriteAecDumpConfigMessage(true);
Minyue Li656d6092018-08-10 15:38:52 +02001757 aec_dump_->WriteInitMessage(formats_.api_format, rtc::TimeUTCMillis());
aleloi868f32f2017-05-23 07:20:05 -07001758}
1759
1760void AudioProcessingImpl::DetachAecDump() {
1761 // The d-tor of a task-queue based AecDump blocks until all pending
1762 // tasks are done. This construction avoids blocking while holding
1763 // the render and capture locks.
1764 std::unique_ptr<AecDump> aec_dump = nullptr;
1765 {
1766 rtc::CritScope cs_render(&crit_render_);
1767 rtc::CritScope cs_capture(&crit_capture_);
1768 aec_dump = std::move(aec_dump_);
1769 }
1770}
1771
Sam Zackrisson4d364492018-03-02 16:03:21 +01001772void AudioProcessingImpl::AttachPlayoutAudioGenerator(
1773 std::unique_ptr<AudioGenerator> audio_generator) {
1774 // TODO(bugs.webrtc.org/8882) Stub.
1775 // Reset internal audio generator with audio_generator.
1776}
1777
1778void AudioProcessingImpl::DetachPlayoutAudioGenerator() {
1779 // TODO(bugs.webrtc.org/8882) Stub.
1780 // Delete audio generator, if one is attached.
1781}
1782
Ivo Creusen56d46092017-11-24 17:29:59 +01001783AudioProcessingStats AudioProcessingImpl::GetStatistics(
Ivo Creusenae026092017-11-20 13:07:16 +01001784 bool has_remote_tracks) const {
Sam Zackrissonb24c00f2018-11-26 16:18:25 +01001785 rtc::CritScope cs_capture(&crit_capture_);
1786 if (!has_remote_tracks) {
1787 return capture_.stats;
1788 }
1789 AudioProcessingStats stats = capture_.stats;
1790 EchoCancellationImpl::Metrics metrics;
1791 if (private_submodules_->echo_controller) {
1792 auto ec_metrics = private_submodules_->echo_controller->GetMetrics();
1793 stats.echo_return_loss = ec_metrics.echo_return_loss;
1794 stats.echo_return_loss_enhancement =
1795 ec_metrics.echo_return_loss_enhancement;
1796 stats.delay_ms = ec_metrics.delay_ms;
Sam Zackrissonb24c00f2018-11-26 16:18:25 +01001797 }
1798 if (config_.residual_echo_detector.enabled) {
1799 RTC_DCHECK(private_submodules_->echo_detector);
1800 auto ed_metrics = private_submodules_->echo_detector->GetMetrics();
1801 stats.residual_echo_likelihood = ed_metrics.echo_likelihood;
1802 stats.residual_echo_likelihood_recent_max =
1803 ed_metrics.echo_likelihood_recent_max;
1804 }
Ivo Creusenae026092017-11-20 13:07:16 +01001805 return stats;
1806}
1807
niklase@google.com470e71d2011-07-07 08:21:25 +00001808GainControl* AudioProcessingImpl::gain_control() const {
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01001809 return public_submodules_->gain_control_config_proxy.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00001810}
1811
niklase@google.com470e71d2011-07-07 08:21:25 +00001812LevelEstimator* AudioProcessingImpl::level_estimator() const {
solenberg949028f2015-12-15 11:39:38 -08001813 return public_submodules_->level_estimator.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00001814}
1815
1816NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
Sam Zackrisson23513132019-01-11 15:10:32 +01001817 return public_submodules_->noise_suppression_proxy.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00001818}
1819
1820VoiceDetection* AudioProcessingImpl::voice_detection() const {
solenberga29386c2015-12-16 03:31:12 -08001821 return public_submodules_->voice_detection.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00001822}
1823
peah8271d042016-11-22 07:24:52 -08001824void AudioProcessingImpl::MutateConfig(
1825 rtc::FunctionView<void(AudioProcessing::Config*)> mutator) {
1826 rtc::CritScope cs_render(&crit_render_);
1827 rtc::CritScope cs_capture(&crit_capture_);
1828 mutator(&config_);
1829 ApplyConfig(config_);
1830}
1831
1832AudioProcessing::Config AudioProcessingImpl::GetConfig() const {
1833 rtc::CritScope cs_render(&crit_render_);
1834 rtc::CritScope cs_capture(&crit_capture_);
1835 return config_;
1836}
1837
peah2ace3f92016-09-10 04:42:27 -07001838bool AudioProcessingImpl::UpdateActiveSubmoduleStates() {
1839 return submodule_states_.Update(
peah8271d042016-11-22 07:24:52 -08001840 config_.high_pass_filter.enabled,
Per Åhgrend547d862019-05-03 15:48:47 +02001841 !!private_submodules_->echo_cancellation,
1842 !!private_submodules_->echo_control_mobile,
ivoc9f4a4a02016-10-28 05:39:16 -07001843 config_.residual_echo_detector.enabled,
peah2ace3f92016-09-10 04:42:27 -07001844 public_submodules_->noise_suppression->is_enabled(),
peah2ace3f92016-09-10 04:42:27 -07001845 public_submodules_->gain_control->is_enabled(),
Alex Loikob5c9a792018-04-16 16:31:22 +02001846 config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
Gustaf Ullbergce045ac2017-10-16 13:49:04 +02001847 capture_nonlocked_.echo_controller_enabled,
peah2ace3f92016-09-10 04:42:27 -07001848 public_submodules_->voice_detection->is_enabled(),
Sam Zackrisson4db667b2018-12-21 16:29:27 +01001849 config_.voice_detection.enabled,
peah2ace3f92016-09-10 04:42:27 -07001850 public_submodules_->level_estimator->is_enabled(),
1851 capture_.transient_suppressor_enabled);
ekmeyerson60d9b332015-08-14 10:35:55 -07001852}
1853
Bjorn Volckeradc46c42015-04-15 11:42:40 +02001854void AudioProcessingImpl::InitializeTransient() {
peahdf3efa82015-11-28 12:35:15 -08001855 if (capture_.transient_suppressor_enabled) {
1856 if (!public_submodules_->transient_suppressor.get()) {
1857 public_submodules_->transient_suppressor.reset(new TransientSuppressor());
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001858 }
peahdf3efa82015-11-28 12:35:15 -08001859 public_submodules_->transient_suppressor->Initialize(
peahde65ddc2016-09-16 15:02:15 -07001860 capture_nonlocked_.capture_processing_format.sample_rate_hz(),
1861 capture_nonlocked_.split_rate, num_proc_channels());
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001862 }
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001863}
1864
Per Åhgren0aefbf02019-08-23 21:29:17 +02001865void AudioProcessingImpl::InitializeHighPassFilter() {
1866 if (submodule_states_.HighPassFilteringRequired()) {
1867 private_submodules_->high_pass_filter.reset(
1868 new HighPassFilter(num_proc_channels()));
peah8271d042016-11-22 07:24:52 -08001869 } else {
Per Åhgren0aefbf02019-08-23 21:29:17 +02001870 private_submodules_->high_pass_filter.reset();
peah8271d042016-11-22 07:24:52 -08001871 }
1872}
alessiob3ec96df2017-05-22 06:57:06 -07001873
Gustaf Ullberg8eb9c7d2017-10-14 08:28:46 +02001874void AudioProcessingImpl::InitializeEchoController() {
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001875 bool use_echo_controller =
1876 echo_control_factory_ ||
Per Åhgren200feba2019-03-06 04:16:46 +01001877 (config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode &&
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001878 !config_.echo_canceller.use_legacy_aec);
1879
1880 if (use_echo_controller) {
1881 // Create and activate the echo controller.
Per Åhgren200feba2019-03-06 04:16:46 +01001882 if (echo_control_factory_) {
1883 private_submodules_->echo_controller =
1884 echo_control_factory_->Create(proc_sample_rate_hz());
1885 } else {
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001886 private_submodules_->echo_controller = std::make_unique<EchoCanceller3>(
Sam Zackrissonfeee1e42019-09-20 07:50:35 +02001887 EchoCanceller3Config(), proc_sample_rate_hz(), num_reverse_channels(),
1888 num_proc_channels());
Per Åhgren200feba2019-03-06 04:16:46 +01001889 }
1890
1891 capture_nonlocked_.echo_controller_enabled = true;
Per Åhgren200feba2019-03-06 04:16:46 +01001892
Per Åhgrenf204faf2019-04-25 15:18:06 +02001893 private_submodules_->echo_cancellation.reset();
1894 aec_render_signal_queue_.reset();
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001895 private_submodules_->echo_control_mobile.reset();
1896 aecm_render_signal_queue_.reset();
Per Åhgrenf204faf2019-04-25 15:18:06 +02001897 return;
peahe0eae3c2016-12-14 01:16:23 -08001898 }
Per Åhgrenf204faf2019-04-25 15:18:06 +02001899
1900 private_submodules_->echo_controller.reset();
1901 capture_nonlocked_.echo_controller_enabled = false;
1902
1903 if (!config_.echo_canceller.enabled) {
1904 private_submodules_->echo_cancellation.reset();
1905 aec_render_signal_queue_.reset();
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001906 private_submodules_->echo_control_mobile.reset();
1907 aecm_render_signal_queue_.reset();
Per Åhgrenf204faf2019-04-25 15:18:06 +02001908 return;
1909 }
1910
1911 if (config_.echo_canceller.mobile_mode) {
1912 // Create and activate AECM.
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001913 size_t max_element_size =
1914 std::max(static_cast<size_t>(1),
1915 kMaxAllowedValuesOfSamplesPerBand *
1916 EchoControlMobileImpl::NumCancellersRequired(
1917 num_output_channels(), num_reverse_channels()));
1918
1919 std::vector<int16_t> template_queue_element(max_element_size);
1920
1921 aecm_render_signal_queue_.reset(
1922 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
1923 kMaxNumFramesToBuffer, template_queue_element,
1924 RenderQueueItemVerifier<int16_t>(max_element_size)));
1925
1926 aecm_render_queue_buffer_.resize(max_element_size);
1927 aecm_capture_queue_buffer_.resize(max_element_size);
1928
1929 private_submodules_->echo_control_mobile.reset(new EchoControlMobileImpl());
1930
1931 private_submodules_->echo_control_mobile->Initialize(
1932 proc_split_sample_rate_hz(), num_reverse_channels(),
1933 num_output_channels());
1934
Per Åhgrenf204faf2019-04-25 15:18:06 +02001935 private_submodules_->echo_cancellation.reset();
1936 aec_render_signal_queue_.reset();
1937 return;
1938 }
1939
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001940 private_submodules_->echo_control_mobile.reset();
1941 aecm_render_signal_queue_.reset();
1942
Per Åhgrenf204faf2019-04-25 15:18:06 +02001943 // Create and activate AEC2.
Per Åhgrenf204faf2019-04-25 15:18:06 +02001944 private_submodules_->echo_cancellation.reset(new EchoCancellationImpl());
1945 private_submodules_->echo_cancellation->SetExtraOptions(
1946 capture_nonlocked_.use_aec2_extended_filter,
1947 capture_nonlocked_.use_aec2_delay_agnostic,
1948 capture_nonlocked_.use_aec2_refined_adaptive_filter);
1949
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001950 size_t element_max_size =
Per Åhgrenf204faf2019-04-25 15:18:06 +02001951 std::max(static_cast<size_t>(1),
1952 kMaxAllowedValuesOfSamplesPerBand *
1953 EchoCancellationImpl::NumCancellersRequired(
1954 num_output_channels(), num_reverse_channels()));
1955
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001956 std::vector<float> template_queue_element(element_max_size);
Per Åhgrenf204faf2019-04-25 15:18:06 +02001957
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001958 aec_render_signal_queue_.reset(
1959 new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>(
1960 kMaxNumFramesToBuffer, template_queue_element,
1961 RenderQueueItemVerifier<float>(element_max_size)));
Per Åhgrenf204faf2019-04-25 15:18:06 +02001962
Per Åhgrenb6e24d72019-04-29 12:14:50 +02001963 aec_render_queue_buffer_.resize(element_max_size);
1964 aec_capture_queue_buffer_.resize(element_max_size);
Per Åhgrenf204faf2019-04-25 15:18:06 +02001965
1966 private_submodules_->echo_cancellation->Initialize(
1967 proc_sample_rate_hz(), num_reverse_channels(), num_output_channels(),
1968 num_proc_channels());
1969
Per Åhgrenf204faf2019-04-25 15:18:06 +02001970 private_submodules_->echo_cancellation->set_suppression_level(
1971 config_.echo_canceller.legacy_moderate_suppression_level
1972 ? EchoCancellationImpl::SuppressionLevel::kModerateSuppression
1973 : EchoCancellationImpl::SuppressionLevel::kHighSuppression);
peahe0eae3c2016-12-14 01:16:23 -08001974}
peah8271d042016-11-22 07:24:52 -08001975
alessiob3ec96df2017-05-22 06:57:06 -07001976void AudioProcessingImpl::InitializeGainController2() {
Alessio Bazzica270f7b52017-10-13 11:05:17 +02001977 if (config_.gain_controller2.enabled) {
1978 private_submodules_->gain_controller2->Initialize(proc_sample_rate_hz());
alessiob3ec96df2017-05-22 06:57:06 -07001979 }
1980}
1981
Alex Loikob5c9a792018-04-16 16:31:22 +02001982void AudioProcessingImpl::InitializePreAmplifier() {
1983 if (config_.pre_amplifier.enabled) {
1984 private_submodules_->pre_amplifier.reset(
1985 new GainApplier(true, config_.pre_amplifier.fixed_gain_factor));
1986 } else {
1987 private_submodules_->pre_amplifier.reset();
1988 }
1989}
1990
ivoc9f4a4a02016-10-28 05:39:16 -07001991void AudioProcessingImpl::InitializeResidualEchoDetector() {
Ivo Creusen09fa4b02018-01-11 16:08:54 +01001992 RTC_DCHECK(private_submodules_->echo_detector);
Ivo Creusen647ef092018-03-14 17:13:48 +01001993 private_submodules_->echo_detector->Initialize(
Ivo Creusenb1facc12018-04-12 16:15:58 +02001994 proc_sample_rate_hz(), 1,
1995 formats_.render_processing_format.sample_rate_hz(), 1);
ivoc9f4a4a02016-10-28 05:39:16 -07001996}
1997
Valeriia Nemychnikovaf06eb572018-08-29 10:37:09 +02001998void AudioProcessingImpl::InitializeAnalyzer() {
1999 if (private_submodules_->capture_analyzer) {
2000 private_submodules_->capture_analyzer->Initialize(proc_sample_rate_hz(),
2001 num_proc_channels());
2002 }
2003}
2004
Sam Zackrisson0beac582017-09-25 12:04:02 +02002005void AudioProcessingImpl::InitializePostProcessor() {
2006 if (private_submodules_->capture_post_processor) {
2007 private_submodules_->capture_post_processor->Initialize(
2008 proc_sample_rate_hz(), num_proc_channels());
2009 }
2010}
2011
Alex Loiko5825aa62017-12-18 16:02:40 +01002012void AudioProcessingImpl::InitializePreProcessor() {
2013 if (private_submodules_->render_pre_processor) {
2014 private_submodules_->render_pre_processor->Initialize(
2015 formats_.render_processing_format.sample_rate_hz(),
2016 formats_.render_processing_format.num_channels());
2017 }
2018}
2019
Per Åhgrenea4c5df2019-05-03 09:00:08 +02002020void AudioProcessingImpl::UpdateHistogramsOnCallEnd() {}
Bjorn Volcker4e7aa432015-07-07 11:50:05 +02002021
aleloi868f32f2017-05-23 07:20:05 -07002022void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) {
2023 if (!aec_dump_) {
2024 return;
2025 }
Per Åhgrenf204faf2019-04-25 15:18:06 +02002026
2027 std::string experiments_description = "";
2028 if (private_submodules_->echo_cancellation) {
2029 experiments_description +=
2030 private_submodules_->echo_cancellation->GetExperimentsDescription();
2031 }
aleloi868f32f2017-05-23 07:20:05 -07002032 // TODO(peah): Add semicolon-separated concatenations of experiment
2033 // descriptions for other submodules.
aleloi868f32f2017-05-23 07:20:05 -07002034 if (constants_.agc_clipped_level_min != kClippedLevelMin) {
2035 experiments_description += "AgcClippingLevelExperiment;";
2036 }
Gustaf Ullbergce045ac2017-10-16 13:49:04 +02002037 if (capture_nonlocked_.echo_controller_enabled) {
2038 experiments_description += "EchoController;";
aleloi868f32f2017-05-23 07:20:05 -07002039 }
Alessio Bazzica270f7b52017-10-13 11:05:17 +02002040 if (config_.gain_controller2.enabled) {
2041 experiments_description += "GainController2;";
2042 }
aleloi868f32f2017-05-23 07:20:05 -07002043
2044 InternalAPMConfig apm_config;
2045
Per Åhgren200feba2019-03-06 04:16:46 +01002046 apm_config.aec_enabled = config_.echo_canceller.enabled;
aleloi868f32f2017-05-23 07:20:05 -07002047 apm_config.aec_delay_agnostic_enabled =
Per Åhgrenf204faf2019-04-25 15:18:06 +02002048 private_submodules_->echo_cancellation &&
Sam Zackrisson7f4dfa42018-11-01 08:59:29 +01002049 private_submodules_->echo_cancellation->is_delay_agnostic_enabled();
aleloi868f32f2017-05-23 07:20:05 -07002050 apm_config.aec_drift_compensation_enabled =
Per Åhgrenf204faf2019-04-25 15:18:06 +02002051 private_submodules_->echo_cancellation &&
Sam Zackrisson7f4dfa42018-11-01 08:59:29 +01002052 private_submodules_->echo_cancellation->is_drift_compensation_enabled();
aleloi868f32f2017-05-23 07:20:05 -07002053 apm_config.aec_extended_filter_enabled =
Per Åhgrenf204faf2019-04-25 15:18:06 +02002054 private_submodules_->echo_cancellation &&
Sam Zackrisson7f4dfa42018-11-01 08:59:29 +01002055 private_submodules_->echo_cancellation->is_extended_filter_enabled();
Per Åhgrenf204faf2019-04-25 15:18:06 +02002056 apm_config.aec_suppression_level =
2057 private_submodules_->echo_cancellation
2058 ? static_cast<int>(
2059 private_submodules_->echo_cancellation->suppression_level())
2060 : 0;
aleloi868f32f2017-05-23 07:20:05 -07002061
Per Åhgrend547d862019-05-03 15:48:47 +02002062 apm_config.aecm_enabled = !!private_submodules_->echo_control_mobile;
aleloi868f32f2017-05-23 07:20:05 -07002063 apm_config.aecm_comfort_noise_enabled =
Per Åhgrenb6e24d72019-04-29 12:14:50 +02002064 private_submodules_->echo_control_mobile &&
Sam Zackrissonc22f5512018-11-05 16:10:00 +01002065 private_submodules_->echo_control_mobile->is_comfort_noise_enabled();
Per Åhgrenb6e24d72019-04-29 12:14:50 +02002066 apm_config.aecm_routing_mode =
2067 private_submodules_->echo_control_mobile
2068 ? static_cast<int>(
2069 private_submodules_->echo_control_mobile->routing_mode())
2070 : 0;
aleloi868f32f2017-05-23 07:20:05 -07002071
2072 apm_config.agc_enabled = public_submodules_->gain_control->is_enabled();
2073 apm_config.agc_mode =
2074 static_cast<int>(public_submodules_->gain_control->mode());
2075 apm_config.agc_limiter_enabled =
2076 public_submodules_->gain_control->is_limiter_enabled();
2077 apm_config.noise_robust_agc_enabled = constants_.use_experimental_agc;
2078
2079 apm_config.hpf_enabled = config_.high_pass_filter.enabled;
2080
2081 apm_config.ns_enabled = public_submodules_->noise_suppression->is_enabled();
2082 apm_config.ns_level =
2083 static_cast<int>(public_submodules_->noise_suppression->level());
2084
2085 apm_config.transient_suppression_enabled =
2086 capture_.transient_suppressor_enabled;
aleloi868f32f2017-05-23 07:20:05 -07002087 apm_config.experiments_description = experiments_description;
Alex Loiko5feb30e2018-04-16 13:52:32 +02002088 apm_config.pre_amplifier_enabled = config_.pre_amplifier.enabled;
2089 apm_config.pre_amplifier_fixed_gain_factor =
2090 config_.pre_amplifier.fixed_gain_factor;
aleloi868f32f2017-05-23 07:20:05 -07002091
2092 if (!forced && apm_config == apm_config_for_aec_dump_) {
2093 return;
2094 }
2095 aec_dump_->WriteConfig(apm_config);
2096 apm_config_for_aec_dump_ = apm_config;
2097}
2098
2099void AudioProcessingImpl::RecordUnprocessedCaptureStream(
2100 const float* const* src) {
2101 RTC_DCHECK(aec_dump_);
2102 WriteAecDumpConfigMessage(false);
2103
2104 const size_t channel_size = formats_.api_format.input_stream().num_frames();
2105 const size_t num_channels = formats_.api_format.input_stream().num_channels();
2106 aec_dump_->AddCaptureStreamInput(
Alex Loikoe36e8bb2018-02-16 11:54:07 +01002107 AudioFrameView<const float>(src, num_channels, channel_size));
aleloi868f32f2017-05-23 07:20:05 -07002108 RecordAudioProcessingState();
2109}
2110
2111void AudioProcessingImpl::RecordUnprocessedCaptureStream(
2112 const AudioFrame& capture_frame) {
2113 RTC_DCHECK(aec_dump_);
2114 WriteAecDumpConfigMessage(false);
2115
2116 aec_dump_->AddCaptureStreamInput(capture_frame);
2117 RecordAudioProcessingState();
2118}
2119
2120void AudioProcessingImpl::RecordProcessedCaptureStream(
2121 const float* const* processed_capture_stream) {
2122 RTC_DCHECK(aec_dump_);
2123
2124 const size_t channel_size = formats_.api_format.output_stream().num_frames();
2125 const size_t num_channels =
2126 formats_.api_format.output_stream().num_channels();
Alex Loikoe36e8bb2018-02-16 11:54:07 +01002127 aec_dump_->AddCaptureStreamOutput(AudioFrameView<const float>(
2128 processed_capture_stream, num_channels, channel_size));
aleloi868f32f2017-05-23 07:20:05 -07002129 aec_dump_->WriteCaptureStreamMessage();
2130}
2131
2132void AudioProcessingImpl::RecordProcessedCaptureStream(
2133 const AudioFrame& processed_capture_frame) {
2134 RTC_DCHECK(aec_dump_);
2135
2136 aec_dump_->AddCaptureStreamOutput(processed_capture_frame);
2137 aec_dump_->WriteCaptureStreamMessage();
2138}
2139
2140void AudioProcessingImpl::RecordAudioProcessingState() {
2141 RTC_DCHECK(aec_dump_);
2142 AecDump::AudioProcessingState audio_proc_state;
2143 audio_proc_state.delay = capture_nonlocked_.stream_delay_ms;
2144 audio_proc_state.drift =
Per Åhgrenf204faf2019-04-25 15:18:06 +02002145 private_submodules_->echo_cancellation
2146 ? private_submodules_->echo_cancellation->stream_drift_samples()
2147 : 0;
Sam Zackrissonf0d1c032019-03-27 13:28:08 +01002148 audio_proc_state.level = agc1()->stream_analog_level();
aleloi868f32f2017-05-23 07:20:05 -07002149 audio_proc_state.keypress = capture_.key_pressed;
2150 aec_dump_->AddAudioProcessingState(audio_proc_state);
2151}
2152
kwiberg83ffe452016-08-29 14:46:07 -07002153AudioProcessingImpl::ApmCaptureState::ApmCaptureState(
Sam Zackrisson9394f6f2018-06-14 10:11:35 +02002154 bool transient_suppressor_enabled)
Per Åhgrenea4c5df2019-05-03 09:00:08 +02002155 : delay_offset_ms(0),
kwiberg83ffe452016-08-29 14:46:07 -07002156 was_stream_delay_set(false),
kwiberg83ffe452016-08-29 14:46:07 -07002157 output_will_be_muted(false),
2158 key_pressed(false),
2159 transient_suppressor_enabled(transient_suppressor_enabled),
peahde65ddc2016-09-16 15:02:15 -07002160 capture_processing_format(kSampleRate16kHz),
peah67995532017-04-10 14:12:41 -07002161 split_rate(kSampleRate16kHz),
Per Åhgren88cf0502018-07-16 17:08:41 +02002162 echo_path_gain_change(false),
Per Åhgrend2650d12018-10-02 17:00:59 +02002163 prev_analog_mic_level(-1),
Fredrik Hernqvistca362852019-05-10 15:50:02 +02002164 prev_pre_amp_gain(-1.f),
2165 playout_volume(-1),
2166 prev_playout_volume(-1) {}
kwiberg83ffe452016-08-29 14:46:07 -07002167
2168AudioProcessingImpl::ApmCaptureState::~ApmCaptureState() = default;
2169
Per Åhgrena1351272019-08-15 12:15:46 +02002170void AudioProcessingImpl::ApmCaptureState::KeyboardInfo::Extract(
2171 const float* const* data,
2172 const StreamConfig& stream_config) {
2173 if (stream_config.has_keyboard()) {
2174 keyboard_data = data[stream_config.num_channels()];
2175 } else {
2176 keyboard_data = NULL;
2177 }
2178 num_keyboard_frames = stream_config.num_frames();
2179}
2180
kwiberg83ffe452016-08-29 14:46:07 -07002181AudioProcessingImpl::ApmRenderState::ApmRenderState() = default;
2182
2183AudioProcessingImpl::ApmRenderState::~ApmRenderState() = default;
2184
niklase@google.com470e71d2011-07-07 08:21:25 +00002185} // namespace webrtc