WAVE 文件格式分析

article/2025/10/12 9:06:29

         WAVE 文件作为多媒体中使用的声音波形文件格式之一,它是以RIFF(Resource Interchange File Format)格式为标准的。每个WAVE文件的头四个字节便是“RIFF”。WAVE 文件由文件头和数据体两大部分组成。其中文件头又分为 RIFF/WAV 文件标识段和声音数据格式说明段两部分。WAVE文件各部分内容及格式见后文。

         常见的声音文件主要有两种,分别对应于单声道(11.025KHz 采样率、8Bit 的采样值)和双声道(44.1KHz 采样率、16Bit 的采样值)。采样率是指:声音信号在“模→数”转换过程中单位时间内采样的次数。采样值是指每一次采样周期 
内声音模拟信号的积分值。

         对于单声道声音文件,采样数据为八位的短整数(short int 00H-FFH);而对于双声道立体声声音文件,每次采样数据为一个16位的整数(int),高八位和低八位分别代表左右两个声道。

        WAVE 文件数据块包含以脉冲编码调制(PCM)格式表示的样本。WAVE 文件是由样本组织而成的。在单声道 WAVE 文件中,声道0代表左声道,声道1代表右声道。在多声道WAVE文件中,样本是交替出现的。

        WAVE 文件除了前面一小段文件头对数据组织进行说明之外,Data 块就是声音的原始采样数据,WAVE 文件虽然可以压缩,但一般都使用不压缩的格式。44.1KHz 采样率、16Bit的分辨率、双声道,所以WAVE可以保存音质要求非常高的声音文件,CD 采用的也是这种格式,声音方面的专家或是音乐发烧友们应该非常熟悉。但这种文件的体积也非常大,以 44.1KHz 16bit 双声道的数据为例,一分钟的声音数据量为:4100*2byte*2channel*60s/1024/1024=10.09M 。所以不合适在网上传送。

下面我们具体地分析 WAVE 文件的格式:

以下是对各个字段的详细解说:

对于Data块,根据声道数和采样率的不同情况:

下面我们看一个具体的例子,声音文件如下:

对应的分析如下图所示:

1.PCM Wave格式详解

WAVE文件格式是微软RIFF(Resource Interchange File Format,资源交换文件标准)的一种,是针对于多媒体文件存储的一种文件格式和标准。 一般而言,RIFF文件由文件头和数据两部分组成,一个WAVE文件由一个“WAVE”数据块组成,这个“WAVE”块又由一个”fmt”子数据块和一个“data”子 数据块组成,也称这种格式为“Canonical form”(权威/牧师格式),如下图所示:

“WAVE”格式由两个子数据块构成:“fmt”块和“data”块,其中“fmt”块的详细解释如下: Subchunk1ID: 占4个字节,内容为“fmt ”的ASCII码(0x666d7420),以大端存储。
Subchunk1Size: 占4个字节,存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节),以小端方式存储。
AudioFormat:占2个字节,以小端方式存储,存储音频文件的编码格式,例如若为PCM则其存储值为1,若为其他非PCM格式的则有一定的压缩。
NumChannels: 占2个字节,以小端方式存储,通道数,单通道(Mono)值为1,双通道(Stereo)值为2,等等。
SampleRate: 占4个字节,以小端方式存储,采样率,如8k,44.1k等。
ByteRate: 占4个字节,以小端方式存储,每秒存储的bit数,其值=SampleRate * NumChannels * BitsPerSample/8
BlockAlign: 占2个字节,以小端方式存储,块对齐大小,其值=NumChannels * BitsPerSample/8
BitsPerSample: 占2个字节,以小端方式存储,每个采样点的bit数,一般为8,16,32等。
接下来是两个可选的扩展参数:
ExtraParamSize: 占2个字节,表示扩展段的大小。
ExtraParams: 扩展段其他自定义的一些参数的具体内容,大小由前一个字段给定。

其中,对于每个采样点的bit数,不同的bit数读取数据的方式不同:

“WAVE”格式文件的第二个子数据块是“data”,其个字段的详细解释如下:
Subchunk2ID: 占4个字节,内容为“data”的ASCII码(0x64617461),以大端存储。
Subchunk2Size: 占4个字节,内容为接下来的正式的数据部分的字节数,其值=NumSamples * NumChannels * BitsPerSample/8
Data: 真正的语音数据部分。

一个Wave文件头的实例

设一个wave文件的前72个字节的十六进制内容如下(可以使用Ultra Edit等工具查看wave文件头):

则其个字段的解析如下图:

