【音视频 | wav】wav音频文件格式详解——包含RIFF规范、完整的各个块解析、PCM转wav代码
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍wav音频格式🍭
😎金句分享😎:🍭子曰:父母在,不远游,游必有方。 ——《论语·里仁篇》。意思是,父母还健在时,就不要远离他们,如果一定要出远门,也必须告知自己所去的地方。🍭
文章未经允许,不许转载 !!!
目录
- 🎄一、概述
- 🎄二、RIFF 规范
- ✨2.1 RIFF 介绍
- ✨2.2 RIFF 文件结构
- 🎈2.2.1 RIFF 块
- 🎈2.2.2 LIST 块
- ✨2.3 FourCC
- 🎄三、wav 文件详解
- ✨3.1 wav 文件结构
- ✨3.2 wav 文件的编码格式
- 🎄四、PCM 转 WAV 的C语言程序
- 🎄五、总结
🎄一、概述
WAV全称是
Waveform Audio File Format
,是一种常用的无损音频文件格式,它最初由微软和IBM于1991年共同开发,并成为Windows操作系统中音频文件的标准格式之一。从文件结构来讲,WAV文件格式是微软存储多媒体文件的RIFF
规范的子集。本文将详细介绍WAV格式文件的文件结构。
WAV格式文件相对于其他音频文件格式具有以下特点:
- 无损压缩:WAV文件采用无损压缩算法,不会丢失原始音频数据,能够保留音频的高质量。
- 高音质:由于无损压缩技术的使用,WAV文件通常具有较高的音质和更好的还原性能。
- 大文件大小:由于不进行任何压缩,WAV文件相对于其他压缩格式(如MP3)的文件大小较大,占用存储空间较多。
- 支持多种采样率和位深度:WAV文件支持多种采样率和位深度,可以根据需求选择合适的参数进行录制或处理。
- 广泛兼容性:WAV格式是一种通用的音频文件格式,几乎所有的音频软件和硬件设备都能够支持读取和播放WAV文件。
原文链接:https://blog.csdn.net/wkd_007/article/details/134125746
🎄二、RIFF 规范
WAV 文件采用RIFF
规范来存储音频数据和相关元信息。这小节我们先了解RIFF
规范。
✨2.1 RIFF 介绍
RIFF(Resource Interchange File Format)是一种通用的文件格式规范,最初由微软开发,用于在不同应用程序之间交换数据。它以分块的方式组织数据,每个块包含一个标识符和相应的数据内容。
能以RIFF格式存储的数据有:
.AVI
:音频视频交错格式数据.WAV
:波形格式数据.RDI
:位图数据格式.RMI
:MIDI格式数据.PAL
:调色板格式.RMN
:多媒体电影.ANI
:动画光标.BND
:其他的RIFF文件
✨2.2 RIFF 文件结构
RIFF文件都是由一个或多个块(chunk)组成的,且第一个块必须是RIFF
块。
常见的块有:RIFF
、LIST
、fmt
、data
,每个块都包含了Id(块标志)、Size(块大小)、data(块数据)。其中,RIFF
块、LIST
块可以包含其他子块。
🎈2.2.1 RIFF 块
RIFF规范的文件的第一个块必须是RIFF块,RIFF块前面12个字节是RIFF块描述,包含了块标志、块大小、块类型。接下去的数据就是子块(Subchunk),RIFF的块类型决定了有多少个子块,有哪些子块。
🎈2.2.2 LIST 块
LIST
块可能比较少见,这里大概了解一下,下图是包含LIST
块的RIFF文件,首先是RIFF文件必须的RIFF chunk
,其数据域又包含有两个subchunk
,其中一个subchunk
的类型为LIST
,该LIST chunk
又包含了两个subchunk
。
✨2.3 FourCC
FourCC 全称为Four-Character Codes
,是一个4字节32位的标识符,通常用来标识文件的数据格式。RIFF文件的块标志就是使用了 FourCC 。FourCC是4个ASCII字符,不足四个字符的则在最后补充空格(不是空字符)。比如,FourCC fmt,实际上是'f'、'm'、't'、' '
。
C语言中,可以用宏来生成FourCC:
#define MAKE_FOURCC(a,b,c,d) \
( ((uint32_t)d) | ( ((uint32_t)c) << 8 ) | ( ((uint32_t)b) << 16 ) | ( ((uint32_t)a) << 24 ) )
🎄三、wav 文件详解
✨3.1 wav 文件结构
WAV文件通常是一个
RIFF
文件,如果数据是没压缩的PCM,则整个文件可以看出44个字节的文件头
+音频数据
构成。如果是压缩的音频数据,接着看下面小节细说。
wav文件(PCM数据)分为三个部分,如下图:
RIFF
块描述(下图紫色部分);- 指定数据格式的子块——
fmt
块(下图绿色部分)、- 包含实际样本数据的子块——
data
块(下图砖红色部分)。
下面是各个块详细的解释,有些块在pcm数据中是用不到的:
RIFF
块描述:
- 1、ChunkID:包含ASCII格式的字母
RIFF
;
- 2、ChunkSize:这个数值
ChunkSize
后面所有数据的大小。可以是整个文件的大小减去8个字节
;也可以是36+SubChunk2Size
;还可以是4 + (8+SubChunk1Size) + (8+SubChunk2Size)
;
- 3、Format:包含字母
WAVE
fmt
块:
- Subchunk1ID:包含字母
fmt
,表示fmt
块;
- Subchunk1Size:这个数值是
Subchunk1Size
后所有fmt
块数据的大小,对于PCM数据来说,这个值固定为16;
- AudioFormat:如果音频数据是PCM,这个值为
1
。1
以外的值表示一些压缩形式;
- NumChannels:声道数,Mono = 1, Stereo = 2 等等;
- SampleRate:采样率,8000,44100,48000 等;
- ByteRate:每秒的字节数,
采样率 * 声道数 * 样本位数 / 8
;
- BlockAlign:每个声道取一个样本的字节数之和,
声道数 * 样本位数 / 8
;
- BitsPerSample:样本位数,每个样本占用的bit位个数。8bit、16bit 等等。
- ExtraParamSize:拓展参数大小,如果是PCM,则不存在;
- ExtraParams:拓展参数数据;
fact
块 (可选),如果是没压缩的PCM,则没有这个块
- id:FOURCC 值为
'f' 'a' 'c' 't'
,4个字节
- size:数据域的长度,4个字节(最小值为4)
- Data:采样总数 4字节
data
块:
- Subchunk2ID:包含字母
data
,表示data
块;
- Subchunk2Size:这个数值是
Subchunk2Size
后所有数据的字节数,也就是实际音频数据的总字节数。
- Data:实际的音频数据;
✨3.2 wav 文件的编码格式
大部分的wav文件的编码格式都是PCM的,但也存在其他编码格式,不同的编码格式,其文件结构会有区别,下表列出了常见编码格式和wav文件结构的区别:
格式编码 | 格式名称 | fmt块长度 | fact 块 |
---|---|---|---|
0x01 | PCM / 非压缩格式 | 16 | |
0x02 | Microsoft ADPCM | 18 | √ |
0x03 | IEEE float | 18 | √ |
0x06 | ITU G.711 a-law | 18 | √ |
0x07 | ITU G.711 μ-law | 18 | √ |
0x031 | GSM 6.10 | 20 | √ |
0x040 | ITU G.721 ADPCM | √ | |
0xFFFE | 见子格式块中的编码格式 | 40 |
🎄四、PCM 转 WAV 的C语言程序
// pcm2wac.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*** Convert PCM16LE raw data to WAVE format* @param pcmpath Input PCM file.* @param channels Channel number of PCM file.* @param sample_rate Sample rate of PCM file.* @param wavepath Output WAVE file.*/
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{typedef struct WAVE_HEADER{ char fccID[4]; unsigned int dwSize; char fccType[4]; }WAVE_HEADER; typedef struct WAVE_FMT{ char fccID[4]; unsigned int dwSize; unsigned short wFormatTag; unsigned short wChannels; unsigned int dwSamplesPerSec; unsigned int dwAvgBytesPerSec; unsigned short wBlockAlign; unsigned short uiBitsPerSample; }WAVE_FMT; typedef struct WAVE_DATA{ char fccID[4]; unsigned int dwSize; }WAVE_DATA; if(channels==0||sample_rate==0){channels = 2;sample_rate = 44100;}int bits = 16;WAVE_HEADER pcmHEADER; WAVE_FMT pcmFMT; WAVE_DATA pcmDATA; unsigned short m_pcmData;FILE *fp,*fpout; fp=fopen(pcmpath, "rb");if(fp == NULL) { printf("open pcm file error\n");return -1; }fpout=fopen(wavepath, "wb+");if(fpout == NULL) { printf("create wav file error\n"); return -1; } //WAVE_HEADERmemcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF")); memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE")); fseek(fpout,sizeof(WAVE_HEADER),1); //WAVE_FMTpcmFMT.dwSamplesPerSec=sample_rate; pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData); pcmFMT.uiBitsPerSample=bits;memcpy(pcmFMT.fccID,"fmt ",strlen("fmt ")); pcmFMT.dwSize=16; pcmFMT.wBlockAlign=2; pcmFMT.wChannels=channels; pcmFMT.wFormatTag=1; fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout); //WAVE_DATA;memcpy(pcmDATA.fccID,"data",strlen("data")); pcmDATA.dwSize=0;fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);fread(&m_pcmData,sizeof(unsigned short),1,fp);while(!feof(fp)){ pcmDATA.dwSize+=2;fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);fread(&m_pcmData,sizeof(unsigned short),1,fp);} pcmHEADER.dwSize=44+pcmDATA.dwSize;rewind(fpout);fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);fclose(fp);fclose(fpout);return 0;
}int main()
{simplest_pcm16le_to_wave("48000Hz-s16le-2ch-ChengDu.pcm",2,48000,"output_nocturne.wav");return 0;
}
代码来自:https://blog.csdn.net/leixiaohua1020/article/details/50534316
🎄五、总结
本文详细介绍wav音频文件的结构,包含RIFF规范、完整的各个块解析、以及提供了pcm转wav的C语言代码。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
参考资料:
WAVE PCM soundfile format
视音频数据处理入门:PCM音频采样数据处理
wav头文件解析
RIFF和WAVE音频文件格式
音频——WAV 格式详解
https://blog.csdn.net/jackailson/article/details/105183413
相关文章:

