车载音频开发(二):对音频数据作音量调节

news/2025/1/11 19:55:16/

通过前一个章节打下的基础车载音频开发(一):从看懂wav开始icon-default.png?t=O83Ahttps://blog.csdn.net/Hellomino_/article/details/140873133?fromshare=blogdetail&sharetype=blogdetail&sharerId=140873133&sharerefer=PC&sharesource=Hellomino_&sharefrom=from_link 我们已经对音频文件wav有了初步的了解 

接下来我们可以将音频的每个采样点的数据提取出来,对数据进行处理,简单的,我们可以将数据减小或增大来升高或减低整体的音量。

一般的,音频的数据采样点分为定点和浮点

定点常见的有16bit,24bit,和32bit

浮点一般用float (32bit)

然后,我们必须要指导采样点数值与分贝值(dB)之间的关系

data  : 每个采样点存储的数值(以浮点值为例)

db     : 每个采样点转化的dB值

dB = 20 * log10f(abs( data))

接下来就是代码时间

 1.首先还是创建读取wav头部信息的结构体

struct WavHeader {char chunkId[4];			//"RIFF"uint32_t chunkSize;			//totalsize - 8char format[4];				//"WAVE"char subchunk1Id[4];		//"fmt"uint32_t subchunk1Size;		//16:Normal; 18:Non_PCM; 40:Extensible;
};struct type40_header {uint16_t audioFormat; 		//wav 格式 1;int型  3:float型  65534:未知uint16_t numChannels; 		//声道数 uint32_t sampleRate;		//采样率uint32_t byteRate;			//比特率:采样率 * 采样位宽uint16_t blockAlign;		//采样深度:uint16_t bitsPerSample;		//采样位宽:采样深度 * 8uint16_t cbSize;uint16_t wValidBitsPerSample;uint32_t dwChannelMask;char SubFormat[4];char ckID[4];uint32_t cksize;uint32_t dwSampleLength;
};struct data_header {char subchunk2Id[4];		//"data"uint32_t subchunk2Size;		//datasize
};

其次,我们创建一个预定义函数

#define volume_(x) pow(10, (x / 20))

接下来,我们用用一个函数将所有采样点数据进行提取并调整音量

int volume_contral(const char* filename,float gain)
{WavHeader header = {};type40_header headera = {};data_header headerb = {};ifstream inputFile(filename, ios::binary);if (!inputFile.is_open()) {cerr << "无法打开文件" << endl;return -1;}// 读取WAV文件头部信息并写入ofstream output("output.wav", ios::binary);if (!output.is_open()) {cerr << "无法打开文件" << endl;return -1;}inputFile.read(reinterpret_cast<char*>(&header), sizeof(header));inputFile.read(reinterpret_cast<char*>(&headera), header.subchunk1Size);inputFile.read(reinterpret_cast<char*>(&headerb), sizeof(headerb));output.write(reinterpret_cast<char*>(&header), sizeof(header));output.write(reinterpret_cast<char*>(&headera), header.subchunk1Size);output.write(reinterpret_cast<char*>(&headerb), sizeof(headerb));const size_t dataSize = headerb.subchunk2Size;vector<char> buffer(dataSize);inputFile.read(buffer.data(), dataSize);uint32_t rearsize = header.chunkSize - (uint32_t)dataSize - header.subchunk1Size - sizeof(headerb) - 12;vector<char> rear(rearsize);inputFile.read(rear.data(), rearsize);inputFile.close();uint16_t perdatasize = headera.bitsPerSample / 8;float wavdata;int32_t WavData = 0;int16_t WavData16 = 0;for (size_t i = 0; i < dataSize / perdatasize; i++) {if (16 == headera.bitsPerSample){memcpy(&WavData16, buffer.data() + i * perdatasize, perdatasize);printf(" %10d , %.2f db ,", WavData16, 20 * log10f(abs((float)WavData16) / 32768));WavData16 = (int16_t)WavData16 * volume_(gain);memcpy(buffer.data() + i * perdatasize, &WavData16,  perdatasize);printf("\t %10d , %.2f db ,", WavData16, 20 * log10f(abs((float)WavData16) / 32768));}else if (24 == headera.bitsPerSample){memcpy(&WavData, buffer.data() + i * perdatasize, perdatasize);printf(" %10d , %.2f db ,", (WavData << 8) / 256, 20 * log10f(abs((float)(WavData << 8)) / 256 / 8388608));WavData = (int32_t)((WavData << 8) * volume_(gain));WavData >>= 8;memcpy(buffer.data() + i * perdatasize, &WavData, perdatasize);printf("\t %10d , %.2f db ,", (WavData << 8) / 256, 20 * log10f(abs((float)(WavData << 8)) / 256 / 8388608));}else if (32 == headera.bitsPerSample){if (3 == headera.audioFormat || (65534 == headera.audioFormat && 0x01 != headera.SubFormat[0])) {memcpy(&wavdata, buffer.data() + i * perdatasize, perdatasize);printf(" %.6f , %.2f db ,", wavdata, 20 * log10f(abs(wavdata)));wavdata = wavdata * volume_(gain);memcpy(buffer.data() + i * perdatasize, &wavdata, perdatasize);printf("\t %.6f , %.2f db ,", wavdata, 20 * log10f(abs(wavdata)));}else {memcpy(&WavData, buffer.data() + i * perdatasize, perdatasize);printf(" %16d , %.2f db ,", WavData, 20 * log10f(abs((float)WavData) / 2147483648));WavData = (int32_t)WavData * volume_(gain);memcpy(buffer.data() + i * perdatasize, &WavData, perdatasize);printf("\t %16d , %.2f db ,", WavData, 20 * log10f(abs((float)WavData) / 2147483648));}}cout << endl;}output.write(buffer.data(), buffer.size());output.write(rear.data(), rearsize);buffer.clear();output.close();return 0;
}