使用C语言文件操作库函数实现的Wave文件读取的实例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// define Wave format structure
typedef struct tWAVEFORMATEX
{short wFormatTag;         /* format type */short nChannels;          /* number of channels (i.e. mono, stereo...) */unsigned int nSamplesPerSec;     /* sample rate */unsigned int nAvgBytesPerSec;    /* for buffer estimation */short nBlockAlign;        /* block size of data */short wBitsPerSample;     /* number of bits per sample of mono data */short cbSize;             /* the count in bytes of the size of *//* extra information (after cbSize) */
} WAVEFORMATEX, *PWAVEFORMATEX;char* wavread(char *fname, WAVEFORMATEX *wf);int main(){char fname[] = "test.wav";char *speech;WAVEFORMATEX wf;speech = wavread(fname, &wf);// afterward processing...return 0;
}// read wave file
char* wavread(char *fname, WAVEFORMATEX *wf){FILE* fp;char str[32];char *speech;unsigned int subchunk1size; // head sizeunsigned int subchunk2size; // speech data size// check format typefp = fopen(fname,"r");if(!fp){fprintf(stderr,"Can not open the wave file: %s.\n",fname);return NULL;}fseek(fp, 8, SEEK_SET);fread(str, sizeof(char), 7, fp);str[7] = '\0';if(strcmp(str,"WAVEfmt")){fprintf(stderr,"The file is not in WAVE format!\n");return NULL;}// read format headerfseek(fp, 16, SEEK_SET);fread((unsigned int*)(&subchunk1size),4,1,fp);fseek(fp, 20, SEEK_SET);fread(wf, subchunk1size, 1, fp);// read wave datafseek(fp, 20+subchunk1size, SEEK_SET);fread(str, 1, 4, fp);str[4] = '\0';if(strcmp(str,"data")){fprintf(stderr,"Locating data start point failed!\n");return NULL;}fseek(fp, 20+subchunk1size+4, SEEK_SET);fread((unsigned int*)(&subchunk2size), 4, 1, fp);speech = (char*)malloc(sizeof(char)*subchunk2size);if(!speech){fprintf(stderr, "Memory alloc failed!\n");return NULL;}fseek(fp, 20+subchunk1size+8, SEEK_SET);fread(speech, 1, subchunk2size, fp);fclose(fp);return speech;
}

 


http://chatgpt.dhexx.cn/article/UDU5apv9.shtml

相关文章

html wave标签,html wave的实现

