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