1 /*
2  *  Copyright (c) 2016 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 #include "modules/audio_processing/agc2/noise_spectrum_estimator.h"
12 
13 #include <string.h>
14 
15 #include <algorithm>
16 
17 #include "api/array_view.h"
18 #include "modules/audio_processing/logging/apm_data_dumper.h"
19 #include "rtc_base/arraysize.h"
20 #include "rtc_base/checks.h"
21 
22 namespace webrtc {
23 namespace {
24 constexpr float kMinNoisePower = 100.f;
25 }  // namespace
26 
NoiseSpectrumEstimator(ApmDataDumper * data_dumper)27 NoiseSpectrumEstimator::NoiseSpectrumEstimator(ApmDataDumper* data_dumper)
28     : data_dumper_(data_dumper) {
29   Initialize();
30 }
31 
Initialize()32 void NoiseSpectrumEstimator::Initialize() {
33   std::fill(noise_spectrum_, noise_spectrum_ + arraysize(noise_spectrum_),
34             kMinNoisePower);
35 }
36 
Update(rtc::ArrayView<const float> spectrum,bool first_update)37 void NoiseSpectrumEstimator::Update(rtc::ArrayView<const float> spectrum,
38                                     bool first_update) {
39   RTC_DCHECK_EQ(65, spectrum.size());
40 
41   if (first_update) {
42     // Initialize the noise spectral estimate with the signal spectrum.
43     std::copy(spectrum.data(), spectrum.data() + spectrum.size(),
44               noise_spectrum_);
45   } else {
46     // Smoothly update the noise spectral estimate towards the signal spectrum
47     // such that the magnitude of the updates are limited.
48     for (size_t k = 0; k < spectrum.size(); ++k) {
49       if (noise_spectrum_[k] < spectrum[k]) {
50         noise_spectrum_[k] = std::min(
51             1.01f * noise_spectrum_[k],
52             noise_spectrum_[k] + 0.05f * (spectrum[k] - noise_spectrum_[k]));
53       } else {
54         noise_spectrum_[k] = std::max(
55             0.99f * noise_spectrum_[k],
56             noise_spectrum_[k] + 0.05f * (spectrum[k] - noise_spectrum_[k]));
57       }
58     }
59   }
60 
61   // Ensure that the noise spectal estimate does not become too low.
62   for (auto& v : noise_spectrum_) {
63     v = std::max(v, kMinNoisePower);
64   }
65 
66   data_dumper_->DumpRaw("lc_noise_spectrum", 65, noise_spectrum_);
67   data_dumper_->DumpRaw("lc_signal_spectrum", spectrum);
68 }
69 
70 }  // namespace webrtc
71