如何实现wave动画?求demo 我理解的关键点: 1、色彩的均匀渐变,比较柔和,没有明显的过渡层 2、不同频率的正弦波 我的实现: 效果相差很大! let canvas1 = document.querySelector(#canvas1); let ctx = canvas1.getContext(2d); canvas1.width = canvas1.parentNode.offset…

802.11ac Wave2 将为WIFI性能和效果带来提升

Wi-Fi联盟推出的第二代802.11ac认证项目&#xff0c;使Wi-Fi网络的速度和效率又向前迈了一大步。 802.11ac正式颁布于2014年&#xff0c;标准包含了很多新特性&#xff0c;这些特性受到了Wi-Fi供应商和消费者的欢迎&#xff0c;特性包括&#xff1a; 采用5GHz频段 更宽的通道 更…

802.11ac wave2的前世今生

2015年下半年&#xff0c;高通、博通、RTL等芯片厂商相继发布了满足802.11ac wave2要求的芯片&#xff0c;WLAN及终端厂商也迅速跟进推出相应的产品和终端。802.11ac wave2在多方推动下于2015年底实现了商用&#xff0c;标志着802.11ac进入了新的发展阶段。 突破多用户并发能力…

什么是Wi-Fi Wave 2?

802.11ac的第二波浪潮(即Wave 2)已经拍到了岸边&#xff0c;而新的MU-MIMO(多用户、多路输入多路输出)技术也正在引起业界的骚动。它正是我们已经看到的Wi-Fi的巨大潜力之一&#xff0c;可大大提升无线网络的吞吐量&#xff0c;并将在密度和容量上与之前的无线网络产生巨大差异…

什么是802.11ac和802.11ac Wave2

什么是802.11ac和802.11ac Wave2 简介什么是802.11ac802.11ac VS 802.11n802.11ac Wave1的关键技术802.11ac Wave2 VS 802.11ac Wave1802.11ac Wave2的关键特性 简介 从1997年第一代802.11标准802.11发布至今&#xff0c;Wi-Fi经历了巨大的发展和普及&#xff0c;802.11ac的推…

wave2lip训练

论文&#xff1a;https://arxiv.org/pdf/2008.10010.pdf 训练源码&#xff1a;https://github.com/Rudrabha/Wav2Lip 经过调整过的代码&#xff1a;https://gitee.com/sparkle__code__guy/wave2lip ffmpeg的安装&#xff1a;https://blog.csdn.net/sslfk/article/details/1…

802.11ac wave 2:你需要知道的6件事

Wi-Fi联盟是全球非盈利性组织&#xff0c;旨在改善Wi-Fi技术的互操作性。近日&#xff0c;Wi-Fi联盟认证了802.11ac wave 2标准&#xff0c;新标准带来了一系列的更新&#xff0c;最终可能会影响消费者及企业的日常连接。 下面让我们看看这六个性能变化&#xff1a; 1.可能实现…

被吹上天的802.11ac Wave2到底好在哪?还有,Wave1哪去了?

802.11ac Wave2到底好在哪&#xff1f; 在说Wave2之前&#xff0c;我们先要了解802.11ac是什么&#xff0c;它的特点是什么。IEEE 802.11ac是802.11的一个通信标准&#xff0c;802.11n的升级版。再具体的渊源这里就不讲了&#xff0c;感兴趣的可自行查阅资料。重点来了&#x…

Java拦截器HandlerInterceptor重写preHandle方法时HttpServletRequest无法获取自定义请求头参数问题

问题描述 在前端vue中设置的自定义请求头参数&#xff1a;token 控制层可以正常获取到自定义请求头参数 拦截器中无法获取 下方是拦截器代码 Component public class JWTInterceptor implements HandlerInterceptor {private final Logger logger LoggerFactory.getLogge…

为什么prehandle被调用两次

为什么prehandle被调用两次 今天我自己尝试写了个拦截器&#xff0c;意外发现这个拦截器执行了两次&#xff0c;查阅很多文章过后却还是没能解决问题。 网上提供的解决方法有&#xff1a;1、排除重复扫描原因&#xff0c;导致拦截器执行多次&#xff0c;2、排除xml重复导入&a…

spring过滤器中 preHandle方法获取方法中的requestParam参数

不想写了 直接截图 postman请求 接口 过滤器中 下面方法即可 request.getParameter(“token”);

SpringMVC拦截器仅调用preHandle()方法的解决办法

在学习SpringMVC拦截器时&#xff0c;想调用拦截器&#xff0c;但是只运行了preHandle()这个方法&#xff0c; 可见postHandle()&#xff0c;afterCompletion()以及发出请求的方法都没有被执行&#xff0c;原来是preHandle()的返回值忘记更改了。应该设置为true。preHandle()方…

Java框架(八)--SpringMVC拦截器(1)--拦截器开发流程、多Interceptor执行顺序及preHandle返回值

拦截器-Interceptor 拦截器&#xff08;Interceptor&#xff09;用于对URL请求进行前置/后置过滤。 Interceptor与Filter用途相似&#xff0c;但实现方式不同。 Interceptor为SpringMVC的标准组件。 Filter为J2EE的标准组件。 Interceptor底层就是基于Spring AOP面向切面编程实…

SpringMvc拦截器preHandle,postHandle,afterCompletion

目录 1.拦截器介绍 2.SpringMVC执行流程&#xff08; 内含拦截器执行流程 &#xff09; 3.拦截器类 4.拦截器preHandle,postHandle,afterCompletion preHandle postHnadle afterCompletion 1.拦截器介绍 SpringMVC中的Interceptor拦截器是非常重要的&#xff0c;他的作…

Interceptor的基本介绍和使用preHandle、postHandle与afterCompletion

目录 preHandlepostHandleafterCompletion项目测试代码项目测试 preHandle 调用时间&#xff1a;Controller方法处理之前 执行顺序&#xff1a;链式Intercepter情况下&#xff0c;Intercepter按照声明的顺序一个接一个执行 若返回false&#xff0c;则中断执行&#xff0c;注…

preHandle执行多次问题

首先说下我的问题吧&#xff0c;我是swagger测试多个接口&#xff0c;其他接口没有啥问题&#xff0c;但是就是查询第三方系统的接口一直请求多次&#xff0c;最后debug看了下第二次的请求路径&#xff0c;卧槽&#xff0c;这个不是别的系统的路径吗&#xff0c;瞬间明白了。 …

java 中prehandle,Spring MVC中拦截器HandlerInterceptorAdapter中的preHandle方法

拦截器&#xff1a;顾名思义&#xff0c;就是对请求进行拦截&#xff0c;做一些预处理、后处理或返回处理的操作 Spring MVC中使用拦截器的方法&#xff0c;继承HandlerInterceptorAdapter类&#xff0c;并根据需求实现其中的preHandle方法(预处理)、postHandle方法(返回处理)&…

HandlerInterceptor的preHandle、postHandle、afterCompletion方法的作用

public class MyHandlerInterceptor implements HandlerInterceptor { &#xff08;1&#xff09; preHandle方法是进行处理器拦截用的&#xff0c;顾名思义&#xff0c;该方法将在Controller处理之前进行调用。 SpringMVC中的Interceptor拦截器是链式的&#xff0c;可以同时…

SpringBoot——拦截器

符合条件的请求被放行&#xff0c;不符合条件的请求访问不到所请求的东西。 1、步骤 &#xff08;以登陆拦截器为例&#xff0c;只有用户登录了才能访问某页面&#xff09;&#xff1a; 1、编写拦截器&#xff0c;实现HandlerInterc此接口有三个方法 &#xff0c; preHandle…