【音视频 | wav】wav音频文件格式详解——包含RIFF规范、完整的各个块解析、PCM转wav代码
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...

人工智能基础_机器学习012_手写梯度下降代码演示_手动写代码完成梯度下降_并实现梯度下降可视化---人工智能工作笔记0052
可以看到上面我们那个公式,现在我们用梯度下降实现一下,比如我们有一堆数据,但是没有方程的情况下,我们来看一下如果计算,对应的w值也就是seta值对吧,没有方程我们可以使用梯度下降 这里首先我们可以设置一个0.0001.我们知道梯度下降的公式, 梯度下降刚开始的时候,下降会快,然…...

Docker安装部署[8.x]版本Elasticsearch+Kibana+IK分词器
文章目录 Docker安装部署elasticsearch拉取镜像创建数据卷创建网络elasticsearch容器,启动!踩坑:虚拟机磁盘扩容 Docker安装部署Kibana拉取镜像Kibana容器,启动! 安装IK分词器安装方式一:直接从github上下载…...

折纸达珠峰高度(forwhile循环)
对折0.1mm厚度的纸张多少次,高度可达珠峰高度8848180mm。 (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅…...
探索网络攻防技术:自学之道
在当今数字化时代,网络攻防技术的重要性日益凸显。无论是个人用户还是企业组织,都需要具备一定的网络安全意识和基本技能来应对日益复杂的网络威胁。自学网络攻防技术成为许多人的选择,今天我们将探讨如何高效、有序地自学网络攻防技术。 如果…...

图像二值化阈值调整——cv2.threshold方法
二值化阈值调整:调整是指在进行图像二值化处理时,调整阈值的过程。阈值决定了将图像中的像素分为黑色和白色的界限,大于阈值的像素被设置为白色,小于等于阈值的像素被设置为黑色。 方法一: 取阈值为 127,…...
【C++代码】背包问题,完全背包,多重背包,打家劫舍,动态规划--代码随想录
爬楼梯(plus) 一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢? 1阶,2阶,… m阶就是物品,楼顶就是背包。每一阶可以重复使用,例如…...
阿里云创始人王坚:云计算和GPT的关系,就是电和电机的关系
10月31日,在2023云栖大会,中国工程院院士、阿里云创始人王坚以《云计算的第三次浪潮》为主题发表演讲,他认为人工智能和云计算的结合,带来云计算的第三次浪潮,它不会在一年、两年完成,它可能会给我们十年、…...

python爬取豆瓣电影Top250数据
本次爬虫案例使用Python语言编写,使用了requests库进行网页请求,使用了BeautifulSoup库进行网页解析,使用了openpyxl库进行数据的保存。 案例中的爬虫目标是豆瓣电影Top250,通过循环访问不同页面进行数据的爬取。在每个页面上&am…...

关键路径及关键路径算法[C/C++]
文章目录 关键路径引例AOE网关键路径与关键活动关键路径算法引例与原理关键路径算法的实现边的存储结构代码实现运行示例 关键路径 关于拓扑排序的内容见拓扑排序详解 引例 通过拓扑排序我们可以解决一个工程是否可以顺序进行的问题,拓扑排序把一个工程分成了若干…...
nginx http 跳转到https
改 Nginx 配置文件 在您安装了 SSL 证书之后,您需要修改 Nginx 的配置文件以启用 HTTPS 和 HTTP 自动跳转 HTTPS。 打开 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf),找到您的网站配置块。在该配置块中添加以下内容&#x…...

