【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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡桃の壶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值