本文主要是介绍【C脚本】计算PCM的DBFS(分贝全尺度),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
DBFS是分贝全尺度(Decibels Full Scale)的缩写,是一种用于衡量音频信号强度的单位。DBFS是相对于数字音频的最大可能幅度而言的,它的取值范围通常是从0到-∞。在DBFS中,0表示音频信号的最大幅度,-∞表示完全没有信号。
计算一个24bit、大端PCM样本的DBFS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>int main() {unsigned char buf[3]; // 存储大端24bit PCM样本的缓冲区float sample; // 存储转换后的浮点数样本值float max_sample = pow(2, 23) - 1; // 最大电平值,即所有位都为1时的值// 假设buf中存储的是大端24bit PCM样本的值buf[0] = 0x12;buf[1] = 0x34;buf[2] = 0x56;// 将24bit PCM样本转换为浮点数int sample_int = (buf[0] << 16) | (buf[1] << 8) | buf[2]; // 先将3个字节拼成一个整数if (sample_int & 0x800000) { // 如果最高位是1,即负数sample_int |= 0xff000000; // 则将32位整数的高8位都置为1,表示负数}sample = (float)sample_int / max_sample; // 转换为浮点数,再除以最大电平值// 计算DBFS值float dbfs = 20 * log10(fabs(sample)); // 用对数函数计算分贝数值printf("DBFS: %.2f\n", dbfs);return 0;
}
之所以用上述方法转负数的原因参见:C语言中负数的存储
求一段PCM的平均DBFS的方法
下面的函数只统计第一个声道的DBFS,且小端数据的计算一直有问题,结果不一定是负数,不清楚是数据有问题还是方法用错了,希望大神指教,感谢。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>/*
@param char *data PCM数据
@param int Endianness 大小端标识,大端为真、小端为假
@param int byte 字节大小,可选:2字节(16bit)、3字节(24bit)
@param int sampling_num 统计的次数
@param int channel 声道数,几声道就写几,如双声道就写2*/
double averageDBFS(char *data, int Endianness, int byte, int sampling_num, int channel) {int i;double sample = 0;double pref = pow(2, byte*8-1);int interval_bit = channel * byte;if(Endianness){// 大端if(byte==3){for(i=0;i<sampling_num;i++){int bsize = i * interval_bit;int value = (*(data+bsize) << 16) | (*(data+bsize+1) << 8) | *(data+bsize+2);if (value & 0x800000) { // 如果最高位是1,即负数value |= 0xff000000; // 则将32位整数的高8位都置为1,表示负数}sample += fabs(value);}}else if(byte==2){for(i=0;i<sampling_num;i++){int bsize = i * interval_bit;short int value = (*(data+bsize) << 8) | *(data+bsize+1);sample += fabs(value);}}}else{// 小端/* if(byte==3){for(i=0;i<sampling_num;i++){int bsize = i * interval_bit;int value = (*(data+bsize+2) << 16) | (*(data+bsize+1) << 8) | *(data+bsize);if (value & 0x800000) { // 如果最高位是1,即负数value |= 0xff000000; // 则将32位整数的高8位都置为1,表示负数}sample += fabs(value);}}else if(byte==2){for(i=0;i<sampling_num;i++){int bsize = i * interval_bit;short int value = (*(data+bsize+1) << 8) | *(data+bsize);sample += fabs(value);}} */}sample /= sampling_num;double dbfs = 20 * log10(sample / pref);return dbfs;
}
这篇关于【C脚本】计算PCM的DBFS(分贝全尺度)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!