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

ops/2025/1/14 0:31:57/

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

相关文章

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…

实战篇: BiLSTM+CRF实现中文分词

中文分词是自然语言处理&#xff08;NLP&#xff09;领域中的基础任务之一&#xff0c;它将一段连续的中文字符切分为词汇单元&#xff0c;为后续的情感分析、机器翻译等任务提供输入。在传统方法中&#xff0c;基于规则的分词方法受限于语言多样性&#xff0c;而统计方法中的隐…

【Vue】MacOS从0开始创建一个前端Vue项目并集成AntDesignVue

文章目录 环境安装创建vue项目vue项目结构解读集成AntDesignVue 环境安装 nodejs环境下载&#xff1a;https://nodejs.org/zh-cn&#xff0c;从官网下载后直接安装即可&#xff0c;通过下面命令判断是否安装成功&#xff1a; node -v npm -v如果有返回版本号就安装成功了。 …

2024 高级爬虫笔记(六)scrapy框架基础知识

目录 一、Scrapy框架基础知识1.1、什么是scrapy&#xff1f;1.2、scrapy的工作流程1.3、scrapy中每个模块的作用&#xff1a;1.4、scrapy的入门使用1.4.1 安装scrapy1.4.2、scrapy项目实现流程1.4.3、创建scrapy项目1.4.4、创建爬虫1.4.5、完善spider1.4.6、配置settings文件1.…

【Rust】结构体定义域实例化

目录 思维导图 1. 结构体的定义与实例化 1.1 结构体的基本概念 1.2 定义结构体 1.3 创建结构体实例 1.4 结构体的定义与实例化示例 2. 访问与修改结构体字段 2.1 访问字段 2.2 修改字段 3. 结构体实例的构造函数 3.1 构造函数的定义 3.2 使用字段初始化简写 4. 结…

RIP协议在简单网络架构的使用

目录 基本概念路由更新机制特点与局限性场景模拟 注意&#xff1a;本文的配置为上文《复杂园区网基本分支的构建》拓展&#xff0c;主要记录rip协议在简单网络架构的使用。 RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是一种基于距离向…

如何实现多级缓存?

本文重点说一说在Java应用中&#xff0c;多级缓存如何实现。 多级缓存是比较常见的一种性能优化的手段&#xff0c;一般来说就是本地缓存分布式缓存。 本地缓存一般采用Caffeine和Guava&#xff0c;这两种是性能比较高的本地缓存的框架。他们都提供了缓存的过期、管理等功能。…

nginx反向代理+缓存

1、nginx-LB配置页面缓存 [rootOldboy conf]# vi nginx.conf http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;include proxy.conf; …