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_FILTER_ANALYZER_H_
12 #define MODULES_AUDIO_PROCESSING_AEC3_FILTER_ANALYZER_H_
13 
14 #include <stddef.h>
15 
16 #include <array>
17 #include <memory>
18 #include <vector>
19 
20 #include "api/array_view.h"
21 #include "api/audio/echo_canceller3_config.h"
22 #include "modules/audio_processing/aec3/aec3_common.h"
23 #include "rtc_base/constructor_magic.h"
24 
25 namespace webrtc {
26 
27 class ApmDataDumper;
28 class RenderBuffer;
29 
30 // Class for analyzing the properties of an adaptive filter.
31 class FilterAnalyzer {
32  public:
33   FilterAnalyzer(const EchoCanceller3Config& config,
34                  size_t num_capture_channels);
35   ~FilterAnalyzer();
36 
37   FilterAnalyzer(const FilterAnalyzer&) = delete;
38   FilterAnalyzer& operator=(const FilterAnalyzer&) = delete;
39 
40   // Resets the analysis.
41   void Reset();
42 
43   // Updates the estimates with new input data.
44   void Update(rtc::ArrayView<const std::vector<float>> filters_time_domain,
45               const RenderBuffer& render_buffer,
46               bool* any_filter_consistent,
47               float* max_echo_path_gain);
48 
49   // Returns the delay in blocks for each filter.
FilterDelaysBlocks()50   rtc::ArrayView<const int> FilterDelaysBlocks() const {
51     return filter_delays_blocks_;
52   }
53 
54   // Returns the minimum delay of all filters in terms of blocks.
MinFilterDelayBlocks()55   int MinFilterDelayBlocks() const { return min_filter_delay_blocks_; }
56 
57   // Returns the number of blocks for the current used filter.
FilterLengthBlocks()58   int FilterLengthBlocks() const {
59     return filter_analysis_states_[0].filter_length_blocks;
60   }
61 
62   // Returns the preprocessed filter.
GetAdjustedFilters()63   rtc::ArrayView<const std::vector<float>> GetAdjustedFilters() const {
64     return h_highpass_;
65   }
66 
67   // Public for testing purposes only.
68   void SetRegionToAnalyze(size_t filter_size);
69 
70  private:
71   struct FilterAnalysisState;
72 
73   void AnalyzeRegion(
74       rtc::ArrayView<const std::vector<float>> filters_time_domain,
75       const RenderBuffer& render_buffer);
76 
77   void UpdateFilterGain(rtc::ArrayView<const float> filters_time_domain,
78                         FilterAnalysisState* st);
79   void PreProcessFilters(
80       rtc::ArrayView<const std::vector<float>> filters_time_domain);
81 
82   void ResetRegion();
83 
84   struct FilterRegion {
85     size_t start_sample_;
86     size_t end_sample_;
87   };
88 
89   // This class checks whether the shape of the impulse response has been
90   // consistent over time.
91   class ConsistentFilterDetector {
92    public:
93     explicit ConsistentFilterDetector(const EchoCanceller3Config& config);
94     void Reset();
95     bool Detect(rtc::ArrayView<const float> filter_to_analyze,
96                 const FilterRegion& region,
97                 rtc::ArrayView<const std::vector<float>> x_block,
98                 size_t peak_index,
99                 int delay_blocks);
100 
101    private:
102     bool significant_peak_;
103     float filter_floor_accum_;
104     float filter_secondary_peak_;
105     size_t filter_floor_low_limit_;
106     size_t filter_floor_high_limit_;
107     const float active_render_threshold_;
108     size_t consistent_estimate_counter_ = 0;
109     int consistent_delay_reference_ = -10;
110   };
111 
112   struct FilterAnalysisState {
FilterAnalysisStateFilterAnalysisState113     explicit FilterAnalysisState(const EchoCanceller3Config& config)
114         : filter_length_blocks(config.filter.refined_initial.length_blocks),
115           consistent_filter_detector(config) {}
116     float gain;
117     size_t peak_index;
118     int filter_length_blocks;
119     bool consistent_estimate = false;
120     ConsistentFilterDetector consistent_filter_detector;
121   };
122 
123   static int instance_count_;
124   std::unique_ptr<ApmDataDumper> data_dumper_;
125   const bool bounded_erl_;
126   const float default_gain_;
127   std::vector<std::vector<float>> h_highpass_;
128 
129   size_t blocks_since_reset_ = 0;
130   FilterRegion region_;
131 
132   std::vector<FilterAnalysisState> filter_analysis_states_;
133   std::vector<int> filter_delays_blocks_;
134 
135   int min_filter_delay_blocks_ = 0;
136 };
137 
138 }  // namespace webrtc
139 
140 #endif  // MODULES_AUDIO_PROCESSING_AEC3_FILTER_ANALYZER_H_
141