Line data Source code
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 "webrtc/modules/audio_processing/level_controller/peak_level_estimator.h"
12 :
13 : #include <algorithm>
14 :
15 : #include "webrtc/modules/audio_processing/audio_buffer.h"
16 : #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
17 :
18 : namespace webrtc {
19 : namespace {
20 :
21 : constexpr float kMinLevel = 30.f;
22 :
23 : } // namespace
24 :
25 0 : PeakLevelEstimator::PeakLevelEstimator(float initial_peak_level_dbfs) {
26 0 : Initialize(initial_peak_level_dbfs);
27 0 : }
28 :
29 0 : PeakLevelEstimator::~PeakLevelEstimator() {}
30 :
31 0 : void PeakLevelEstimator::Initialize(float initial_peak_level_dbfs) {
32 0 : RTC_DCHECK_LE(-100.f, initial_peak_level_dbfs);
33 0 : RTC_DCHECK_GE(0.f, initial_peak_level_dbfs);
34 :
35 0 : peak_level_ = std::pow(10.f, initial_peak_level_dbfs / 20.f) * 32768.f;
36 0 : peak_level_ = std::max(peak_level_, kMinLevel);
37 :
38 0 : hold_counter_ = 0;
39 0 : initialization_phase_ = true;
40 0 : }
41 :
42 0 : float PeakLevelEstimator::Analyze(SignalClassifier::SignalType signal_type,
43 : float frame_peak_level) {
44 0 : if (frame_peak_level == 0) {
45 0 : RTC_DCHECK_LE(kMinLevel, peak_level_);
46 0 : return peak_level_;
47 : }
48 :
49 0 : if (peak_level_ < frame_peak_level) {
50 : // Smoothly update the estimate upwards when the frame peak level is
51 : // higher than the estimate.
52 0 : peak_level_ += 0.1f * (frame_peak_level - peak_level_);
53 0 : hold_counter_ = 100;
54 0 : initialization_phase_ = false;
55 : } else {
56 0 : hold_counter_ = std::max(0, hold_counter_ - 1);
57 :
58 : // When the signal is highly non-stationary, update the estimate slowly
59 : // downwards if the estimate is lower than the frame peak level.
60 0 : if ((signal_type == SignalClassifier::SignalType::kHighlyNonStationary &&
61 0 : hold_counter_ == 0) ||
62 0 : initialization_phase_) {
63 0 : peak_level_ =
64 0 : std::max(peak_level_ + 0.01f * (frame_peak_level - peak_level_),
65 0 : peak_level_ * 0.995f);
66 : }
67 : }
68 :
69 0 : peak_level_ = std::max(peak_level_, kMinLevel);
70 :
71 0 : return peak_level_;
72 : }
73 :
74 : } // namespace webrtc
|