1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
240654039cde13b3338cc7084cd87d5decbc06fbaandrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1178693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/audio_processing_impl.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com#include <assert.h>
1486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk#include <algorithm>
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
161ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker#include "webrtc/base/checks.h"
17e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.org#include "webrtc/base/platform_file.h"
18369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah#include "webrtc/base/trace_event.h"
1960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson#include "webrtc/common_audio/audio_converter.h"
20dfa36058c945cf2ef9932a566987f648c24fa632Michael Graczyk#include "webrtc/common_audio/channel_buffer.h"
2160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson#include "webrtc/common_audio/include/audio_util.h"
2260730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
231ca324f23770e17d19433ccd3a3b021870d709caBjorn Volckerextern "C" {
241ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker#include "webrtc/modules/audio_processing/aec/aec_core.h"
251ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker}
26788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org#include "webrtc/modules/audio_processing/agc/agc_manager_direct.h"
2778693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/audio_buffer.h"
280f663de2ec25731d538a3a7d9b4d2c21ae61af8dmgraczyk@chromium.org#include "webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h"
29ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org#include "webrtc/modules/audio_processing/common.h"
3056e4a05053d6addc7dbbe2b4d07271305fdbea75andrew@webrtc.org#include "webrtc/modules/audio_processing/echo_cancellation_impl.h"
3178693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
3278693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/gain_control_impl.h"
3378693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/high_pass_filter_impl.h"
3460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson#include "webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.h"
3578693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/level_estimator_impl.h"
3678693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/noise_suppression_impl.h"
3778693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/processing_component.h"
38ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org#include "webrtc/modules/audio_processing/transient/transient_suppressor.h"
3978693fe37ce4b77bb4e93f848768a4ef2b0ab2d8andrew@webrtc.org#include "webrtc/modules/audio_processing/voice_detection_impl.h"
40ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/include/module_common_types.h"
4198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/file_wrapper.h"
4298f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/logging.h"
4398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/metrics.h"
447bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
457bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
467bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org// Files generated at build-time by the protobuf compiler.
47a3736345dd8d90542792d164f269b4bf986dd4baleozwang@webrtc.org#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
48534e495df0bdf2890b10c7ff65e59d96291e1981leozwang@webrtc.org#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
49ce9bfbb33db9ff3e65c9db23ccbfb3467cb0f732leozwang@google.com#else
50808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com#include "webrtc/audio_processing/debug.pb.h"
51ce9bfbb33db9ff3e65c9db23ccbfb3467cb0f732leozwang@google.com#endif
527bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk#define RETURN_ON_ERR(expr) \
5586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  do {                      \
5686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    int err = (expr);       \
5786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    if (err != kNoError) {  \
5886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      return err;           \
5986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    }                       \
6060730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org  } while (0)
6160730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc {
6386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyknamespace {
6486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
6586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczykstatic bool LayoutHasKeyboard(AudioProcessing::ChannelLayout layout) {
6686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  switch (layout) {
6786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    case AudioProcessing::kMono:
6886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    case AudioProcessing::kStereo:
6986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      return false;
7086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    case AudioProcessing::kMonoAndKeyboard:
7186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    case AudioProcessing::kStereoAndKeyboard:
7286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      return true;
7386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  }
7486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
7586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  assert(false);
7686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  return false;
7786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk}
7886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk}  // namespace
7960730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org
8060730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org// Throughout webrtc, it's assumed that success is represented by zero.
812ebfac5649a5e48fbbc501b42a4336ff979c03e6kwiberg@webrtc.orgstatic_assert(AudioProcessing::kNoError == 0, "kNoError must be zero");
8260730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org
83788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org// This class has two main functionalities:
84788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//
85788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org// 1) It is returned instead of the real GainControl after the new AGC has been
86788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    enabled in order to prevent an outside user from overriding compression
87788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    settings. It doesn't do anything in its implementation, except for
88788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    delegating the const methods and Enable calls to the real GainControl, so
89788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    AGC can still be disabled.
90788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//
91788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org// 2) It is injected into AgcManagerDirect and implements volume callbacks for
92788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    getting and setting the volume level. It just caches this value to be used
93788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org//    in VoiceEngine later.
94788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.orgclass GainControlForNewAgc : public GainControl, public VolumeCallbacks {
95788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org public:
96788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  explicit GainControlForNewAgc(GainControlImpl* gain_control)
9786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      : real_gain_control_(gain_control), volume_(0) {}
98788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
99788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  // GainControl implementation.
10014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int Enable(bool enable) override {
101788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->Enable(enable);
102788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
10314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool is_enabled() const override { return real_gain_control_->is_enabled(); }
10414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int set_stream_analog_level(int level) override {
105788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    volume_ = level;
106788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return AudioProcessing::kNoError;
107788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
10814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int stream_analog_level() override { return volume_; }
10914665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int set_mode(Mode mode) override { return AudioProcessing::kNoError; }
11014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  Mode mode() const override { return GainControl::kAdaptiveAnalog; }
11114665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int set_target_level_dbfs(int level) override {
112788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return AudioProcessing::kNoError;
113788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
11414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int target_level_dbfs() const override {
115788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->target_level_dbfs();
116788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
11714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int set_compression_gain_db(int gain) override {
118788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return AudioProcessing::kNoError;
119788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
12014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int compression_gain_db() const override {
121788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->compression_gain_db();
122788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
12314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int enable_limiter(bool enable) override { return AudioProcessing::kNoError; }
12414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool is_limiter_enabled() const override {
125788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->is_limiter_enabled();
126788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
12714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int set_analog_level_limits(int minimum, int maximum) override {
128788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return AudioProcessing::kNoError;
129788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
13014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int analog_level_minimum() const override {
131788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->analog_level_minimum();
132788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
13314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int analog_level_maximum() const override {
134788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->analog_level_maximum();
135788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
13614665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool stream_is_saturated() const override {
137788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    return real_gain_control_->stream_is_saturated();
138788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
139788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
140788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  // VolumeCallbacks implementation.
14114665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void SetMicVolume(int volume) override { volume_ = volume; }
14214665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int GetMicVolume() override { return volume_; }
143788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
144788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org private:
145788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  GainControl* real_gain_control_;
146788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  int volume_;
147788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org};
148788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
1495e465c33cac54ed5265f18413f7afc44aae2dfcasolenbergstruct AudioProcessingImpl::ApmPublicSubmodules {
1505e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  ApmPublicSubmodules()
1515e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg      : echo_cancellation(nullptr),
1525e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg        echo_control_mobile(nullptr),
153a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg        gain_control(nullptr) {}
1545e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  // Accessed externally of APM without any lock acquired.
1555e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  EchoCancellationImpl* echo_cancellation;
1565e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  EchoControlMobileImpl* echo_control_mobile;
1575e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  GainControlImpl* gain_control;
1585e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<HighPassFilterImpl> high_pass_filter;
159949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  rtc::scoped_ptr<LevelEstimatorImpl> level_estimator;
1605e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<NoiseSuppressionImpl> noise_suppression;
161a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  rtc::scoped_ptr<VoiceDetectionImpl> voice_detection;
1625e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<GainControlForNewAgc> gain_control_for_new_agc;
1635e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg
1645e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  // Accessed internally from both render and capture.
1655e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<TransientSuppressor> transient_suppressor;
1665e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<IntelligibilityEnhancer> intelligibility_enhancer;
1675e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg};
1685e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg
1695e465c33cac54ed5265f18413f7afc44aae2dfcasolenbergstruct AudioProcessingImpl::ApmPrivateSubmodules {
1705e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  explicit ApmPrivateSubmodules(Beamformer<float>* beamformer)
1715e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg      : beamformer(beamformer) {}
1725e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  // Accessed internally from capture or during initialization
1735e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  std::list<ProcessingComponent*> component_list;
1745e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<Beamformer<float>> beamformer;
1755e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  rtc::scoped_ptr<AgcManagerDirect> agc_manager;
1765e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg};
1775e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg
178cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebsconst int AudioProcessing::kNativeSampleRatesHz[] = {
179cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    AudioProcessing::kSampleRate8kHz,
180cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    AudioProcessing::kSampleRate16kHz,
181cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    AudioProcessing::kSampleRate32kHz,
182cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    AudioProcessing::kSampleRate48kHz};
183cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebsconst size_t AudioProcessing::kNumNativeSampleRates =
184cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    arraysize(AudioProcessing::kNativeSampleRatesHz);
185cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebsconst int AudioProcessing::kMaxNativeSampleRateHz = AudioProcessing::
186cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    kNativeSampleRatesHz[AudioProcessing::kNumNativeSampleRates - 1];
187cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebsconst int AudioProcessing::kMaxAECMSampleRateHz = kSampleRate16kHz;
188cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs
189e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.orgAudioProcessing* AudioProcessing::Create() {
190e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.org  Config config;
191d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org  return Create(config, nullptr);
192e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.org}
193e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.org
194e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.orgAudioProcessing* AudioProcessing::Create(const Config& config) {
195d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org  return Create(config, nullptr);
196d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org}
197d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org
198d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.orgAudioProcessing* AudioProcessing::Create(const Config& config,
199dfa36058c945cf2ef9932a566987f648c24fa632Michael Graczyk                                         Beamformer<float>* beamformer) {
200d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org  AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (apm->Initialize() != kNoError) {
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete apm;
203df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    apm = nullptr;
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return apm;
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
209e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.orgAudioProcessingImpl::AudioProcessingImpl(const Config& config)
210d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org    : AudioProcessingImpl(config, nullptr) {}
211d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org
212d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.orgAudioProcessingImpl::AudioProcessingImpl(const Config& config,
213dfa36058c945cf2ef9932a566987f648c24fa632Michael Graczyk                                         Beamformer<float>* beamformer)
214df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    : public_submodules_(new ApmPublicSubmodules()),
215df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      private_submodules_(new ApmPrivateSubmodules(beamformer)),
216df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      constants_(config.Get<ExperimentalAgc>().startup_min_volume,
217788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
218df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                 false,
219788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org#else
220df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                 config.Get<ExperimentalAgc>().enabled,
221788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org#endif
2222a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs                 config.Get<Intelligibility>().enabled),
223df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
2241c7075f076987f31c280060b855b6a31312895a6andrew#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
2252a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs      capture_(false,
2261c7075f076987f31c280060b855b6a31312895a6andrew#else
2272a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs      capture_(config.Get<ExperimentalNs>().enabled,
2281c7075f076987f31c280060b855b6a31312895a6andrew#endif
2292a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs               config.Get<Beamforming>().array_geometry,
230b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs               config.Get<Beamforming>().target_direction),
231b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs      capture_nonlocked_(config.Get<Beamforming>().enabled)
232df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah{
233df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
234df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_render(&crit_render_);
235df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_capture(&crit_capture_);
236df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
237df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_cancellation =
238df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        new EchoCancellationImpl(this, &crit_render_, &crit_capture_);
239df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_control_mobile =
240df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        new EchoControlMobileImpl(this, &crit_render_, &crit_capture_);
241df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->gain_control =
242df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        new GainControlImpl(this, &crit_capture_, &crit_capture_);
24370f9903e570931831a027ba6f91c164efc604a85solenberg    public_submodules_->high_pass_filter.reset(
24470f9903e570931831a027ba6f91c164efc604a85solenberg        new HighPassFilterImpl(&crit_capture_));
245949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg    public_submodules_->level_estimator.reset(
246949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg        new LevelEstimatorImpl(&crit_capture_));
2475e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg    public_submodules_->noise_suppression.reset(
2485e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg        new NoiseSuppressionImpl(&crit_capture_));
249a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg    public_submodules_->voice_detection.reset(
250a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg        new VoiceDetectionImpl(&crit_capture_));
251df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->gain_control_for_new_agc.reset(
252df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        new GainControlForNewAgc(public_submodules_->gain_control));
253df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
254df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->component_list.push_back(
255df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->echo_cancellation);
256df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->component_list.push_back(
257df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->echo_control_mobile);
258df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->component_list.push_back(
259df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->gain_control);
260df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
261788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
262e84978f3d8612e7e482791552b94e0847967d3baandrew@webrtc.org  SetExtraOptions(config);
263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comAudioProcessingImpl::~AudioProcessingImpl() {
266df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Depends on gain_control_ and
267df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // public_submodules_->gain_control_for_new_agc.
268df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  private_submodules_->agc_manager.reset();
269df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Depends on gain_control_.
270df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  public_submodules_->gain_control_for_new_agc.reset();
271df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  while (!private_submodules_->component_list.empty()) {
272df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    ProcessingComponent* component =
273df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        private_submodules_->component_list.front();
274df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    component->Destroy();
275df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    delete component;
276df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->component_list.pop_front();
277df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2797bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
280df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
281df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.debug_file->CloseFile();
282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
283df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah#endif
284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::Initialize() {
287df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner during initialization.
288df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
289df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return InitializeLocked();
291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
293ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.orgint AudioProcessingImpl::Initialize(int input_sample_rate_hz,
294ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                    int output_sample_rate_hz,
295a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org                                    int reverse_sample_rate_hz,
296ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                    ChannelLayout input_layout,
297ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                    ChannelLayout output_layout,
298ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                    ChannelLayout reverse_layout) {
29986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  const ProcessingConfig processing_config = {
30060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      {{input_sample_rate_hz,
30160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        ChannelsFromLayout(input_layout),
30286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        LayoutHasKeyboard(input_layout)},
30360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson       {output_sample_rate_hz,
30460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        ChannelsFromLayout(output_layout),
30586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        LayoutHasKeyboard(output_layout)},
30660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson       {reverse_sample_rate_hz,
30760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        ChannelsFromLayout(reverse_layout),
30860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        LayoutHasKeyboard(reverse_layout)},
30960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson       {reverse_sample_rate_hz,
31060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        ChannelsFromLayout(reverse_layout),
31186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        LayoutHasKeyboard(reverse_layout)}}};
31286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
31386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  return Initialize(processing_config);
31486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk}
31586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
31686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczykint AudioProcessingImpl::Initialize(const ProcessingConfig& processing_config) {
317df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner during initialization.
318df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
319df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
32086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  return InitializeLocked(processing_config);
321a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org}
322a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
323df3efa8c079294857a8b8e0a02634d06a6d6b6d6peahint AudioProcessingImpl::MaybeInitializeRender(
32481b9bfe6856bb4f9fd0ba79899f72b8385c58979peah    const ProcessingConfig& processing_config) {
325df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return MaybeInitialize(processing_config);
32681b9bfe6856bb4f9fd0ba79899f72b8385c58979peah}
32781b9bfe6856bb4f9fd0ba79899f72b8385c58979peah
328df3efa8c079294857a8b8e0a02634d06a6d6b6d6peahint AudioProcessingImpl::MaybeInitializeCapture(
32981b9bfe6856bb4f9fd0ba79899f72b8385c58979peah    const ProcessingConfig& processing_config) {
330df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return MaybeInitialize(processing_config);
33181b9bfe6856bb4f9fd0ba79899f72b8385c58979peah}
33281b9bfe6856bb4f9fd0ba79899f72b8385c58979peah
333192164eebc9bbb5c5745f19330b203174304e269peah// Calls InitializeLocked() if any of the audio parameters have changed from
334df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah// their current values (needs to be called while holding the crit_render_lock).
335df3efa8c079294857a8b8e0a02634d06a6d6b6d6peahint AudioProcessingImpl::MaybeInitialize(
336192164eebc9bbb5c5745f19330b203174304e269peah    const ProcessingConfig& processing_config) {
337df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Called from both threads. Thread check is therefore not possible.
338df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (processing_config == formats_.api_format) {
339192164eebc9bbb5c5745f19330b203174304e269peah    return kNoError;
340192164eebc9bbb5c5745f19330b203174304e269peah  }
341df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
342df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
343192164eebc9bbb5c5745f19330b203174304e269peah  return InitializeLocked(processing_config);
344192164eebc9bbb5c5745f19330b203174304e269peah}
345192164eebc9bbb5c5745f19330b203174304e269peah
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::InitializeLocked() {
34786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  const int fwd_audio_buffer_channels =
348b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs      capture_nonlocked_.beamformer_enabled
349df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          ? formats_.api_format.input_stream().num_channels()
350df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          : formats_.api_format.output_stream().num_channels();
35160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  const int rev_audio_buffer_out_num_frames =
352df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.reverse_output_stream().num_frames() == 0
353df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          ? formats_.rev_proc_format.num_frames()
354df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          : formats_.api_format.reverse_output_stream().num_frames();
355df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (formats_.api_format.reverse_input_stream().num_channels() > 0) {
356df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_audio.reset(new AudioBuffer(
357df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        formats_.api_format.reverse_input_stream().num_frames(),
358df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        formats_.api_format.reverse_input_stream().num_channels(),
359df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        formats_.rev_proc_format.num_frames(),
360df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        formats_.rev_proc_format.num_channels(),
36160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        rev_audio_buffer_out_num_frames));
36260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    if (rev_conversion_needed()) {
363df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      render_.render_converter = AudioConverter::Create(
364df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          formats_.api_format.reverse_input_stream().num_channels(),
365df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          formats_.api_format.reverse_input_stream().num_frames(),
366df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          formats_.api_format.reverse_output_stream().num_channels(),
367df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          formats_.api_format.reverse_output_stream().num_frames());
36860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    } else {
369df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      render_.render_converter.reset(nullptr);
37060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    }
37186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  } else {
372df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_audio.reset(nullptr);
373df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_converter.reset(nullptr);
37486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  }
375df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.capture_audio.reset(
376df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      new AudioBuffer(formats_.api_format.input_stream().num_frames(),
377df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                      formats_.api_format.input_stream().num_channels(),
378df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                      capture_nonlocked_.fwd_proc_format.num_frames(),
379df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                      fwd_audio_buffer_channels,
380df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                      formats_.api_format.output_stream().num_frames()));
381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // Initialize all components.
383df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  for (auto item : private_submodules_->component_list) {
384e534086492e92c45d74b176f3c8be4addb69713fmgraczyk@chromium.org    int err = item->Initialize();
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (err != kNoError) {
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      return err;
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
390adc46c4cf7dd8a015b0757c99787d80525c123abBjorn Volcker  InitializeExperimentalAgc();
391adc46c4cf7dd8a015b0757c99787d80525c123abBjorn Volcker  InitializeTransient();
392ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org  InitializeBeamformer();
39360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  InitializeIntelligibility();
39470f9903e570931831a027ba6f91c164efc604a85solenberg  InitializeHighPassFilter();
3955e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  InitializeNoiseSuppression();
396949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  InitializeLevelEstimator();
397a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  InitializeVoiceDetection();
39870f9903e570931831a027ba6f91c164efc604a85solenberg
3997bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
400df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
401808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com    int err = WriteInitMessage();
402808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com    if (err != kNoError) {
403808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com      return err;
404808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com    }
405808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
4067bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif
407808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return kNoError;
409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
41186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczykint AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
41286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  for (const auto& stream : config.streams) {
41386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    if (stream.num_channels() > 0 && stream.sample_rate_hz() <= 0) {
41486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      return kBadSampleRateError;
41586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    }
41664e753c3998a17429418180b3a947231a9fd98cdmagjed  }
41786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
4186955870806624479723addfae6dcf5d13968796cPeter Kasting  const size_t num_in_channels = config.input_stream().num_channels();
4196955870806624479723addfae6dcf5d13968796cPeter Kasting  const size_t num_out_channels = config.output_stream().num_channels();
42086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
42186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  // Need at least one input channel.
42286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  // Need either one output channel or as many outputs as there are inputs.
42386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  if (num_in_channels == 0 ||
42486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk      !(num_out_channels == 1 || num_out_channels == num_in_channels)) {
425a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org    return kBadNumberChannelsError;
426a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org  }
42786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
428b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  if (capture_nonlocked_.beamformer_enabled &&
4296955870806624479723addfae6dcf5d13968796cPeter Kasting      num_in_channels != capture_.array_geometry.size()) {
430d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org    return kBadNumberChannelsError;
431d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org  }
432ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org
433df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  formats_.api_format = config;
434ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org
435ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // We process at the closest native rate >= min(input rate, output rate)...
43686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  const int min_proc_rate =
437df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      std::min(formats_.api_format.input_stream().sample_rate_hz(),
438df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah               formats_.api_format.output_stream().sample_rate_hz());
439ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  int fwd_proc_rate;
440cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  for (size_t i = 0; i < kNumNativeSampleRates; ++i) {
441cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    fwd_proc_rate = kNativeSampleRatesHz[i];
442cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    if (fwd_proc_rate >= min_proc_rate) {
443cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs      break;
444cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    }
445ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  }
446ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // ...with one exception.
447df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (public_submodules_->echo_control_mobile->is_enabled() &&
448cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs      min_proc_rate > kMaxAECMSampleRateHz) {
449cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    fwd_proc_rate = kMaxAECMSampleRateHz;
450ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  }
451ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org
452df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_nonlocked_.fwd_proc_format = StreamConfig(fwd_proc_rate);
453ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org
454ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // We normally process the reverse stream at 16 kHz. Unless...
455ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  int rev_proc_rate = kSampleRate16kHz;
456df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate8kHz) {
457ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    // ...the forward stream is at 8 kHz.
458ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    rev_proc_rate = kSampleRate8kHz;
459ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  } else {
460df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (formats_.api_format.reverse_input_stream().sample_rate_hz() ==
46160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson        kSampleRate32kHz) {
462ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      // ...or the input is at 32 kHz, in which case we use the splitting
463ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      // filter rather than the resampler.
464ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      rev_proc_rate = kSampleRate32kHz;
465ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    }
466a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org  }
467a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
46830be827e6a2bfae76c445e62d0853f83d238814aandrew@webrtc.org  // Always downmix the reverse stream to mono for analysis. This has been
46930be827e6a2bfae76c445e62d0853f83d238814aandrew@webrtc.org  // demonstrated to work well for AEC in most practical scenarios.
470df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  formats_.rev_proc_format = StreamConfig(rev_proc_rate, 1);
471a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
472df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate32kHz ||
473df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate48kHz) {
474df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    capture_nonlocked_.split_rate = kSampleRate16kHz;
475a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org  } else {
476df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    capture_nonlocked_.split_rate =
477df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.fwd_proc_format.sample_rate_hz();
478a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org  }
479a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
480a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org  return InitializeLocked();
481a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org}
482a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
48361e596fc49443971219aa3989b200407d919f6c5andrew@webrtc.orgvoid AudioProcessingImpl::SetExtraOptions(const Config& config) {
484df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner when setting the extra options.
485df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
486df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
487df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  for (auto item : private_submodules_->component_list) {
488e534086492e92c45d74b176f3c8be4addb69713fmgraczyk@chromium.org    item->SetExtraOptions(config);
489e534086492e92c45d74b176f3c8be4addb69713fmgraczyk@chromium.org  }
490788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
491df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_.transient_suppressor_enabled !=
492df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      config.Get<ExperimentalNs>().enabled) {
493df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    capture_.transient_suppressor_enabled =
494df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        config.Get<ExperimentalNs>().enabled;
495788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    InitializeTransient();
496788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
4972a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs
4982a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
499b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  if (capture_nonlocked_.beamformer_enabled !=
500b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs          config.Get<Beamforming>().enabled) {
501b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs    capture_nonlocked_.beamformer_enabled = config.Get<Beamforming>().enabled;
5022a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs    if (config.Get<Beamforming>().array_geometry.size() > 1) {
5032a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs      capture_.array_geometry = config.Get<Beamforming>().array_geometry;
5042a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs    }
5052a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs    capture_.target_direction = config.Get<Beamforming>().target_direction;
5062a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs    InitializeBeamformer();
5072a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs  }
5082a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs#endif  // WEBRTC_ANDROID_PLATFORM_BUILD
50961e596fc49443971219aa3989b200407d919f6c5andrew@webrtc.org}
51061e596fc49443971219aa3989b200407d919f6c5andrew@webrtc.org
51166085beef83c790a69666b9be8a74bb2eee44fabpeahint AudioProcessingImpl::input_sample_rate_hz() const {
51266085beef83c790a69666b9be8a74bb2eee44fabpeah  // Accessed from outside APM, hence a lock is needed.
51366085beef83c790a69666b9be8a74bb2eee44fabpeah  rtc::CritScope cs(&crit_capture_);
51466085beef83c790a69666b9be8a74bb2eee44fabpeah  return formats_.api_format.input_stream().sample_rate_hz();
51566085beef83c790a69666b9be8a74bb2eee44fabpeah}
51666085beef83c790a69666b9be8a74bb2eee44fabpeah
517ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.orgint AudioProcessingImpl::proc_sample_rate_hz() const {
518df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
519df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return capture_nonlocked_.fwd_proc_format.sample_rate_hz();
520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
522ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.orgint AudioProcessingImpl::proc_split_sample_rate_hz() const {
523df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
524df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return capture_nonlocked_.split_rate;
525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5276955870806624479723addfae6dcf5d13968796cPeter Kastingsize_t AudioProcessingImpl::num_reverse_channels() const {
528df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
529df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return formats_.rev_proc_format.num_channels();
530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5326955870806624479723addfae6dcf5d13968796cPeter Kastingsize_t AudioProcessingImpl::num_input_channels() const {
533df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
534df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return formats_.api_format.input_stream().num_channels();
535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5376955870806624479723addfae6dcf5d13968796cPeter Kastingsize_t AudioProcessingImpl::num_proc_channels() const {
538b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  // Used as callback from submodules, hence locking is not allowed.
539b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  return capture_nonlocked_.beamformer_enabled ? 1 : num_output_channels();
540b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs}
541b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs
5426955870806624479723addfae6dcf5d13968796cPeter Kastingsize_t AudioProcessingImpl::num_output_channels() const {
543df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
544df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return formats_.api_format.output_stream().num_channels();
545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
54717342e5092430c3893246077aee3b727298df117andrew@webrtc.orgvoid AudioProcessingImpl::set_output_will_be_muted(bool muted) {
548df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_capture_);
549df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.output_will_be_muted = muted;
550df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (private_submodules_->agc_manager.get()) {
551df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->agc_manager->SetCaptureMuted(
552df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.output_will_be_muted);
553788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
55417342e5092430c3893246077aee3b727298df117andrew@webrtc.org}
55517342e5092430c3893246077aee3b727298df117andrew@webrtc.org
55617342e5092430c3893246077aee3b727298df117andrew@webrtc.org
557ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.orgint AudioProcessingImpl::ProcessStream(const float* const* src,
558dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                       size_t samples_per_channel,
559ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                       int input_sample_rate_hz,
56017e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org                                       ChannelLayout input_layout,
561ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                       int output_sample_rate_hz,
562ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                       ChannelLayout output_layout,
563ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org                                       float* const* dest) {
564369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_ChannelLayout");
565df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  StreamConfig input_stream;
566df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  StreamConfig output_stream;
567df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
568df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Access the formats_.api_format.input_stream beneath the capture lock.
569df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // The lock must be released as it is later required in the call
570df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // to ProcessStream(,,,);
571df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs(&crit_capture_);
572df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    input_stream = formats_.api_format.input_stream();
573df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    output_stream = formats_.api_format.output_stream();
574df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
575df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
57686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  input_stream.set_sample_rate_hz(input_sample_rate_hz);
57786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  input_stream.set_num_channels(ChannelsFromLayout(input_layout));
57886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  input_stream.set_has_keyboard(LayoutHasKeyboard(input_layout));
57986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  output_stream.set_sample_rate_hz(output_sample_rate_hz);
58086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  output_stream.set_num_channels(ChannelsFromLayout(output_layout));
58186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  output_stream.set_has_keyboard(LayoutHasKeyboard(output_layout));
58286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
58386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  if (samples_per_channel != input_stream.num_frames()) {
58486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    return kBadDataLengthError;
58586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  }
58686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  return ProcessStream(src, input_stream, output_stream, dest);
58786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk}
58886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
58986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczykint AudioProcessingImpl::ProcessStream(const float* const* src,
59086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk                                       const StreamConfig& input_config,
59186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk                                       const StreamConfig& output_config,
59286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk                                       float* const* dest) {
593369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_StreamConfig");
594df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  ProcessingConfig processing_config;
595df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
596df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Acquire the capture lock in order to safely call the function
597df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // that retrieves the render side data. This function accesses apm
598df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // getters that need the capture lock held when being called.
599df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_capture(&crit_capture_);
600df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_cancellation->ReadQueuedRenderData();
601df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_control_mobile->ReadQueuedRenderData();
602df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->gain_control->ReadQueuedRenderData();
603df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
604df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!src || !dest) {
605df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      return kNullPointerError;
606df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    }
60760730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org
608df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    processing_config = formats_.api_format;
609df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
610fa6228e221d818af55e3d8343c792f2c1ecc7252peah
61186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.input_stream() = input_config;
61286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.output_stream() = output_config;
61386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
614df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
615df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Do conditional reinitialization.
616df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_render(&crit_render_);
617df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(MaybeInitializeCapture(processing_config));
618df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
619df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
62086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  assert(processing_config.input_stream().num_frames() ==
621df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah         formats_.api_format.input_stream().num_frames());
62217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
62317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
624df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
62513b96ba90f72164134019cbfc07d4a47cf1fd091Minyue    RETURN_ON_ERR(WriteConfigMessage(false));
62613b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
627df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.capture.event_msg->set_type(audioproc::Event::STREAM);
628df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
62959a1b1b92850747a0e758b9668f725ed9e961a33aluebs@webrtc.org    const size_t channel_size =
630df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        sizeof(float) * formats_.api_format.input_stream().num_frames();
6316955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < formats_.api_format.input_stream().num_channels();
6326955870806624479723addfae6dcf5d13968796cPeter Kasting         ++i)
633ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      msg->add_input_channel(src[i], channel_size);
63417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
63517e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#endif
63617e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
637df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.capture_audio->CopyFrom(src, formats_.api_format.input_stream());
63817e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  RETURN_ON_ERR(ProcessStreamLocked());
639df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.capture_audio->CopyTo(formats_.api_format.output_stream(), dest);
64017e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
64117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
642df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
643df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
64459a1b1b92850747a0e758b9668f725ed9e961a33aluebs@webrtc.org    const size_t channel_size =
645df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        sizeof(float) * formats_.api_format.output_stream().num_frames();
6466955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < formats_.api_format.output_stream().num_channels();
6476955870806624479723addfae6dcf5d13968796cPeter Kasting         ++i)
648ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      msg->add_output_channel(dest[i], channel_size);
649df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
650df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                          &crit_debug_, &debug_dump_.capture));
65117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
65217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#endif
65317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
65417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  return kNoError;
65517e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org}
65617e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
65717e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.orgint AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
658369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_AudioFrame");
659df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
660df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Acquire the capture lock in order to safely call the function
661df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // that retrieves the render side data. This function accesses apm
662df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // getters that need the capture lock held when being called.
663df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // The lock needs to be released as
664df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // public_submodules_->echo_control_mobile->is_enabled() aquires this lock
665df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // as well.
666df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_capture(&crit_capture_);
667df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_cancellation->ReadQueuedRenderData();
668df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->echo_control_mobile->ReadQueuedRenderData();
669df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->gain_control->ReadQueuedRenderData();
670df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
671fa6228e221d818af55e3d8343c792f2c1ecc7252peah
67217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  if (!frame) {
67360730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org    return kNullPointerError;
67460730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org  }
675ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // Must be a native rate.
676ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  if (frame->sample_rate_hz_ != kSampleRate8kHz &&
677ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      frame->sample_rate_hz_ != kSampleRate16kHz &&
678087da13fe8be20b61b556f60eac937c9d0b19fb8aluebs@webrtc.org      frame->sample_rate_hz_ != kSampleRate32kHz &&
679087da13fe8be20b61b556f60eac937c9d0b19fb8aluebs@webrtc.org      frame->sample_rate_hz_ != kSampleRate48kHz) {
680ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    return kBadSampleRateError;
681ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  }
682192164eebc9bbb5c5745f19330b203174304e269peah
683df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (public_submodules_->echo_control_mobile->is_enabled() &&
684cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs      frame->sample_rate_hz_ > kMaxAECMSampleRateHz) {
685ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates";
686ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    return kUnsupportedComponentError;
687ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  }
68817e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
689df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  ProcessingConfig processing_config;
690df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
691df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Aquire lock for the access of api_format.
692df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // The lock is released immediately due to the conditional
693df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // reinitialization.
694df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_capture(&crit_capture_);
695df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // TODO(ajm): The input and output rates and channels are currently
696df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // constrained to be identical in the int16 interface.
697df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    processing_config = formats_.api_format;
698df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
69986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.input_stream().set_sample_rate_hz(frame->sample_rate_hz_);
70086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.input_stream().set_num_channels(frame->num_channels_);
70186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.output_stream().set_sample_rate_hz(frame->sample_rate_hz_);
70286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  processing_config.output_stream().set_num_channels(frame->num_channels_);
70386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
704df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
705df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Do conditional reinitialization.
706df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs_render(&crit_render_);
707df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(MaybeInitializeCapture(processing_config));
708df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  }
709df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
710192164eebc9bbb5c5745f19330b203174304e269peah  if (frame->samples_per_channel_ !=
711df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.input_stream().num_frames()) {
712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return kBadDataLengthError;
713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7157bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
716df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
717df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.capture.event_msg->set_type(audioproc::Event::STREAM);
718df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
71986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    const size_t data_size =
72086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
72163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    msg->set_input_data(frame->data_, data_size);
722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
7237bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
725df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.capture_audio->DeinterleaveFrom(frame);
72617e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  RETURN_ON_ERR(ProcessStreamLocked());
727df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.capture_audio->InterleaveTo(frame,
728df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                       output_copy_needed(is_data_processed()));
72917e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
73017e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
731df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
732df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
73386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    const size_t data_size =
73486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
73517e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org    msg->set_output_data(frame->data_, data_size);
736df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
737df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                          &crit_debug_, &debug_dump_.capture));
73817e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
73917e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#endif
74017e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
74117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  return kNoError;
74217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org}
74317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
74417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.orgint AudioProcessingImpl::ProcessStreamLocked() {
74517e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
746df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
747df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
748df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    msg->set_delay(capture_nonlocked_.stream_delay_ms);
749df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    msg->set_drift(
750df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->echo_cancellation->stream_drift_samples());
75163da1dd9720533990842f1e0aa94bf8269c86ae4bjornv@webrtc.org    msg->set_level(gain_control()->stream_analog_level());
752df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    msg->set_keypress(capture_.key_pressed);
75317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
75417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org#endif
755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7561ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker  MaybeUpdateHistograms();
7571ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker
758df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  AudioBuffer* ca = capture_.capture_audio.get();  // For brevity.
75960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
760df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.use_new_agc &&
761df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->gain_control->is_enabled()) {
762df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->agc_manager->AnalyzePreProcess(
763df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ca->channels()[0], ca->num_channels(),
764df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.fwd_proc_format.num_frames());
765788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
766788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
767369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org  bool data_processed = is_data_processed();
768369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org  if (analysis_needed(data_processed)) {
769be05c74ec8ee975f3451809425756d0f6a51ff2ealuebs@webrtc.org    ca->SplitIntoFrequencyBands();
770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
772df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.intelligibility_enabled) {
773df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->intelligibility_enhancer->AnalyzeCaptureAudio(
774df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ca->split_channels_f(kBand0To8kHz), capture_nonlocked_.split_rate,
775df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ca->num_channels());
77660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
77760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
778b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  if (capture_nonlocked_.beamformer_enabled) {
779df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->beamformer->ProcessChunk(*ca->split_data_f(),
780df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                                  ca->split_data_f());
781ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org    ca->set_num_channels(1);
782ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org  }
783ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org
78470f9903e570931831a027ba6f91c164efc604a85solenberg  public_submodules_->high_pass_filter->ProcessCaptureAudio(ca);
785df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(public_submodules_->gain_control->AnalyzeCaptureAudio(ca));
7865e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  public_submodules_->noise_suppression->AnalyzeCaptureAudio(ca);
787df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(public_submodules_->echo_cancellation->ProcessCaptureAudio(ca));
788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
789df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (public_submodules_->echo_control_mobile->is_enabled() &&
790df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->noise_suppression->is_enabled()) {
791103657b48442dedd1742fca4a73d5131bf4ae624andrew@webrtc.org    ca->CopyLowPassToReference();
792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
7935e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  public_submodules_->noise_suppression->ProcessCaptureAudio(ca);
794df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(
795df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_control_mobile->ProcessCaptureAudio(ca));
796a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  public_submodules_->voice_detection->ProcessCaptureAudio(ca);
797788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
798df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.use_new_agc &&
799df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->gain_control->is_enabled() &&
800b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs      (!capture_nonlocked_.beamformer_enabled ||
801df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah       private_submodules_->beamformer->is_target_present())) {
802df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->agc_manager->Process(
803df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ca->split_bands_const(0)[kBand0To8kHz], ca->num_frames_per_band(),
804df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.split_rate);
805788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
806df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(public_submodules_->gain_control->ProcessCaptureAudio(ca));
807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
808369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org  if (synthesis_needed(data_processed)) {
809be05c74ec8ee975f3451809425756d0f6a51ff2ealuebs@webrtc.org    ca->MergeFrequencyBands();
810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
812788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  // TODO(aluebs): Investigate if the transient suppression placement should be
813788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  // before or after the AGC.
814df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_.transient_suppressor_enabled) {
815788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    float voice_probability =
816df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        private_submodules_->agc_manager.get()
817df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah            ? private_submodules_->agc_manager->voice_probability()
818df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah            : 1.f;
819788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
820df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->transient_suppressor->Suppress(
82186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        ca->channels_f()[0], ca->num_frames(), ca->num_channels(),
82286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        ca->split_bands_const_f(0)[kBand0To8kHz], ca->num_frames_per_band(),
82386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        ca->keyboard_data(), ca->num_keyboard_frames(), voice_probability,
824df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.key_pressed);
825788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
826788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
827755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org  // The level estimator operates on the recombined data.
828949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  public_submodules_->level_estimator->ProcessStream(ca);
82917e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
830df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.was_stream_delay_set = false;
83117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  return kNoError;
83217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org}
83317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
83417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.orgint AudioProcessingImpl::AnalyzeReverseStream(const float* const* data,
835dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                              size_t samples_per_channel,
83660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson                                              int rev_sample_rate_hz,
83717e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org                                              ChannelLayout layout) {
838369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::AnalyzeReverseStream_ChannelLayout");
839df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_render_);
84086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  const StreamConfig reverse_config = {
84160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      rev_sample_rate_hz, ChannelsFromLayout(layout), LayoutHasKeyboard(layout),
84286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  };
84386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  if (samples_per_channel != reverse_config.num_frames()) {
84486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    return kBadDataLengthError;
84586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  }
846df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return AnalyzeReverseStreamLocked(data, reverse_config, reverse_config);
84760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}
84860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
84960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonint AudioProcessingImpl::ProcessReverseStream(
85060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const float* const* src,
85160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const StreamConfig& reverse_input_config,
85260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const StreamConfig& reverse_output_config,
85360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    float* const* dest) {
854369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_StreamConfig");
855df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_render_);
856df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(AnalyzeReverseStreamLocked(src, reverse_input_config,
857df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                           reverse_output_config));
85860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  if (is_rev_processed()) {
859df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_audio->CopyTo(formats_.api_format.reverse_output_stream(),
860df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                 dest);
86181b9bfe6856bb4f9fd0ba79899f72b8385c58979peah  } else if (render_check_rev_conversion_needed()) {
862df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_converter->Convert(src, reverse_input_config.num_samples(),
863df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                      dest,
864df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                      reverse_output_config.num_samples());
86560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  } else {
86660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    CopyAudioIfNeeded(src, reverse_input_config.num_frames(),
86760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson                      reverse_input_config.num_channels(), dest);
86860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
86960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
87060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  return kNoError;
87186c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk}
87286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
873df3efa8c079294857a8b8e0a02634d06a6d6b6d6peahint AudioProcessingImpl::AnalyzeReverseStreamLocked(
87460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const float* const* src,
87560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const StreamConfig& reverse_input_config,
87660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    const StreamConfig& reverse_output_config) {
877df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (src == nullptr) {
87817e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org    return kNullPointerError;
87917e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
880755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
8816955870806624479723addfae6dcf5d13968796cPeter Kasting  if (reverse_input_config.num_channels() == 0) {
88286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    return kBadNumberChannelsError;
88317e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
885df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  ProcessingConfig processing_config = formats_.api_format;
88660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_input_stream() = reverse_input_config;
88760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_output_stream() = reverse_output_config;
88886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
889df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(MaybeInitializeRender(processing_config));
89060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  assert(reverse_input_config.num_frames() ==
891df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah         formats_.api_format.reverse_input_stream().num_frames());
89286c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
8937bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
894df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
895df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.render.event_msg->set_type(audioproc::Event::REVERSE_STREAM);
896df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::ReverseStream* msg =
897df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        debug_dump_.render.event_msg->mutable_reverse_stream();
89859a1b1b92850747a0e758b9668f725ed9e961a33aluebs@webrtc.org    const size_t channel_size =
899df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        sizeof(float) * formats_.api_format.reverse_input_stream().num_frames();
9006955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0;
901df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah         i < formats_.api_format.reverse_input_stream().num_channels(); ++i)
90260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      msg->add_channel(src[i], channel_size);
903df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
904df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                          &crit_debug_, &debug_dump_.render));
905808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
9067bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif
907808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
908df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  render_.render_audio->CopyFrom(src,
909df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                 formats_.api_format.reverse_input_stream());
91060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  return ProcessReverseStreamLocked();
91160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}
91260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
91360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonint AudioProcessingImpl::ProcessReverseStream(AudioFrame* frame) {
914369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::ProcessReverseStream_AudioFrame");
91560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  RETURN_ON_ERR(AnalyzeReverseStream(frame));
916df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_render_);
91760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  if (is_rev_processed()) {
918df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    render_.render_audio->InterleaveTo(frame, true);
91960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
92060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
92160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  return kNoError;
922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
925369f828bfe9f42e9d1d712e8493fbbd7e776b9c3peah  TRACE_EVENT0("webrtc", "AudioProcessing::AnalyzeReverseStream_AudioFrame");
926df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_render_);
927df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (frame == nullptr) {
928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return kNullPointerError;
929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
930ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // Must be a native rate.
931ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  if (frame->sample_rate_hz_ != kSampleRate8kHz &&
932ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org      frame->sample_rate_hz_ != kSampleRate16kHz &&
933087da13fe8be20b61b556f60eac937c9d0b19fb8aluebs@webrtc.org      frame->sample_rate_hz_ != kSampleRate32kHz &&
934087da13fe8be20b61b556f60eac937c9d0b19fb8aluebs@webrtc.org      frame->sample_rate_hz_ != kSampleRate48kHz) {
935ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org    return kBadSampleRateError;
936ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  }
937ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org  // This interface does not tolerate different forward and reverse rates.
938192164eebc9bbb5c5745f19330b203174304e269peah  if (frame->sample_rate_hz_ !=
939df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.input_stream().sample_rate_hz()) {
940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return kBadSampleRateError;
941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
942a8b97373d5d3154357cc6589ff949ee9f6f99d8dandrew@webrtc.org
94386c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  if (frame->num_channels_ <= 0) {
94486c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    return kBadNumberChannelsError;
94586c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  }
94686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
947df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  ProcessingConfig processing_config = formats_.api_format;
94860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_input_stream().set_sample_rate_hz(
94960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      frame->sample_rate_hz_);
95060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_input_stream().set_num_channels(
95160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      frame->num_channels_);
95260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_output_stream().set_sample_rate_hz(
95360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      frame->sample_rate_hz_);
95460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  processing_config.reverse_output_stream().set_num_channels(
95560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      frame->num_channels_);
95686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk
957df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(MaybeInitializeRender(processing_config));
95886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  if (frame->samples_per_channel_ !=
959df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.reverse_input_stream().num_frames()) {
96017e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org    return kBadDataLengthError;
96117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  }
962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9637bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
964df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
965df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.render.event_msg->set_type(audioproc::Event::REVERSE_STREAM);
966df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    audioproc::ReverseStream* msg =
967df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        debug_dump_.render.event_msg->mutable_reverse_stream();
96886c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    const size_t data_size =
96986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk        sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
97063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    msg->set_data(frame->data_, data_size);
971df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
972df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                          &crit_debug_, &debug_dump_.render));
973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
9747bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif
975df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  render_.render_audio->DeinterleaveFrom(frame);
97660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  return ProcessReverseStreamLocked();
97717e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org}
978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
97960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonint AudioProcessingImpl::ProcessReverseStreamLocked() {
980df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  AudioBuffer* ra = render_.render_audio.get();  // For brevity.
981df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (formats_.rev_proc_format.sample_rate_hz() == kSampleRate32kHz) {
982be05c74ec8ee975f3451809425756d0f6a51ff2ealuebs@webrtc.org    ra->SplitIntoFrequencyBands();
983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
985df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.intelligibility_enabled) {
986df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Currently run in single-threaded mode when the intelligibility
987df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // enhancer is activated.
988df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // TODO(peah): Fix to be properly multi-threaded.
989df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CritScope cs(&crit_capture_);
990df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->intelligibility_enhancer->ProcessRenderAudio(
991df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ra->split_channels_f(kBand0To8kHz), capture_nonlocked_.split_rate,
992df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        ra->num_channels());
99360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
99460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
995df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(public_submodules_->echo_cancellation->ProcessRenderAudio(ra));
996df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(
997df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_control_mobile->ProcessRenderAudio(ra));
998df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (!constants_.use_new_agc) {
999df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    RETURN_ON_ERR(public_submodules_->gain_control->ProcessRenderAudio(ra));
1000788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
1001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1002df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (formats_.rev_proc_format.sample_rate_hz() == kSampleRate32kHz &&
100360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson      is_rev_processed()) {
100460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    ra->MergeFrequencyBands();
100560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
100660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
100717e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  return kNoError;
1008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::set_stream_delay_ms(int delay) {
1011df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_capture_);
10125f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org  Error retval = kNoError;
1013df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.was_stream_delay_set = true;
1014df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  delay += capture_.delay_offset_ms;
10156f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.org
1016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (delay < 0) {
10175f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org    delay = 0;
10185f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org    retval = kBadStreamParameterWarning;
1019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // TODO(ajm): the max is rather arbitrarily chosen; investigate.
1022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (delay > 500) {
10235f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org    delay = 500;
10245f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org    retval = kBadStreamParameterWarning;
1025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1027df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_nonlocked_.stream_delay_ms = delay;
10285f23d64cf2da06b45c2c1c837bb11d260cb85ecfandrew@webrtc.org  return retval;
1029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::stream_delay_ms() const {
1032df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
1033df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return capture_nonlocked_.stream_delay_ms;
1034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool AudioProcessingImpl::was_stream_delay_set() const {
1037df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Used as callback from submodules, hence locking is not allowed.
1038df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return capture_.was_stream_delay_set;
1039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
104117e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.orgvoid AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) {
1042df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_capture_);
1043df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.key_pressed = key_pressed;
104417e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org}
104517e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org
10466f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.orgvoid AudioProcessingImpl::set_delay_offset_ms(int offset) {
1047df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_capture_);
1048df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.delay_offset_ms = offset;
10496f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.org}
10506f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.org
10516f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.orgint AudioProcessingImpl::delay_offset_ms() const {
1052df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs(&crit_capture_);
1053df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return capture_.delay_offset_ms;
10546f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.org}
10556f9f817e06776f0c181809dc7748639599bcf42eandrew@webrtc.org
1056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::StartDebugRecording(
1057a4df27b6713583045e51e20c4eb93718d15ca33eivoc    const char filename[AudioProcessing::kMaxFilenameSize]) {
1058df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner.
1059df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
1060df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
1061664cdafb8ad7ccef531cb6bf7bd42752841f220fAndré Susano Pinto  static_assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize, "");
1062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1063df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (filename == nullptr) {
1064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return kNullPointerError;
1065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
10677bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // Stop any ongoing recording.
1069df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
1070df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (debug_dump_.debug_file->CloseFile() == -1) {
1071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      return kFileError;
1072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1075df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->OpenFile(filename, false) == -1) {
1076df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    debug_dump_.debug_file->CloseFile();
1077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return kFileError;
1078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
108013b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  RETURN_ON_ERR(WriteConfigMessage(true));
108113b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  RETURN_ON_ERR(WriteInitMessage());
1082863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  return kNoError;
1083863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org#else
1084863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  return kUnsupportedFunctionError;
1085863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1086863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org}
1087863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org
1088a4df27b6713583045e51e20c4eb93718d15ca33eivocint AudioProcessingImpl::StartDebugRecording(FILE* handle) {
1089df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner.
1090df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
1091df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
1092863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org
1093df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (handle == nullptr) {
1094863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org    return kNullPointerError;
1095863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  }
1096863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org
1097863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1098863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  // Stop any ongoing recording.
1099df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
1100df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (debug_dump_.debug_file->CloseFile() == -1) {
1101863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org      return kFileError;
1102863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org    }
1103863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  }
1104863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org
1105df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->OpenFromFileHandle(handle, true, false) == -1) {
1106863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org    return kFileError;
1107863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org  }
1108863b5361003e36451a946ca6f9886efb3c1bfa53henrikg@webrtc.org
110913b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  RETURN_ON_ERR(WriteConfigMessage(true));
111013b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  RETURN_ON_ERR(WriteInitMessage());
1111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return kNoError;
11127bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#else
11137bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  return kUnsupportedFunctionError;
11147bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1117e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.orgint AudioProcessingImpl::StartDebugRecordingForPlatformFile(
1118e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.org    rtc::PlatformFile handle) {
1119df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner.
1120df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
1121df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
1122e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.org  FILE* stream = rtc::FdopenPlatformFileForWriting(handle);
1123a4df27b6713583045e51e20c4eb93718d15ca33eivoc  return StartDebugRecording(stream);
1124e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.org}
1125e46bc77e941f12ca24b04cf42fca98e15bc139eexians@webrtc.org
1126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint AudioProcessingImpl::StopDebugRecording() {
1127df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner.
1128df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
1129df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
11307bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
11317bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // We just return if recording hasn't started.
1133df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (debug_dump_.debug_file->Open()) {
1134df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (debug_dump_.debug_file->CloseFile() == -1) {
1135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      return kFileError;
1136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return kNoError;
11397bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#else
11407bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  return kUnsupportedFunctionError;
11417bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comEchoCancellation* AudioProcessingImpl::echo_cancellation() const {
1145df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1146df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
1147df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return public_submodules_->echo_cancellation;
1148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comEchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
1151df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1152df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
1153df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return public_submodules_->echo_control_mobile;
1154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comGainControl* AudioProcessingImpl::gain_control() const {
1157df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1158df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
1159df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.use_new_agc) {
1160df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    return public_submodules_->gain_control_for_new_agc.get();
1161788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
1162df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return public_submodules_->gain_control;
1163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comHighPassFilter* AudioProcessingImpl::high_pass_filter() const {
1166df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1167df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
116870f9903e570931831a027ba6f91c164efc604a85solenberg  return public_submodules_->high_pass_filter.get();
1169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comLevelEstimator* AudioProcessingImpl::level_estimator() const {
1172df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1173df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
1174949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  return public_submodules_->level_estimator.get();
1175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comNoiseSuppression* AudioProcessingImpl::noise_suppression() const {
1178df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1179df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
11805e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  return public_submodules_->noise_suppression.get();
1181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comVoiceDetection* AudioProcessingImpl::voice_detection() const {
1184df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Adding a lock here has no effect as it allows any access to the submodule
1185df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // from the returned pointer.
1186a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  return public_submodules_->voice_detection.get();
1187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1189369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.orgbool AudioProcessingImpl::is_data_processed() const {
1190b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  if (capture_nonlocked_.beamformer_enabled) {
1191ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org    return true;
1192ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org  }
1193ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org
11947bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  int enabled_count = 0;
1195df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  for (auto item : private_submodules_->component_list) {
1196e534086492e92c45d74b176f3c8be4addb69713fmgraczyk@chromium.org    if (item->is_component_enabled()) {
11977bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org      enabled_count++;
11987bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    }
11997bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  }
120070f9903e570931831a027ba6f91c164efc604a85solenberg  if (public_submodules_->high_pass_filter->is_enabled()) {
120170f9903e570931831a027ba6f91c164efc604a85solenberg    enabled_count++;
120270f9903e570931831a027ba6f91c164efc604a85solenberg  }
12035e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  if (public_submodules_->noise_suppression->is_enabled()) {
12045e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg    enabled_count++;
12055e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg  }
1206949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  if (public_submodules_->level_estimator->is_enabled()) {
1207949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg    enabled_count++;
1208949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  }
1209a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  if (public_submodules_->voice_detection->is_enabled()) {
1210a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg    enabled_count++;
1211a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  }
12127bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
1213df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Data is unchanged if no components are enabled, or if only
1214df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // public_submodules_->level_estimator
1215df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // or public_submodules_->voice_detection is enabled.
12167bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  if (enabled_count == 0) {
12177bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    return false;
12187bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  } else if (enabled_count == 1) {
1219df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (public_submodules_->level_estimator->is_enabled() ||
1220df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->voice_detection->is_enabled()) {
12217bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org      return false;
12227bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    }
12237bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  } else if (enabled_count == 2) {
1224df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (public_submodules_->level_estimator->is_enabled() &&
1225df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        public_submodules_->voice_detection->is_enabled()) {
12267bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org      return false;
12277bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    }
12287bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  }
12297bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  return true;
12307bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org}
12317bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
123217e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.orgbool AudioProcessingImpl::output_copy_needed(bool is_data_processed) const {
1233369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org  // Check if we've upmixed or downmixed the audio.
1234df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return ((formats_.api_format.output_stream().num_channels() !=
1235df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah           formats_.api_format.input_stream().num_channels()) ||
1236df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          is_data_processed || capture_.transient_suppressor_enabled);
12377bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org}
12387bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
1239369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.orgbool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
124086c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk  return (is_data_processed &&
1241df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          (capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
1242df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah               kSampleRate32kHz ||
1243df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah           capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
1244df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah               kSampleRate48kHz));
1245369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org}
1246369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.org
1247369166a179a201494beeff4ec060c6dff8b27affandrew@webrtc.orgbool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
1248df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (!is_data_processed &&
1249df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      !public_submodules_->voice_detection->is_enabled() &&
1250df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      !capture_.transient_suppressor_enabled) {
1251df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Only public_submodules_->level_estimator is enabled.
12527bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    return false;
1253df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  } else if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
1254df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                 kSampleRate32kHz ||
1255df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah             capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
1256df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                 kSampleRate48kHz) {
1257df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Something besides public_submodules_->level_estimator is enabled, and we
1258df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // have super-wb.
12597bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org    return true;
12607bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  }
12617bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org  return false;
12627bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org}
12637bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org
126460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonbool AudioProcessingImpl::is_rev_processed() const {
1265df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return constants_.intelligibility_enabled &&
1266df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah         public_submodules_->intelligibility_enhancer->active();
126760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}
126860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
126981b9bfe6856bb4f9fd0ba79899f72b8385c58979peahbool AudioProcessingImpl::render_check_rev_conversion_needed() const {
127081b9bfe6856bb4f9fd0ba79899f72b8385c58979peah  return rev_conversion_needed();
127181b9bfe6856bb4f9fd0ba79899f72b8385c58979peah}
127281b9bfe6856bb4f9fd0ba79899f72b8385c58979peah
127360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonbool AudioProcessingImpl::rev_conversion_needed() const {
1274df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  return (formats_.api_format.reverse_input_stream() !=
1275df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          formats_.api_format.reverse_output_stream());
127660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}
127760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
1278adc46c4cf7dd8a015b0757c99787d80525c123abBjorn Volckervoid AudioProcessingImpl::InitializeExperimentalAgc() {
1279df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.use_new_agc) {
1280df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!private_submodules_->agc_manager.get()) {
1281df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      private_submodules_->agc_manager.reset(new AgcManagerDirect(
1282df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          public_submodules_->gain_control,
1283df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          public_submodules_->gain_control_for_new_agc.get(),
1284df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah          constants_.agc_startup_min_volume));
1285788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    }
1286df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->agc_manager->Initialize();
1287df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->agc_manager->SetCaptureMuted(
1288df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.output_will_be_muted);
1289788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
1290788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org}
1291788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
1292adc46c4cf7dd8a015b0757c99787d80525c123abBjorn Volckervoid AudioProcessingImpl::InitializeTransient() {
1293df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_.transient_suppressor_enabled) {
1294df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!public_submodules_->transient_suppressor.get()) {
1295df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->transient_suppressor.reset(new TransientSuppressor());
1296788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org    }
1297df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->transient_suppressor->Initialize(
1298df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.fwd_proc_format.sample_rate_hz(),
1299df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.split_rate,
1300b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs        num_proc_channels());
1301788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org  }
1302788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org}
1303788acd17adf6b3d605b5ea66cf394eb81fc086a9pbos@webrtc.org
1304ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.orgvoid AudioProcessingImpl::InitializeBeamformer() {
1305b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  if (capture_nonlocked_.beamformer_enabled) {
1306df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!private_submodules_->beamformer) {
1307df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      private_submodules_->beamformer.reset(new NonlinearBeamformer(
13082a34688f86517bfd3745e131e4e5d2b7a924f46aaluebs          capture_.array_geometry, capture_.target_direction));
1309d82f55d2a73da925d4160e3d1430f79f76170992aluebs@webrtc.org    }
1310df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    private_submodules_->beamformer->Initialize(kChunkSizeMs,
1311df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                                capture_nonlocked_.split_rate);
1312ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org  }
1313ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org}
1314ae643ce280876d3b1ebcf0cc628f27ba7116b534aluebs@webrtc.org
131560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonvoid AudioProcessingImpl::InitializeIntelligibility() {
1316df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (constants_.intelligibility_enabled) {
131760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson    IntelligibilityEnhancer::Config config;
1318df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    config.sample_rate_hz = capture_nonlocked_.split_rate;
1319df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    config.num_capture_channels = capture_.capture_audio->num_channels();
1320df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    config.num_render_channels = render_.render_audio->num_channels();
1321df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    public_submodules_->intelligibility_enhancer.reset(
1322df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        new IntelligibilityEnhancer(config));
132360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  }
132460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}
132560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson
132670f9903e570931831a027ba6f91c164efc604a85solenbergvoid AudioProcessingImpl::InitializeHighPassFilter() {
1327b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  public_submodules_->high_pass_filter->Initialize(num_proc_channels(),
132870f9903e570931831a027ba6f91c164efc604a85solenberg                                                   proc_sample_rate_hz());
13295e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg}
13305e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg
13315e465c33cac54ed5265f18413f7afc44aae2dfcasolenbergvoid AudioProcessingImpl::InitializeNoiseSuppression() {
1332b2328d11dcc86fba1661ee3fa0d51fc126939764aluebs  public_submodules_->noise_suppression->Initialize(num_proc_channels(),
13335e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg                                                    proc_sample_rate_hz());
133470f9903e570931831a027ba6f91c164efc604a85solenberg}
133570f9903e570931831a027ba6f91c164efc604a85solenberg
1336949028fbf1e9a01fb96b186b95606c0096e7d13fsolenbergvoid AudioProcessingImpl::InitializeLevelEstimator() {
1337949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg  public_submodules_->level_estimator->Initialize();
1338949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg}
1339949028fbf1e9a01fb96b186b95606c0096e7d13fsolenberg
1340a29386c26d515be9fbeaeca3e0bc6019f29142c2solenbergvoid AudioProcessingImpl::InitializeVoiceDetection() {
1341a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg  public_submodules_->voice_detection->Initialize(proc_split_sample_rate_hz());
1342a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg}
1343a29386c26d515be9fbeaeca3e0bc6019f29142c2solenberg
13441ca324f23770e17d19433ccd3a3b021870d709caBjorn Volckervoid AudioProcessingImpl::MaybeUpdateHistograms() {
1345d92f2674d7e99ae69b26d434b47ea0adf14aff0cBjorn Volcker  static const int kMinDiffDelayMs = 60;
13461ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker
13471ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker  if (echo_cancellation()->is_enabled()) {
13484e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker    // Activate delay_jumps_ counters if we know echo_cancellation is runnning.
13494e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker    // If a stream has echo we know that the echo_cancellation is in process.
1350df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (capture_.stream_delay_jumps == -1 &&
1351df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        echo_cancellation()->stream_has_echo()) {
1352df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_.stream_delay_jumps = 0;
13534e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker    }
1354df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (capture_.aec_system_delay_jumps == -1 &&
13554e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker        echo_cancellation()->stream_has_echo()) {
1356df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_.aec_system_delay_jumps = 0;
13574e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker    }
13584e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker
13591ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    // Detect a jump in platform reported system delay and log the difference.
1360df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    const int diff_stream_delay_ms =
1361df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_nonlocked_.stream_delay_ms - capture_.last_stream_delay_ms;
1362df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (diff_stream_delay_ms > kMinDiffDelayMs &&
1363df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.last_stream_delay_ms != 0) {
136453805324c0fa904d796cc0b333868c591f2c5f2casapersson      RTC_HISTOGRAM_COUNTS_SPARSE(
136553805324c0fa904d796cc0b333868c591f2c5f2casapersson          "WebRTC.Audio.PlatformReportedStreamDelayJump", diff_stream_delay_ms,
136653805324c0fa904d796cc0b333868c591f2c5f2casapersson          kMinDiffDelayMs, 1000, 100);
1367df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      if (capture_.stream_delay_jumps == -1) {
1368df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.stream_delay_jumps = 0;  // Activate counter if needed.
13694e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker      }
1370df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_.stream_delay_jumps++;
13711ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    }
1372df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    capture_.last_stream_delay_ms = capture_nonlocked_.stream_delay_ms;
13731ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker
13741ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    // Detect a jump in AEC system delay and log the difference.
1375df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    const int frames_per_ms =
1376df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        rtc::CheckedDivExact(capture_nonlocked_.split_rate, 1000);
13771ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    const int aec_system_delay_ms =
13781ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker        WebRtcAec_system_delay(echo_cancellation()->aec_core()) / frames_per_ms;
137986c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk    const int diff_aec_system_delay_ms =
1380df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        aec_system_delay_ms - capture_.last_aec_system_delay_ms;
13811ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    if (diff_aec_system_delay_ms > kMinDiffDelayMs &&
1382df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.last_aec_system_delay_ms != 0) {
138353805324c0fa904d796cc0b333868c591f2c5f2casapersson      RTC_HISTOGRAM_COUNTS_SPARSE("WebRTC.Audio.AecSystemDelayJump",
138453805324c0fa904d796cc0b333868c591f2c5f2casapersson                                  diff_aec_system_delay_ms, kMinDiffDelayMs,
138553805324c0fa904d796cc0b333868c591f2c5f2casapersson                                  1000, 100);
1386df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      if (capture_.aec_system_delay_jumps == -1) {
1387df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.aec_system_delay_jumps = 0;  // Activate counter if needed.
13884e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker      }
1389df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_.aec_system_delay_jumps++;
13901ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker    }
1391df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    capture_.last_aec_system_delay_ms = aec_system_delay_ms;
13921ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker  }
13931ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker}
13941ca324f23770e17d19433ccd3a3b021870d709caBjorn Volcker
13954e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volckervoid AudioProcessingImpl::UpdateHistogramsOnCallEnd() {
1396df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // Run in a single-threaded manner.
1397df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_render(&crit_render_);
1398df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  rtc::CritScope cs_capture(&crit_capture_);
1399df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
1400df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_.stream_delay_jumps > -1) {
140153805324c0fa904d796cc0b333868c591f2c5f2casapersson    RTC_HISTOGRAM_ENUMERATION_SPARSE(
14024e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker        "WebRTC.Audio.NumOfPlatformReportedStreamDelayJumps",
1403df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah        capture_.stream_delay_jumps, 51);
14044e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker  }
1405df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.stream_delay_jumps = -1;
1406df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.last_stream_delay_ms = 0;
14074e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker
1408df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (capture_.aec_system_delay_jumps > -1) {
140953805324c0fa904d796cc0b333868c591f2c5f2casapersson    RTC_HISTOGRAM_ENUMERATION_SPARSE("WebRTC.Audio.NumOfAecSystemDelayJumps",
141053805324c0fa904d796cc0b333868c591f2c5f2casapersson                                     capture_.aec_system_delay_jumps, 51);
14114e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker  }
1412df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.aec_system_delay_jumps = -1;
1413df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  capture_.last_aec_system_delay_ms = 0;
14144e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker}
14154e7aa43ea0fd7106cd39036798877301398966a6Bjorn Volcker
14167bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1417df3efa8c079294857a8b8e0a02634d06a6d6b6d6peahint AudioProcessingImpl::WriteMessageToDebugFile(
1418df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    FileWrapper* debug_file,
1419df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    rtc::CriticalSection* crit_debug,
1420df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    ApmDebugDumpThreadState* debug_state) {
1421df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  int32_t size = debug_state->event_msg->ByteSize();
1422808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  if (size <= 0) {
1423808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com    return kUnspecifiedError;
1424808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
1425621df678c8690f36875b0b34d45393df58662172andrew@webrtc.org#if defined(WEBRTC_ARCH_BIG_ENDIAN)
142686c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk// TODO(ajm): Use little-endian "on the wire". For the moment, we can be
142786c6d33aec684d08189d498912e47cbc17c4d2dbMichael Graczyk//            pretty safe in assuming little-endian.
1428808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com#endif
1429808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1430df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (!debug_state->event_msg->SerializeToString(&debug_state->event_str)) {
1431808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com    return kUnspecifiedError;
1432808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
1433808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1434df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  {
1435df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Ensure atomic writes of the message.
1436a4df27b6713583045e51e20c4eb93718d15ca33eivoc    rtc::CritScope cs_capture(crit_debug);
1437df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    // Write message preceded by its size.
1438df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!debug_file->Write(&size, sizeof(int32_t))) {
1439df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      return kFileError;
1440df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    }
1441df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    if (!debug_file->Write(debug_state->event_str.data(),
1442df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                           debug_state->event_str.length())) {
1443df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      return kFileError;
1444df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah    }
1445808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
1446808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1447df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  debug_state->event_msg->Clear();
1448808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
144917e40641b30559602e26382e500bd9708bad37e3andrew@webrtc.org  return kNoError;
1450808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com}
1451808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1452808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.comint AudioProcessingImpl::WriteInitMessage() {
1453df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  debug_dump_.capture.event_msg->set_type(audioproc::Event::INIT);
1454df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  audioproc::Init* msg = debug_dump_.capture.event_msg->mutable_init();
1455df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  msg->set_sample_rate(formats_.api_format.input_stream().sample_rate_hz());
1456df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah
14576955870806624479723addfae6dcf5d13968796cPeter Kasting  msg->set_num_input_channels(static_cast<google::protobuf::int32>(
14586955870806624479723addfae6dcf5d13968796cPeter Kasting      formats_.api_format.input_stream().num_channels()));
14596955870806624479723addfae6dcf5d13968796cPeter Kasting  msg->set_num_output_channels(static_cast<google::protobuf::int32>(
14606955870806624479723addfae6dcf5d13968796cPeter Kasting      formats_.api_format.output_stream().num_channels()));
14616955870806624479723addfae6dcf5d13968796cPeter Kasting  msg->set_num_reverse_channels(static_cast<google::protobuf::int32>(
14626955870806624479723addfae6dcf5d13968796cPeter Kasting      formats_.api_format.reverse_input_stream().num_channels()));
146360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson  msg->set_reverse_sample_rate(
1464df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.reverse_input_stream().sample_rate_hz());
1465192164eebc9bbb5c5745f19330b203174304e269peah  msg->set_output_sample_rate(
1466df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      formats_.api_format.output_stream().sample_rate_hz());
1467df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // TODO(ekmeyerson): Add reverse output fields to
1468df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  // debug_dump_.capture.event_msg.
1469808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1470df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
1471df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                        &crit_debug_, &debug_dump_.capture));
147213b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  return kNoError;
147313b96ba90f72164134019cbfc07d4a47cf1fd091Minyue}
147413b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
147513b96ba90f72164134019cbfc07d4a47cf1fd091Minyueint AudioProcessingImpl::WriteConfigMessage(bool forced) {
147613b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  audioproc::Config config;
147713b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1478df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_aec_enabled(public_submodules_->echo_cancellation->is_enabled());
147913b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  config.set_aec_delay_agnostic_enabled(
1480df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_cancellation->is_delay_agnostic_enabled());
148113b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  config.set_aec_drift_compensation_enabled(
1482df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_cancellation->is_drift_compensation_enabled());
148313b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  config.set_aec_extended_filter_enabled(
1484df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_cancellation->is_extended_filter_enabled());
1485df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_aec_suppression_level(static_cast<int>(
1486df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_cancellation->suppression_level()));
148713b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1488df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_aecm_enabled(
1489df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_control_mobile->is_enabled());
149013b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  config.set_aecm_comfort_noise_enabled(
1491df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_control_mobile->is_comfort_noise_enabled());
1492df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_aecm_routing_mode(static_cast<int>(
1493df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->echo_control_mobile->routing_mode()));
149413b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1495df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_agc_enabled(public_submodules_->gain_control->is_enabled());
1496df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_agc_mode(
1497df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      static_cast<int>(public_submodules_->gain_control->mode()));
1498df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_agc_limiter_enabled(
1499df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      public_submodules_->gain_control->is_limiter_enabled());
1500df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_noise_robust_agc_enabled(constants_.use_new_agc);
150113b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1502df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_hpf_enabled(public_submodules_->high_pass_filter->is_enabled());
150313b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1504df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_ns_enabled(public_submodules_->noise_suppression->is_enabled());
1505df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_ns_level(
1506df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      static_cast<int>(public_submodules_->noise_suppression->level()));
150713b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1508df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  config.set_transient_suppression_enabled(
1509df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      capture_.transient_suppressor_enabled);
151013b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
151113b96ba90f72164134019cbfc07d4a47cf1fd091Minyue  std::string serialized_config = config.SerializeAsString();
1512df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  if (!forced &&
1513df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah      debug_dump_.capture.last_serialized_config == serialized_config) {
151413b96ba90f72164134019cbfc07d4a47cf1fd091Minyue    return kNoError;
1515808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  }
1516808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com
1517df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  debug_dump_.capture.last_serialized_config = serialized_config;
151813b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1519df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  debug_dump_.capture.event_msg->set_type(audioproc::Event::CONFIG);
1520df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  debug_dump_.capture.event_msg->mutable_config()->CopyFrom(config);
152113b96ba90f72164134019cbfc07d4a47cf1fd091Minyue
1522df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah  RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
1523df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah                                        &crit_debug_, &debug_dump_.capture));
1524808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com  return kNoError;
1525808e0e0dac055f8b87ad6878f046e35b4b2c1c27ajm@google.com}
15267bf2646e4dc82e0a46bbde40b82c047acd70e0f1andrew@webrtc.org#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1527ddbb8a2c243f9d54cb0ce0092e341dfc6e126bb3andrew@webrtc.org
1528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}  // namespace webrtc
1529