Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: webrtc/modules/audio_processing/rms_level.cc

Issue 2535523002: Refactor RMSLevel and give it new functionality (Closed)
Patch Set: Rename to RmsLevel Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_processing/rms_level.h" 11 #include "webrtc/modules/audio_processing/rms_level.h"
12 12
13 #include <math.h> 13 #include <math.h>
14 #include <algorithm>
15 #include <numeric>
14 16
15 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
16 18
17 namespace webrtc { 19 namespace webrtc {
20 namespace {
21 static constexpr float kMaxSquaredLevel = 32768 * 32768;
22 static constexpr int kMinLevelDb = 127;
23 // kMinLevel is the level corresponding to kMinLevelDb, that is 10^(-127/10).
24 static constexpr float kMinLevel = 1.995262314968883e-13f;
18 25
19 static const float kMaxSquaredLevel = 32768 * 32768; 26 // Calculates the normalized RMS value from a mean square value. The input
27 // should be the sum of squared samples divided by the number of samples. The
28 // value will be normalized to full range before computing the RMS, wich is
29 // returned as a negated dBfs. That is, 0 is full amplitude while 127 is very
30 // faint.
31 int ComputeRms(float mean_square) {
32 if (mean_square <= kMinLevel * kMaxSquaredLevel) {
33 // Very faint; simply return the minimum value.
34 return kMinLevelDb;
35 }
36 // Normalize by the max level.
37 const float mean_square_norm = mean_square / kMaxSquaredLevel;
38 RTC_DCHECK_GT(mean_square_norm, kMinLevel);
39 // 20log_10(x^0.5) = 10log_10(x)
40 const float rms = 10.f * log10(mean_square_norm);
41 RTC_DCHECK_LE(rms, 0.f);
42 RTC_DCHECK_GT(rms, -kMinLevelDb);
43 // Return the negated value.
44 return static_cast<int>(-rms + 0.5f);
45 }
46 } // namespace
20 47
21 RMSLevel::RMSLevel() 48 RmsLevel::RmsLevel() {
22 : sum_square_(0), 49 Reset();
23 sample_count_(0) {}
24
25 RMSLevel::~RMSLevel() {}
26
27 void RMSLevel::Reset() {
28 sum_square_ = 0;
29 sample_count_ = 0;
30 } 50 }
31 51
32 void RMSLevel::Process(const int16_t* data, size_t length) { 52 RmsLevel::~RmsLevel() = default;
33 for (size_t i = 0; i < length; ++i) { 53
34 sum_square_ += data[i] * data[i]; 54 void RmsLevel::Reset() {
55 sum_square_ = 0.f;
56 sample_count_ = 0;
57 max_sum_square_ = 0.f;
58 block_size_ = rtc::Optional<size_t>();
59 }
60
61 void RmsLevel::Analyze(rtc::ArrayView<const int16_t> data) {
62 if (data.empty()) {
63 return;
35 } 64 }
65
66 CheckBlockSize(data.size());
67
68 const float sum_square =
69 std::accumulate(data.begin(), data.end(), 0.f,
70 [](float a, int16_t b) { return a + b * b; });
71 RTC_DCHECK_GE(sum_square, 0.f);
72 sum_square_ += sum_square;
73 sample_count_ += data.size();
74
75 max_sum_square_ = std::max(max_sum_square_, sum_square);
76 }
77
78 void RmsLevel::AnalyzeMuted(size_t length) {
79 CheckBlockSize(length);
36 sample_count_ += length; 80 sample_count_ += length;
37 } 81 }
38 82
39 void RMSLevel::ProcessMuted(size_t length) { 83 int RmsLevel::Average() {
40 sample_count_ += length; 84 int rms = (sample_count_ == 0) ? kMinLevelDb
85 : ComputeRms(sum_square_ / sample_count_);
86 Reset();
87 return rms;
41 } 88 }
42 89
43 int RMSLevel::RMS() { 90 RmsLevel::Levels RmsLevel::AverageAndPeak() {
44 if (sample_count_ == 0 || sum_square_ == 0) { 91 // Note that block_size_ should by design always be non-empty when
45 Reset(); 92 // sample_count_ != 0. Also, the * operator of rtc::Optional enforces this
46 return kMinLevel; 93 // with a DCHECK.
47 } 94 Levels levels = (sample_count_ == 0)
48 95 ? Levels{kMinLevelDb, kMinLevelDb}
49 // Normalize by the max level. 96 : Levels{ComputeRms(sum_square_ / sample_count_),
50 float rms = sum_square_ / (sample_count_ * kMaxSquaredLevel); 97 ComputeRms(max_sum_square_ / *block_size_)};
51 // 20log_10(x^0.5) = 10log_10(x)
52 rms = 10 * log10(rms);
53 RTC_DCHECK_LE(rms, 0);
54 if (rms < -kMinLevel)
55 rms = -kMinLevel;
56
57 rms = -rms;
58 Reset(); 98 Reset();
59 return static_cast<int>(rms + 0.5); 99 return levels;
60 } 100 }
61 101
102 void RmsLevel::CheckBlockSize(size_t block_size) {
103 if (block_size_ != rtc::Optional<size_t>(block_size)) {
104 Reset();
105 block_size_ = rtc::Optional<size_t>(block_size);
106 }
107 }
62 } // namespace webrtc 108 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/rms_level.h ('k') | webrtc/modules/audio_processing/rms_level_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698