xref: /aosp_15_r20/external/webrtc/modules/audio_processing/aec3/stationarity_estimator.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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_STATIONARITY_ESTIMATOR_H_
12 #define MODULES_AUDIO_PROCESSING_AEC3_STATIONARITY_ESTIMATOR_H_
13 
14 #include <stddef.h>
15 
16 #include <array>
17 #include <atomic>
18 #include <memory>
19 
20 #include "api/array_view.h"
21 #include "modules/audio_processing/aec3/aec3_common.h"  // kFftLengthBy2Plus1...
22 #include "modules/audio_processing/aec3/reverb_model.h"
23 #include "rtc_base/checks.h"
24 
25 namespace webrtc {
26 
27 class ApmDataDumper;
28 struct SpectrumBuffer;
29 
30 class StationarityEstimator {
31  public:
32   StationarityEstimator();
33   ~StationarityEstimator();
34 
35   // Reset the stationarity estimator.
36   void Reset();
37 
38   // Update just the noise estimator. Usefull until the delay is known
39   void UpdateNoiseEstimator(
40       rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum);
41 
42   // Update the flag indicating whether this current frame is stationary. For
43   // getting a more robust estimation, it looks at future and/or past frames.
44   void UpdateStationarityFlags(
45       const SpectrumBuffer& spectrum_buffer,
46       rtc::ArrayView<const float> render_reverb_contribution_spectrum,
47       int idx_current,
48       int num_lookahead);
49 
50   // Returns true if the current band is stationary.
IsBandStationary(size_t band)51   bool IsBandStationary(size_t band) const {
52     return stationarity_flags_[band] && (hangovers_[band] == 0);
53   }
54 
55   // Returns true if the current block is estimated as stationary.
56   bool IsBlockStationary() const;
57 
58  private:
59   static constexpr int kWindowLength = 13;
60   // Returns the power of the stationary noise spectrum at a band.
GetStationarityPowerBand(size_t k)61   float GetStationarityPowerBand(size_t k) const { return noise_.Power(k); }
62 
63   // Get an estimation of the stationarity for the current band by looking
64   // at the past/present/future available data.
65   bool EstimateBandStationarity(const SpectrumBuffer& spectrum_buffer,
66                                 rtc::ArrayView<const float> average_reverb,
67                                 const std::array<int, kWindowLength>& indexes,
68                                 size_t band) const;
69 
70   // True if all bands at the current point are stationary.
71   bool AreAllBandsStationary();
72 
73   // Update the hangover depending on the stationary status of the current
74   // frame.
75   void UpdateHangover();
76 
77   // Smooth the stationarity detection by looking at neighbouring frequency
78   // bands.
79   void SmoothStationaryPerFreq();
80 
81   class NoiseSpectrum {
82    public:
83     NoiseSpectrum();
84     ~NoiseSpectrum();
85 
86     // Reset the noise power spectrum estimate state.
87     void Reset();
88 
89     // Update the noise power spectrum with a new frame.
90     void Update(
91         rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum);
92 
93     // Get the noise estimation power spectrum.
Spectrum()94     rtc::ArrayView<const float> Spectrum() const { return noise_spectrum_; }
95 
96     // Get the noise power spectrum at a certain band.
Power(size_t band)97     float Power(size_t band) const {
98       RTC_DCHECK_LT(band, noise_spectrum_.size());
99       return noise_spectrum_[band];
100     }
101 
102    private:
103     // Get the update coefficient to be used for the current frame.
104     float GetAlpha() const;
105 
106     // Update the noise power spectrum at a certain band with a new frame.
107     float UpdateBandBySmoothing(float power_band,
108                                 float power_band_noise,
109                                 float alpha) const;
110     std::array<float, kFftLengthBy2Plus1> noise_spectrum_;
111     size_t block_counter_;
112   };
113 
114   static std::atomic<int> instance_count_;
115   std::unique_ptr<ApmDataDumper> data_dumper_;
116   NoiseSpectrum noise_;
117   std::array<int, kFftLengthBy2Plus1> hangovers_;
118   std::array<bool, kFftLengthBy2Plus1> stationarity_flags_;
119 };
120 
121 }  // namespace webrtc
122 
123 #endif  // MODULES_AUDIO_PROCESSING_AEC3_STATIONARITY_ESTIMATOR_H_
124