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_ADAPTIVE_FIR_FILTER_H_
12 #define MODULES_AUDIO_PROCESSING_AEC3_ADAPTIVE_FIR_FILTER_H_
13 
14 #include <array>
15 #include <memory>
16 #include <vector>
17 
18 #include "api/array_view.h"
19 #include "modules/audio_processing/aec3/aec3_common.h"
20 #include "modules/audio_processing/aec3/aec3_fft.h"
21 #include "modules/audio_processing/aec3/fft_data.h"
22 #include "modules/audio_processing/aec3/render_buffer.h"
23 #include "modules/audio_processing/logging/apm_data_dumper.h"
24 #include "rtc_base/constructormagic.h"
25 
26 namespace webrtc {
27 namespace aec3 {
28 // Computes and stores the frequency response of the filter.
29 void UpdateFrequencyResponse(
30     rtc::ArrayView<const FftData> H,
31     std::vector<std::array<float, kFftLengthBy2Plus1>>* H2);
32 #if defined(WEBRTC_HAS_NEON)
33 void UpdateFrequencyResponse_NEON(
34     rtc::ArrayView<const FftData> H,
35     std::vector<std::array<float, kFftLengthBy2Plus1>>* H2);
36 #endif
37 #if defined(WEBRTC_ARCH_X86_FAMILY)
38 void UpdateFrequencyResponse_SSE2(
39     rtc::ArrayView<const FftData> H,
40     std::vector<std::array<float, kFftLengthBy2Plus1>>* H2);
41 #endif
42 
43 // Computes and stores the echo return loss estimate of the filter, which is the
44 // sum of the partition frequency responses.
45 void UpdateErlEstimator(
46     const std::vector<std::array<float, kFftLengthBy2Plus1>>& H2,
47     std::array<float, kFftLengthBy2Plus1>* erl);
48 #if defined(WEBRTC_HAS_NEON)
49 void UpdateErlEstimator_NEON(
50     const std::vector<std::array<float, kFftLengthBy2Plus1>>& H2,
51     std::array<float, kFftLengthBy2Plus1>* erl);
52 #endif
53 #if defined(WEBRTC_ARCH_X86_FAMILY)
54 void UpdateErlEstimator_SSE2(
55     const std::vector<std::array<float, kFftLengthBy2Plus1>>& H2,
56     std::array<float, kFftLengthBy2Plus1>* erl);
57 #endif
58 
59 // Adapts the filter partitions.
60 void AdaptPartitions(const RenderBuffer& render_buffer,
61                      const FftData& G,
62                      rtc::ArrayView<FftData> H);
63 #if defined(WEBRTC_HAS_NEON)
64 void AdaptPartitions_NEON(const RenderBuffer& render_buffer,
65                           const FftData& G,
66                           rtc::ArrayView<FftData> H);
67 #endif
68 #if defined(WEBRTC_ARCH_X86_FAMILY)
69 void AdaptPartitions_SSE2(const RenderBuffer& render_buffer,
70                           const FftData& G,
71                           rtc::ArrayView<FftData> H);
72 #endif
73 
74 // Produces the filter output.
75 void ApplyFilter(const RenderBuffer& render_buffer,
76                  rtc::ArrayView<const FftData> H,
77                  FftData* S);
78 #if defined(WEBRTC_HAS_NEON)
79 void ApplyFilter_NEON(const RenderBuffer& render_buffer,
80                       rtc::ArrayView<const FftData> H,
81                       FftData* S);
82 #endif
83 #if defined(WEBRTC_ARCH_X86_FAMILY)
84 void ApplyFilter_SSE2(const RenderBuffer& render_buffer,
85                       rtc::ArrayView<const FftData> H,
86                       FftData* S);
87 #endif
88 
89 }  // namespace aec3
90 
91 // Provides a frequency domain adaptive filter functionality.
92 class AdaptiveFirFilter {
93  public:
94   AdaptiveFirFilter(size_t size_partitions,
95                     Aec3Optimization optimization,
96                     ApmDataDumper* data_dumper);
97 
98   ~AdaptiveFirFilter();
99 
100   // Produces the output of the filter.
101   void Filter(const RenderBuffer& render_buffer, FftData* S) const;
102 
103   // Adapts the filter.
104   void Adapt(const RenderBuffer& render_buffer, const FftData& G);
105 
106   // Receives reports that known echo path changes have occured and adjusts
107   // the filter adaptation accordingly.
108   void HandleEchoPathChange();
109 
110   // Returns the filter size.
SizePartitions()111   size_t SizePartitions() const { return H_.size(); }
112 
113   // Returns the filter based echo return loss.
Erl()114   const std::array<float, kFftLengthBy2Plus1>& Erl() const { return erl_; }
115 
116   // Returns the frequency responses for the filter partitions.
117   const std::vector<std::array<float, kFftLengthBy2Plus1>>&
FilterFrequencyResponse()118   FilterFrequencyResponse() const {
119     return H2_;
120   }
121 
122   // Returns the estimate of the impulse response.
123   const std::array<float, kAdaptiveFilterTimeDomainLength>&
FilterImpulseResponse()124   FilterImpulseResponse() const {
125     return h_;
126   }
127 
DumpFilter(const char * name)128   void DumpFilter(const char* name) {
129     for (auto& H : H_) {
130       data_dumper_->DumpRaw(name, H.re);
131       data_dumper_->DumpRaw(name, H.im);
132     }
133   }
134 
135  private:
136   // Constrain the filter partitions in a cyclic manner.
137   void Constrain();
138 
139   ApmDataDumper* const data_dumper_;
140   const Aec3Fft fft_;
141   const Aec3Optimization optimization_;
142   std::vector<FftData> H_;
143   std::vector<std::array<float, kFftLengthBy2Plus1>> H2_;
144   std::array<float, kAdaptiveFilterTimeDomainLength> h_;
145   std::array<float, kFftLengthBy2Plus1> erl_;
146   size_t partition_to_constrain_ = 0;
147 
148   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveFirFilter);
149 };
150 
151 }  // namespace webrtc
152 
153 #endif  // MODULES_AUDIO_PROCESSING_AEC3_ADAPTIVE_FIR_FILTER_H_
154