tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

aec_state.h (11537B)


      1 /*
      2 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #ifndef MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_
     12 #define MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_
     13 
     14 #include <stddef.h>
     15 
     16 #include <array>
     17 #include <atomic>
     18 #include <memory>
     19 #include <optional>
     20 #include <vector>
     21 
     22 #include "api/array_view.h"
     23 #include "api/audio/echo_canceller3_config.h"
     24 #include "api/environment/environment.h"
     25 #include "modules/audio_processing/aec3/aec3_common.h"
     26 #include "modules/audio_processing/aec3/block.h"
     27 #include "modules/audio_processing/aec3/delay_estimate.h"
     28 #include "modules/audio_processing/aec3/echo_audibility.h"
     29 #include "modules/audio_processing/aec3/echo_path_variability.h"
     30 #include "modules/audio_processing/aec3/erl_estimator.h"
     31 #include "modules/audio_processing/aec3/erle_estimator.h"
     32 #include "modules/audio_processing/aec3/filter_analyzer.h"
     33 #include "modules/audio_processing/aec3/render_buffer.h"
     34 #include "modules/audio_processing/aec3/reverb_model.h"
     35 #include "modules/audio_processing/aec3/reverb_model_estimator.h"
     36 #include "modules/audio_processing/aec3/subtractor_output.h"
     37 #include "modules/audio_processing/aec3/subtractor_output_analyzer.h"
     38 #include "modules/audio_processing/aec3/transparent_mode.h"
     39 
     40 namespace webrtc {
     41 
     42 class ApmDataDumper;
     43 
     44 // Handles the state and the conditions for the echo removal functionality.
     45 class AecState {
     46 public:
     47  AecState(const Environment& env,
     48           const EchoCanceller3Config& config,
     49           size_t num_capture_channels);
     50  ~AecState();
     51 
     52  // Returns whether the echo subtractor can be used to determine the residual
     53  // echo.
     54  bool UsableLinearEstimate() const {
     55    return filter_quality_state_.LinearFilterUsable() &&
     56           config_.filter.use_linear_filter;
     57  }
     58 
     59  // Returns whether the echo subtractor output should be used as output.
     60  bool UseLinearFilterOutput() const {
     61    return filter_quality_state_.LinearFilterUsable() &&
     62           config_.filter.use_linear_filter;
     63  }
     64 
     65  // Returns whether the render signal is currently active.
     66  bool ActiveRender() const { return blocks_with_active_render_ > 200; }
     67 
     68  // Returns the appropriate scaling of the residual echo to match the
     69  // audibility.
     70  void GetResidualEchoScaling(ArrayView<float> residual_scaling) const;
     71 
     72  // Returns whether the stationary properties of the signals are used in the
     73  // aec.
     74  bool UseStationarityProperties() const {
     75    return config_.echo_audibility.use_stationarity_properties;
     76  }
     77 
     78  // Returns the ERLE.
     79  ArrayView<const std::array<float, kFftLengthBy2Plus1>> Erle(
     80      bool onset_compensated) const {
     81    return erle_estimator_.Erle(onset_compensated);
     82  }
     83 
     84  // Returns the non-capped ERLE.
     85  ArrayView<const std::array<float, kFftLengthBy2Plus1>> ErleUnbounded() const {
     86    return erle_estimator_.ErleUnbounded();
     87  }
     88 
     89  // Returns the fullband ERLE estimate in log2 units.
     90  float FullBandErleLog2() const { return erle_estimator_.FullbandErleLog2(); }
     91 
     92  // Returns the ERL.
     93  const std::array<float, kFftLengthBy2Plus1>& Erl() const {
     94    return erl_estimator_.Erl();
     95  }
     96 
     97  // Returns the time-domain ERL.
     98  float ErlTimeDomain() const { return erl_estimator_.ErlTimeDomain(); }
     99 
    100  // Returns the delay estimate based on the linear filter.
    101  int MinDirectPathFilterDelay() const {
    102    return delay_state_.MinDirectPathFilterDelay();
    103  }
    104 
    105  // Returns whether the capture signal is saturated.
    106  bool SaturatedCapture() const { return capture_signal_saturation_; }
    107 
    108  // Returns whether the echo signal is saturated.
    109  bool SaturatedEcho() const { return saturation_detector_.SaturatedEcho(); }
    110 
    111  // Updates the capture signal saturation.
    112  void UpdateCaptureSaturation(bool capture_signal_saturation) {
    113    capture_signal_saturation_ = capture_signal_saturation;
    114  }
    115 
    116  // Returns whether the transparent mode is active
    117  bool TransparentModeActive() const {
    118    return transparent_state_ && transparent_state_->Active();
    119  }
    120 
    121  // Takes appropriate action at an echo path change.
    122  void HandleEchoPathChange(const EchoPathVariability& echo_path_variability);
    123 
    124  // Returns the decay factor for the echo reverberation. The parameter `mild`
    125  // indicates which exponential decay to return. The default one or a milder
    126  // one that can be used during nearend regions.
    127  float ReverbDecay(bool mild) const {
    128    return reverb_model_estimator_.ReverbDecay(mild);
    129  }
    130 
    131  // Return the frequency response of the reverberant echo.
    132  ArrayView<const float> GetReverbFrequencyResponse() const {
    133    return reverb_model_estimator_.GetReverbFrequencyResponse();
    134  }
    135 
    136  // Returns whether the transition for going out of the initial stated has
    137  // been triggered.
    138  bool TransitionTriggered() const {
    139    return initial_state_.TransitionTriggered();
    140  }
    141 
    142  // Updates the aec state.
    143  // TODO(bugs.webrtc.org/10913): Compute multi-channel ERL.
    144  void Update(
    145      const std::optional<DelayEstimate>& external_delay,
    146      ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
    147          adaptive_filter_frequency_responses,
    148      ArrayView<const std::vector<float>> adaptive_filter_impulse_responses,
    149      const RenderBuffer& render_buffer,
    150      ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2_refined,
    151      ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
    152      ArrayView<const SubtractorOutput> subtractor_output);
    153 
    154  // Returns filter length in blocks.
    155  int FilterLengthBlocks() const {
    156    // All filters have the same length, so arbitrarily return channel 0 length.
    157    return filter_analyzer_.FilterLengthBlocks();
    158  }
    159 
    160  std::optional<DelayEstimate> ExternalDelayBlocks() const {
    161    return delay_state_.ExternalDelayBlocks();
    162  }
    163 
    164 private:
    165  static std::atomic<int> instance_count_;
    166  std::unique_ptr<ApmDataDumper> data_dumper_;
    167  const EchoCanceller3Config config_;
    168  const size_t num_capture_channels_;
    169  const bool deactivate_initial_state_reset_at_echo_path_change_;
    170  const bool full_reset_at_echo_path_change_;
    171  const bool subtractor_analyzer_reset_at_echo_path_change_;
    172 
    173  // Class for controlling the transition from the intial state, which in turn
    174  // controls when the filter parameters for the initial state should be used.
    175  class InitialState {
    176   public:
    177    explicit InitialState(const EchoCanceller3Config& config);
    178    // Resets the state to again begin in the initial state.
    179    void Reset();
    180 
    181    // Updates the state based on new data.
    182    void Update(bool active_render, bool saturated_capture);
    183 
    184    // Returns whether the initial state is active or not.
    185    bool InitialStateActive() const { return initial_state_; }
    186 
    187    // Returns that the transition from the initial state has was started.
    188    bool TransitionTriggered() const { return transition_triggered_; }
    189 
    190   private:
    191    const bool conservative_initial_phase_;
    192    const float initial_state_seconds_;
    193    bool transition_triggered_ = false;
    194    bool initial_state_ = true;
    195    size_t strong_not_saturated_render_blocks_ = 0;
    196  } initial_state_;
    197 
    198  // Class for choosing the direct-path delay relative to the beginning of the
    199  // filter, as well as any other data related to the delay used within
    200  // AecState.
    201  class FilterDelay {
    202   public:
    203    FilterDelay(const EchoCanceller3Config& config,
    204                size_t num_capture_channels);
    205 
    206    // Returns whether an external delay has been reported to the AecState (from
    207    // the delay estimator).
    208    bool ExternalDelayReported() const { return external_delay_.has_value(); }
    209 
    210    // Returns the external delay reported to the AecState (from the delay
    211    // estimator).
    212    std::optional<DelayEstimate> ExternalDelayBlocks() const {
    213      return external_delay_;
    214    }
    215 
    216    // Returns the delay in blocks relative to the beginning of the filter that
    217    // corresponds to the direct path of the echo.
    218    ArrayView<const int> DirectPathFilterDelays() const {
    219      return filter_delays_blocks_;
    220    }
    221 
    222    // Returns the minimum delay among the direct path delays relative to the
    223    // beginning of the filter
    224    int MinDirectPathFilterDelay() const { return min_filter_delay_; }
    225 
    226    // Updates the delay estimates based on new data.
    227    void Update(ArrayView<const int> analyzer_filter_delay_estimates_blocks,
    228                const std::optional<DelayEstimate>& external_delay,
    229                size_t blocks_with_proper_filter_adaptation);
    230 
    231   private:
    232    const int delay_headroom_blocks_;
    233    std::vector<int> filter_delays_blocks_;
    234    int min_filter_delay_;
    235    std::optional<DelayEstimate> external_delay_;
    236  } delay_state_;
    237 
    238  // Classifier for toggling transparent mode when there is no echo.
    239  std::unique_ptr<TransparentMode> transparent_state_;
    240 
    241  // Class for analyzing how well the linear filter is, and can be expected to,
    242  // perform on the current signals. The purpose of this is for using to
    243  // select the echo suppression functionality as well as the input to the echo
    244  // suppressor.
    245  class FilteringQualityAnalyzer {
    246   public:
    247    FilteringQualityAnalyzer(const EchoCanceller3Config& config,
    248                             size_t num_capture_channels);
    249 
    250    // Returns whether the linear filter can be used for the echo
    251    // canceller output.
    252    bool LinearFilterUsable() const { return overall_usable_linear_estimates_; }
    253 
    254    // Returns whether an individual filter output can be used for the echo
    255    // canceller output.
    256    const std::vector<bool>& UsableLinearFilterOutputs() const {
    257      return usable_linear_filter_estimates_;
    258    }
    259 
    260    // Resets the state of the analyzer.
    261    void Reset();
    262 
    263    // Updates the analysis based on new data.
    264    void Update(bool active_render,
    265                bool transparent_mode,
    266                bool saturated_capture,
    267                const std::optional<DelayEstimate>& external_delay,
    268                bool any_filter_converged);
    269 
    270   private:
    271    const bool use_linear_filter_;
    272    bool overall_usable_linear_estimates_ = false;
    273    size_t filter_update_blocks_since_reset_ = 0;
    274    size_t filter_update_blocks_since_start_ = 0;
    275    bool convergence_seen_ = false;
    276    std::vector<bool> usable_linear_filter_estimates_;
    277  } filter_quality_state_;
    278 
    279  // Class for detecting whether the echo is to be considered to be
    280  // saturated.
    281  class SaturationDetector {
    282   public:
    283    // Returns whether the echo is to be considered saturated.
    284    bool SaturatedEcho() const { return saturated_echo_; }
    285 
    286    // Updates the detection decision based on new data.
    287    void Update(const Block& x,
    288                bool saturated_capture,
    289                bool usable_linear_estimate,
    290                ArrayView<const SubtractorOutput> subtractor_output,
    291                float echo_path_gain);
    292 
    293   private:
    294    bool saturated_echo_ = false;
    295  } saturation_detector_;
    296 
    297  ErlEstimator erl_estimator_;
    298  ErleEstimator erle_estimator_;
    299  size_t strong_not_saturated_render_blocks_ = 0;
    300  size_t blocks_with_active_render_ = 0;
    301  bool capture_signal_saturation_ = false;
    302  FilterAnalyzer filter_analyzer_;
    303  EchoAudibility echo_audibility_;
    304  ReverbModelEstimator reverb_model_estimator_;
    305  ReverbModel avg_render_reverb_;
    306  SubtractorOutputAnalyzer subtractor_output_analyzer_;
    307 };
    308 
    309 }  // namespace webrtc
    310 
    311 #endif  // MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_