1 /*
2  *  Copyright (c) 2018 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_REVERB_DECAY_ESTIMATOR_H_
12 #define MODULES_AUDIO_PROCESSING_AEC3_REVERB_DECAY_ESTIMATOR_H_
13 
14 #include <array>
15 #include <vector>
16 
17 #include "absl/types/optional.h"
18 #include "api/array_view.h"
19 #include "modules/audio_processing/aec3/aec3_common.h"  // kMaxAdaptiveFilter...
20 
21 namespace webrtc {
22 
23 class ApmDataDumper;
24 struct EchoCanceller3Config;
25 
26 // Class for estimating the decay of the late reverb.
27 class ReverbDecayEstimator {
28  public:
29   explicit ReverbDecayEstimator(const EchoCanceller3Config& config);
30   ~ReverbDecayEstimator();
31   // Updates the decay estimate.
32   void Update(rtc::ArrayView<const float> filter,
33               const absl::optional<float>& filter_quality,
34               int filter_delay_blocks,
35               bool usable_linear_filter,
36               bool stationary_signal);
37   // Returns the decay for the exponential model.
Decay()38   float Decay() const { return decay_; }
39   // Dumps debug data.
40   void Dump(ApmDataDumper* data_dumper) const;
41 
42  private:
43   void EstimateDecay(rtc::ArrayView<const float> filter, int peak_block);
44   void AnalyzeFilter(rtc::ArrayView<const float> filter);
45 
46   void ResetDecayEstimation();
47 
48   // Class for estimating the decay of the late reverb from the linear filter.
49   class LateReverbLinearRegressor {
50    public:
51     // Resets the estimator to receive a specified number of data points.
52     void Reset(int num_data_points);
53     // Accumulates estimation data.
54     void Accumulate(float z);
55     // Estimates the decay.
56     float Estimate();
57     // Returns whether an estimate is available.
EstimateAvailable()58     bool EstimateAvailable() const { return n_ == N_ && N_ != 0; }
59 
60    public:
61     float nz_ = 0.f;
62     float nn_ = 0.f;
63     float count_ = 0.f;
64     int N_ = 0;
65     int n_ = 0;
66   };
67 
68   // Class for identifying the length of the early reverb from the linear
69   // filter. For identifying the early reverberations, the impulse response is
70   // divided in sections and the tilt of each section is computed by a linear
71   // regressor.
72   class EarlyReverbLengthEstimator {
73    public:
74     explicit EarlyReverbLengthEstimator(int max_blocks);
75     ~EarlyReverbLengthEstimator();
76 
77     // Resets the estimator.
78     void Reset();
79     // Accumulates estimation data.
80     void Accumulate(float value, float smoothing);
81     // Estimates the size in blocks of the early reverb.
82     int Estimate();
83     // Dumps debug data.
84     void Dump(ApmDataDumper* data_dumper) const;
85 
86    private:
87     std::vector<float> numerators_smooth_;
88     std::vector<float> numerators_;
89     int coefficients_counter_;
90     int block_counter_ = 0;
91     int n_sections_ = 0;
92   };
93 
94   const int filter_length_blocks_;
95   const int filter_length_coefficients_;
96   const bool use_adaptive_echo_decay_;
97   LateReverbLinearRegressor late_reverb_decay_estimator_;
98   EarlyReverbLengthEstimator early_reverb_estimator_;
99   int late_reverb_start_;
100   int late_reverb_end_;
101   int block_to_analyze_ = 0;
102   int estimation_region_candidate_size_ = 0;
103   bool estimation_region_identified_ = false;
104   std::vector<float> previous_gains_;
105   float decay_;
106   float tail_gain_ = 0.f;
107   float smoothing_constant_ = 0.f;
108 };
109 
110 }  // namespace webrtc
111 
112 #endif  // MODULES_AUDIO_PROCESSING_AEC3_REVERB_DECAY_ESTIMATOR_H_
113