http://www.ppmy.cn/news/1562317.html

相关文章

Redis 性能优化 18招

前言 Redis在我们的日常开发工作中&#xff0c;使用频率非常高&#xff0c;已经变成了必不可少的技术之一。 Redis的使用场景也很多。 比如&#xff1a;保存用户登录态&#xff0c;做限流&#xff0c;做分布式锁&#xff0c;做缓存提升数据访问速度等等。 那么问题来了&…

TON 生态增长实战四城巡回压轴站—— 深圳站即将启动

2024 年&#xff0c;TON 生态迎来了前所未有的突破与成长&#xff0c;成为区块链领域不可忽视的力量。这一年&#xff0c;TON 的用户数增长至 1337 万&#xff0c;月活跃钱包数量达到 1240 万&#xff0c;生态总锁仓量&#xff08;TVL&#xff09;从年初的 53.7 万美元跃升至 7…

Linux-蓝牙协议

SPP (Serial Port Profile): 串口协议&#xff08;SPP&#xff09;是一个蓝牙配置文件&#xff0c;允许设备通过蓝牙模拟传统的串行端口通信。它通常用于无线串口连接&#xff0c;允许设备如计算机和外设&#xff08;例如打印机或条形码扫描器&#xff09;之间进行数据传输。A…

[Unity]发包前遇到的坑之GridLayoutGroup

发包前禁用了UI上面一个调试页面A后&#xff0c;发现无法正确获取某一个用了GridLayoutGroup组件的所有子物体的世界坐标。 一顿研究之后发现&#xff0c;在Start的时候想要正确获取其坐标&#xff0c;需要强制刷新一次布局&#xff0c;方法如下&#xff1a; UnityEngine.U…

培训机构Day27

今天看老师给我们实现了登录功能前后端实现&#xff0c;在不借助成熟框架来实现对于初学者来说难度确实很大。需要大量时间练习。 知识点&#xff1a; 设计模式&#xff1a;面向对象的语言。对某个特定领域特定场景问题的最佳解决方案。 1.单例模式。singleton。单个实例&…

分享几个高清无水印国外视频素材网站

在数字内容创作日益盛行的今天&#xff0c;高质量的视频素材成为了视频制作、广告创意和多媒体项目中不可或缺的元素。对于追求专业水准的创作者而言&#xff0c;高清、无水印的视频素材是确保作品质量的基石。以下将分享几个优质的视频素材网站&#xff0c;为您的创作之路提供…

k8s里面etcd的作用

etcd 是 Kubernetes 集群中一个至关重要的组件,它是一个开源的分布式键值存储系统,主要用于存储和管理 Kubernetes 集群的配置和状态信息。以下是 etcd 在 Kubernetes 中的具体作用和功能: ### 1. **集群状态存储** etcd 是 Kubernetes 集群的持久化存储后端,负责存储和管…

VUE3 VITE项目在 npm 中,关于 Vue 的常用命令有一些基础命令

如果你正在使用 Vite 构建的 Vue 3 项目&#xff0c;并且想要使用相关的 Vue 和 Vite 工具&#xff0c;下面是一些常用的命令和步骤来创建和管理 Vue 项目。 1. 使用 npm create 创建 Vue 3 项目&#xff08;Vite&#xff09; 如果你还没有创建项目&#xff0c;可以使用以下命…