【C脚本】计算PCM的DBFS(分贝全尺度)

2024-04-01 23:12

本文主要是介绍【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(分贝全尺度)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/868379

相关文章

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

利用Python脚本实现批量将图片转换为WebP格式

《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

《Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)》本文主要介绍了Golang分布式锁实现,采用Redis+Lua脚本确保原子性,持可重入和自动续期,用于防止超卖及重复下单,具有一定... 目录1 概念应用场景分布式锁必备特性2 思路分析宕机与过期防止误删keyLua保证原子性可重入锁自动

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,