可靠的互联网兼职平台,平常可以做副业充实生活
在互联网时代,越来越多的人开始通过网络来寻找兼职副业的机会,能够更灵活地安排自己的时间,实现自己的收入增值。那么找到一个正规可靠的线上兼职平台就是一个比较重要的事情,这里分享几个正规靠谱的线上兼职副业平台,…...

云安全—K8s APi Server 6443 攻击面
0x00 前言 在未授权的一文中,详细描述了k8s api中的8080端口未授权的问题,那么本篇主要来说6443端口的利用。 0x01 API连接攻击面 1.匿名用户访问 匿名开放方式:kubectl create clusterrolebinding cluster-system-anonymous --clusterro…...

【案例实战】NodeJS+Vue3+MySQL实现列表查询功能
这篇文章,给大家带来一个列表查询的功能,从前端到后端的一个综合案例实战。 采用vue3作为前端开发,nodejs作为后端开发。 首先我们先来看一下完成的页面效果。点击分页,可以切换到上一页、下一页。搜索框可以进行模糊查询。 后端…...

Google play开发者账号被封的几种常见原因及相关解决思路
在Google paly上,每天都有大量的应用被成功发布,同时也有很多开发者账号被封禁。特别是在今年的十月份之前,谷歌的"封号潮"给很多开发者带来了沉重的打击。不过,令人欣慰的是,自十月份之后,情况逐…...

