/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/modules/interface/module_common_types.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/voice_engine/level_indicator.h" namespace webrtc { namespace voe { // Number of bars on the indicator. // Note that the number of elements is specified because we are indexing it // in the range of 0-32 const int8_t permutation[33] = {0,1,2,3,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,9,9,9,9,9,9,9,9}; AudioLevel::AudioLevel() : _critSect(*CriticalSectionWrapper::CreateCriticalSection()), _absMax(0), _count(0), _currentLevel(0), _currentLevelFullRange(0) { } AudioLevel::~AudioLevel() { delete &_critSect; } void AudioLevel::Clear() { CriticalSectionScoped cs(&_critSect); _absMax = 0; _count = 0; _currentLevel = 0; _currentLevelFullRange = 0; } void AudioLevel::ComputeLevel(const AudioFrame& audioFrame) { int16_t absValue(0); // Check speech level (works for 2 channels as well) absValue = WebRtcSpl_MaxAbsValueW16( audioFrame.data_, audioFrame.samples_per_channel_*audioFrame.num_channels_); // Protect member access using a lock since this method is called on a // dedicated audio thread in the RecordedDataIsAvailable() callback. CriticalSectionScoped cs(&_critSect); if (absValue > _absMax) _absMax = absValue; // Update level approximately 10 times per second if (_count++ == kUpdateFrequency) { _currentLevelFullRange = _absMax; _count = 0; // Highest value for a int16_t is 0x7fff = 32767 // Divide with 1000 to get in the range of 0-32 which is the range of // the permutation vector int32_t position = _absMax/1000; // Make it less likely that the bar stays at position 0. I.e. only if // its in the range 0-250 (instead of 0-1000) if ((position == 0) && (_absMax > 250)) { position = 1; } _currentLevel = permutation[position]; // Decay the absolute maximum (divide by 4) _absMax >>= 2; } } int8_t AudioLevel::Level() const { CriticalSectionScoped cs(&_critSect); return _currentLevel; } int16_t AudioLevel::LevelFullRange() const { CriticalSectionScoped cs(&_critSect); return _currentLevelFullRange; } } // namespace voe } // namespace webrtc