计算一个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;
}