WebRTC中音频能量计算

1.WebRTC中音频能量计算

WebRTC中实现获取音频能量计算的方法是:获取音频数据最大的振幅(即绝对值最大)(范围是0-32767),然后再除以1000,得到0-32之间的数值。从数组中获取相应索引所对应的能量level等级。

我们看下webRTC中level_indicator.cc中对音频level判断的处理。

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() :
    _absMax(0),
    _count(0),
    _currentLevel(0),
    _currentLevelFullRange(0) {
}

AudioLevel::~AudioLevel() {
}

void AudioLevel::Clear()
{
    rtc::CritScope 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.
    rtc::CritScope cs(&_critSect);

    if (absValue > _absMax)
    _absMax = absValue;
    //WebRTC中音频帧间隔是10ms一次音频帧,这里把塞入10次音频帧作为一次统计,来获取这10次中的最大音频帧的能量值(需要在去噪后计算音频能量,减小误差)
    // 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;
        }
        //算出position的位置后,从上面的音频能量数组中获取当前的level等级。
        _currentLevel = permutation[position];

        // Decay the absolute maximum (divide by 4)
        _absMax >>= 2;
    }
}
/**
*获取音频能量,范围0-9
*/
int8_t AudioLevel::Level() const
{
    rtc::CritScope cs(&_critSect);
    return _currentLevel;
}
/**
*获取音频能量,范围0-32767
*/
int16_t AudioLevel::LevelFullRange() const
{
    rtc::CritScope cs(&_critSect);
    return _currentLevelFullRange;
}

}  // namespace voe

}  // namespace webrtc

看下WebRtcSpl_MaxAbsValueW16C函数,函数主要是获取vector中的绝对值的最大值,同时不能超过int16的最大值32767。

int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, size_t length) 
{
    size_t i = 0;
    int absolute = 0, maximum = 0;
    for (i = 0; i < length; i++) {
        absolute = abs((int)vector[i]);
        if (absolute > maximum) {
            maximum = absolute;
        }
    }
    if (maximum > 32767) {
        maximum = 32767;
    }
    return (int16_t)maximum;
}

这个最终获取的值就可以用来实时获取音频的音量值了。

我们可以看到这里取的是最大值,为了得到的结果更加准确的话,音频的能量计算最好放在去噪后。

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/126664081