【音视频 | 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 冒泡排序的改进 下面的排序方法中,关键字比较次数与记录的初…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...