audio_level.cc (3146B)
1 /* 2 * Copyright (c) 2012 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 "audio/audio_level.h" 12 13 #include <cstdint> 14 15 #include "api/audio/audio_frame.h" 16 #include "common_audio/signal_processing/include/signal_processing_library.h" 17 #include "rtc_base/synchronization/mutex.h" 18 19 namespace webrtc { 20 namespace voe { 21 22 AudioLevel::AudioLevel() 23 : abs_max_(0), count_(0), current_level_full_range_(0) {} 24 25 AudioLevel::~AudioLevel() {} 26 27 void AudioLevel::Reset() { 28 MutexLock lock(&mutex_); 29 abs_max_ = 0; 30 count_ = 0; 31 current_level_full_range_ = 0; 32 total_energy_ = 0.0; 33 total_duration_ = 0.0; 34 } 35 36 int16_t AudioLevel::LevelFullRange() const { 37 MutexLock lock(&mutex_); 38 return current_level_full_range_; 39 } 40 41 void AudioLevel::ResetLevelFullRange() { 42 MutexLock lock(&mutex_); 43 abs_max_ = 0; 44 count_ = 0; 45 current_level_full_range_ = 0; 46 } 47 48 double AudioLevel::TotalEnergy() const { 49 MutexLock lock(&mutex_); 50 return total_energy_; 51 } 52 53 double AudioLevel::TotalDuration() const { 54 MutexLock lock(&mutex_); 55 return total_duration_; 56 } 57 58 void AudioLevel::ComputeLevel(const AudioFrame& audioFrame, double duration) { 59 // Check speech level (works for 2 channels as well) 60 int16_t abs_value = 61 audioFrame.muted() 62 ? 0 63 : WebRtcSpl_MaxAbsValueW16( 64 audioFrame.data(), 65 audioFrame.samples_per_channel_ * audioFrame.num_channels_); 66 67 // Protect member access using a lock since this method is called on a 68 // dedicated audio thread in the RecordedDataIsAvailable() callback. 69 MutexLock lock(&mutex_); 70 71 if (abs_value > abs_max_) 72 abs_max_ = abs_value; 73 74 // Update level approximately 9 times per second, assuming audio frame 75 // duration is approximately 10 ms. (The update frequency is every 76 // 11th (= |kUpdateFrequency+1|) call: 1000/(11*10)=9.09..., we should 77 // probably change this behavior, see https://crbug.com/webrtc/10784). 78 if (count_++ == kUpdateFrequency) { 79 current_level_full_range_ = abs_max_; 80 81 count_ = 0; 82 83 // Decay the absolute maximum (divide by 4) 84 abs_max_ >>= 2; 85 } 86 87 // See the description for "totalAudioEnergy" in the WebRTC stats spec 88 // (https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy) 89 // for an explanation of these formulas. In short, we need a value that can 90 // be used to compute RMS audio levels over different time intervals, by 91 // taking the difference between the results from two getStats calls. To do 92 // this, the value needs to be of units "squared sample value * time". 93 double additional_energy = 94 static_cast<double>(current_level_full_range_) / INT16_MAX; 95 additional_energy *= additional_energy; 96 total_energy_ += additional_energy * duration; 97 total_duration_ += duration; 98 } 99 100 } // namespace voe 101 } // namespace webrtc