summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/modules/audio_processing/aec3/aec_state.h
blob: 358c74d8e0b3e6f4522b02eea57132304af36990 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_
#define MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_

#include <algorithm>
#include <memory>
#include <vector>

#include "api/array_view.h"
#include "api/optional.h"
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/echo_path_variability.h"
#include "modules/audio_processing/aec3/erl_estimator.h"
#include "modules/audio_processing/aec3/erle_estimator.h"
#include "modules/audio_processing/aec3/render_buffer.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/constructormagic.h"

namespace webrtc {

class ApmDataDumper;

// Handles the state and the conditions for the echo removal functionality.
class AecState {
 public:
  explicit AecState(const AudioProcessing::Config::EchoCanceller3& config);
  ~AecState();

  // Returns whether the linear filter estimate is usable.
  bool UsableLinearEstimate() const { return usable_linear_estimate_; }

  // Returns whether there has been echo leakage detected.
  bool EchoLeakageDetected() const { return echo_leakage_detected_; }

  // Returns whether the render signal is currently active.
  // TODO(peah): Deprecate this in an upcoming CL.
  bool ActiveRender() const { return blocks_with_filter_adaptation_ > 200; }

  // Returns the ERLE.
  const std::array<float, kFftLengthBy2Plus1>& Erle() const {
    return erle_estimator_.Erle();
  }

  // Returns the ERL.
  const std::array<float, kFftLengthBy2Plus1>& Erl() const {
    return erl_estimator_.Erl();
  }

  // Returns the delay estimate based on the linear filter.
  rtc::Optional<size_t> FilterDelay() const { return filter_delay_; }

  // Returns the externally provided delay.
  rtc::Optional<size_t> ExternalDelay() const { return external_delay_; }

  // Returns whether the capture signal is saturated.
  bool SaturatedCapture() const { return capture_signal_saturation_; }

  // Returns whether the echo signal is saturated.
  bool SaturatedEcho() const { return echo_saturation_; }

  // Updates the capture signal saturation.
  void UpdateCaptureSaturation(bool capture_signal_saturation) {
    capture_signal_saturation_ = capture_signal_saturation;
  }

  // Returns whether the transparent mode is active
  bool TransparentMode() const { return transparent_mode_; }

  // Takes appropriate action at an echo path change.
  void HandleEchoPathChange(const EchoPathVariability& echo_path_variability);

  // Returns the decay factor for the echo reverberation.
  float ReverbDecay() const { return reverb_decay_; }

  // Returns whether the echo suppression gain should be forced to zero.
  bool ForcedZeroGain() const { return force_zero_gain_; }

  // Returns whether the echo in the capture signal is audible.
  bool InaudibleEcho() const { return echo_audibility_.InaudibleEcho(); }

  // Updates the aec state with the AEC output signal.
  void UpdateWithOutput(rtc::ArrayView<const float> e) {
    echo_audibility_.UpdateWithOutput(e);
  }

  // Returns whether the linear filter should have been able to adapt properly.
  bool SufficientFilterUpdates() const {
    return blocks_with_filter_adaptation_ >= kEchoPathChangeConvergenceBlocks;
  }

  // Returns whether the echo subtractor can be used to determine the residual
  // echo.
  bool LinearEchoEstimate() const {
    return UsableLinearEstimate() && !TransparentMode();
  }

  // Returns whether the AEC is in an initial state.
  bool InitialState() const {
    return capture_block_counter_ < 3 * kNumBlocksPerSecond;
  }

  // Updates the aec state.
  void Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
                  adaptive_filter_frequency_response,
              const std::array<float, kAdaptiveFilterTimeDomainLength>&
                  adaptive_filter_impulse_response,
              bool converged_filter,
              const rtc::Optional<size_t>& external_delay_samples,
              const RenderBuffer& render_buffer,
              const std::array<float, kFftLengthBy2Plus1>& E2_main,
              const std::array<float, kFftLengthBy2Plus1>& Y2,
              rtc::ArrayView<const float> x,
              const std::array<float, kBlockSize>& s_main,
              bool echo_leakage_detected);

 private:
  class EchoAudibility {
   public:
    void Update(rtc::ArrayView<const float> x,
                const std::array<float, kBlockSize>& s,
                bool converged_filter);
    void UpdateWithOutput(rtc::ArrayView<const float> e);
    bool InaudibleEcho() const { return inaudible_echo_; }

   private:
    float max_nearend_ = 0.f;
    size_t max_nearend_counter_ = 0;
    size_t low_farend_counter_ = 0;
    bool inaudible_echo_ = false;
  };

  void UpdateReverb(const std::array<float, kAdaptiveFilterTimeDomainLength>&
                        impulse_response);

  static int instance_count_;
  std::unique_ptr<ApmDataDumper> data_dumper_;
  ErlEstimator erl_estimator_;
  ErleEstimator erle_estimator_;
  size_t capture_block_counter_ = 0;
  size_t blocks_with_filter_adaptation_ = 0;
  bool usable_linear_estimate_ = false;
  bool echo_leakage_detected_ = false;
  bool capture_signal_saturation_ = false;
  bool echo_saturation_ = false;
  bool transparent_mode_ = false;
  float previous_max_sample_ = 0.f;
  bool force_zero_gain_ = false;
  bool render_received_ = false;
  size_t force_zero_gain_counter_ = 0;
  rtc::Optional<size_t> filter_delay_;
  rtc::Optional<size_t> external_delay_;
  size_t blocks_since_last_saturation_ = 1000;
  float reverb_decay_to_test_ = 0.9f;
  float reverb_decay_candidate_ = 0.f;
  float reverb_decay_candidate_residual_ = -1.f;
  EchoAudibility echo_audibility_;
  const AudioProcessing::Config::EchoCanceller3 config_;
  float reverb_decay_;

  RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
};

}  // namespace webrtc

#endif  // MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_