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