WAVE绘制频谱图(四)——总结其它一些将PCM数据转为分贝值算法
{
https://blog.csdn.net/qq_36568418/article/details/91549540?spm=1001.2014.3001.5502
}
{
1:计算分贝 音频数据与大小
首先我们分别累加每个采样点的数值,除以采样个数,得到声音平均能量值。
然后再将其做100与32767之间的等比量化。得到1-100的量化值。
通常情况下,人声分布在较低的能量范围,这样就会使量化后的数据大致分布在1-20的较小区间,不能够很敏感的感知变化。
所以我们将其做了5倍的放大,当然计算后大于100的值,我们将其赋值100.
-
-
//参数为数据,采样个数
-
//返回值为分贝
-
-
int SimpleCalculate_DB(short* pcmData, int sample)
-
{
-
signed short ret = 0;
-
if (sample > 0){
-
int sum = 0;
-
signed short* pos = (signed short *)pcmData;
-
for (int i = 0; i < sample; i++){
-
sum += abs(*pos);
-
pos++;
-
}
-
ret = sum * 500.0 / (sample * VOLUMEMAX);
-
if (ret >= 100){
-
ret = 100;
-
}
-
}
-
return ret;
-
}
2:计算均方根(RMS) 即能量值
-
static const float kMaxSquaredLevel = 32768 * 32768;
-
constexpr float kMinLevel = 30.f;
-
-
void Process(const int16_t* data, size_t length)
-
{
-
float sum_square_ = 0;
-
size_t sample_count_ = 0;
-
for (size_t i = 0; i < length; ++i) {
-
sum_square_ += data[i] * data[i];
-
}
-
sample_count_ += length;.
-
float rms = sum_square_ / (sample_count_ * kMaxSquaredLevel);
-
//20log_10(x^0.5) = 10log_10(x)
-
rms = 10 * log10(rms);
-
if (rms < -kMinLevel)
-
rms = -kMinLevel;
-
rms = -rms;
-
return static_cast<int>(rms + 0.5);
-
}
3:获取音频数据最大的振幅(即绝对值最大)(0-32767),除以1000,得到(0-32)。从数组中获取相应索引所对应的分贝值。(提取自webrtc)
-
-
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};
-
-
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;
-
}
-
-
void ComputeLevel(const int16_t* data, size_t length)
-
{
-
int16_t _absMax = 0;
-
int16_t _count = 0;
-
int8_t _currentLevel = 0;
-
int16_t absValue(0);
-
absValue = WebRtcSpl_MaxAbsValueW16(data,length);
-
if (absValue > _absMax)
-
_absMax = absValue;
-
if (_count++ == 10) {
-
_count = 0;
-
int32_t position = _absMax/1000;
-
if ((position == 0) && (_absMax > 250)){
-
position = 1;
-
}
-
_currentLevel = permutation[position];
-
_absMax >>= 2;
-
}
-
}
上文第三篇中采用的即为计算RMS能量值.
}