深入理解计算机系统CS213学习笔记
Lecture 01 1. 计算机表示数字 int 整数运算可能会出现错误,超过32位时会出现溢出。 float 浮点数不适用结合律,因为浮点数表示的精度有限。 根其原因,是用有限的位数表示无限的数字空间。 2.利用分层的存储系统,使程序运行更…...

【设计模式】第8节:结构型模式之“适配器模式”
一、简介 适配器模式是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。 适配器模式角色: 请求者client:调用服务的角色目标Target:定义了Client要使用的功…...

Stable Diffusion WebUI扩展openpose-editor如何使用
先上地址: GitHub - fkunn1326/openpose-editor: Openpose Editor for AUTOMATIC1111s stable-diffusion-webuiOpenpose Editor for AUTOMATIC1111s stable-diffusion-webui - GitHub - fkunn1326/openpose-editor: Openpose Editor for AUTOMATIC1111s stable-diffusion-webu…...

企业网络带宽使用情况检查技巧
想要提高网络性能的企业通常会考虑限制对占用带宽的应用程序(如社交媒体和视频流应用程序)的访问,但对于那些真正需要获得高效网络的人来说,这还不够,您需要定期跟踪带宽使用情况。 虽然有许多工具可以帮助您检查网络…...

C/C++笔试易错与高频题型图解知识点(三)——数据结构部分(持续更新中)
目录 1. 排序 1.1 冒泡排序的改进 2. 二叉树 2.1 二叉树的性质 3. 栈 & 队列 3.1 循环队列 3.2 链式队列 4. 平衡二叉搜索树——AVL树、红黑树 5 优先级队列(堆) 1. 排序 1.1 冒泡排序的改进 下面的排序方法中,关键字比较次数与记录的初…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...