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

embedded/2025/1/12 18:36:46/

通过前一个章节打下的基础车载音频开发(一):从看懂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/embedded/153352.html

相关文章

webpack03

什么是source-map 将代码编译压缩之后&#xff0c;&#xff0c;可以通过source-map映射会原来的代码&#xff0c;&#xff0c;&#xff0c;在调试的时候可以准确找到原代码报错位置&#xff0c;&#xff0c;&#xff0c;进行修改 source-map有很多值&#xff1a; eval &#…

2025年第三届“华数杯”国际大学生数学建模竞赛【A题】Problem A: Can He Swim Faster

问题1&#xff1a;运动员的出色比赛表现通常得益于艰苦且持续的专业训练&#xff0c;这不仅提升了游泳技能&#xff0c;也增强了生理储备。比赛中&#xff0c;科学控制游泳速度是关键&#xff0c;包括保持个人节奏、寻求最佳身体状态节奏和合理分配体力。针对自由泳项目&#x…

【计算机网络】IPSec的安全协议和封装模式

根据上一篇文章我们讲了IPSec的基本框架&#xff0c;这一篇我们将对IPSec的协议和封装模式进行讲解。 IPSec安全协议 AH(Authentication Header)报文头验证协议&#xff0c;主要提供完整性、真实性、防重放功能&#xff1b;然而&#xff0c;AH并不加密数据报文(机密性)。IP协议…

国产3D CAD将逐步取代国外软件

在工业软件的关键领域&#xff0c;计算机辅助设计&#xff08;CAD&#xff09;软件对于制造业的重要性不言而喻。近年来&#xff0c;国产 CAD 的发展态势迅猛&#xff0c;展现出巨大的潜力与机遇&#xff0c;正逐步改变着 CAD 市场长期由国外软件主导的格局。 国产CAD发展现状 …

JS scrollIntoView 技巧揭秘:解锁网页流畅交互

文章目录 一.基本概念二.语法和参数基本语法&#xff1a;element.scrollIntoView();参数详解&#xff1a; 三.应用场景和示例场景一&#xff1a;点击目录点位到相应的位置React 示例代码&#xff1a;Vue3 示例代码&#xff1a; 场景二&#xff1a;轮播图定位到指定图片示例代码…

从零开始搭建一个RESTful API(Node.js + Express)

随着Web开发的普及&#xff0c;RESTful API已经成为开发者在后端开发中的常见方式。RESTful API通过标准的HTTP方法&#xff08;GET、POST、PUT、DELETE&#xff09;实现客户端和服务器之间的通信&#xff0c;使得前后端开发能够解耦&#xff0c;前端可以通过API获取数据并进行…

ip属地功能有什么作用?自己的ip属地哪里看

虽然现在各大平台纷纷推出了IP属地功能。但是很多小伙伴还是不太了解&#xff0c;为什么要开启这个功能&#xff0c;那么&#xff0c;IP属地功能究竟有哪些作用&#xff1f;又该如何查看自己的IP属地信息呢&#xff1f;本文将为您一一解答。 一、IP属地功能有什么作用 ‌IP属地…

element plus 使用 el-tree 组件设置默认选中和获取所有选中节点id

1. 设置默认选中&#xff1a; 使用 default-checked-keys 属性&#xff0c;设置默认要选中的节点&#xff0c;以数组形式&#xff0c;如下&#xff1a; <el-treeref"treeRef":data"data"show-checkboxnode-key"id":props"defaultProps…