计算一个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;
}
04-02 12:54