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 "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
12#include "webrtc/modules/include/module_common_types.h"
13#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
14#include "webrtc/voice_engine/level_indicator.h"
15
16namespace webrtc {
17
18namespace voe {
19
20// Number of bars on the indicator.
21// Note that the number of elements is specified because we are indexing it
22// in the range of 0-32
23const int8_t permutation[33] =
24    {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};
25
26
27AudioLevel::AudioLevel() :
28    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
29    _absMax(0),
30    _count(0),
31    _currentLevel(0),
32    _currentLevelFullRange(0) {
33}
34
35AudioLevel::~AudioLevel() {
36    delete &_critSect;
37}
38
39void AudioLevel::Clear()
40{
41    CriticalSectionScoped cs(&_critSect);
42    _absMax = 0;
43    _count = 0;
44    _currentLevel = 0;
45    _currentLevelFullRange = 0;
46}
47
48void AudioLevel::ComputeLevel(const AudioFrame& audioFrame)
49{
50    int16_t absValue(0);
51
52    // Check speech level (works for 2 channels as well)
53    absValue = WebRtcSpl_MaxAbsValueW16(
54        audioFrame.data_,
55        audioFrame.samples_per_channel_*audioFrame.num_channels_);
56
57    // Protect member access using a lock since this method is called on a
58    // dedicated audio thread in the RecordedDataIsAvailable() callback.
59    CriticalSectionScoped cs(&_critSect);
60
61    if (absValue > _absMax)
62    _absMax = absValue;
63
64    // Update level approximately 10 times per second
65    if (_count++ == kUpdateFrequency)
66    {
67        _currentLevelFullRange = _absMax;
68
69        _count = 0;
70
71        // Highest value for a int16_t is 0x7fff = 32767
72        // Divide with 1000 to get in the range of 0-32 which is the range of
73        // the permutation vector
74        int32_t position = _absMax/1000;
75
76        // Make it less likely that the bar stays at position 0. I.e. only if
77        // its in the range 0-250 (instead of 0-1000)
78        if ((position == 0) && (_absMax > 250))
79        {
80            position = 1;
81        }
82        _currentLevel = permutation[position];
83
84        // Decay the absolute maximum (divide by 4)
85        _absMax >>= 2;
86    }
87}
88
89int8_t AudioLevel::Level() const
90{
91    CriticalSectionScoped cs(&_critSect);
92    return _currentLevel;
93}
94
95int16_t AudioLevel::LevelFullRange() const
96{
97    CriticalSectionScoped cs(&_critSect);
98    return _currentLevelFullRange;
99}
100
101}  // namespace voe
102
103}  // namespace webrtc
104