【音频】WAV 格式详解

news/2024/10/27 21:11:36/

文章目录

  • WAV 文件格式解析
    • 概述
    • 块解析
      • RIFF chunk
      • fmt chunk
      • data chunk
    • 示例分析
    • 代码解析

WAV 文件格式解析

概述

wav 文件支持多种不同的比特率、采样率、多声道音频。

WAV 文件格式是 Microsoft 的 RIFF 规范的一个子集,用于存储多媒体文件。RIFF(resource interchange file format 资源互换文件格式,以 chunk(块) 为单位组织文件)格式文件。在 windows 上,大部分多媒体文件都是 RIFF 文件。wav 文件由若干个 RIFF chunk 构成,分别为: RIFF WAVE Chunk,Format Chunk,Fact Chunk(可选),Data Chunk。另外,文件中还可能包含一些可选的区块,如:Fact chunk、Cue points chunk、Playlist chunk、Associated data list chunk 等。具体格式如下:

请添加图片描述

块解析

wav 文件都是由 chunk 组成,chunk 的格式如下

size内容含义
4 bytesID如:RIFF,fmt,data
4 byteschund size如标准的 fmt chunk 为 16 字节
N bytesdatachunk 的内容

RIFF chunk

typedef struct
{char ChunkID[4]; //'R','I','F','F'unsigned int ChunkSize;char Format[4];  //'W','A','V','E'
}riff_chunk;
size内容含义
4 bytesChunkIDRIFF
4 bytesChunkSize从下一个字段首地址开始到文件末尾的总字节数。该字段的数值加 8 为当前文件的实际长度
4 bytesFormatWAVE

其中 ChunkSize 代表的是整个 file_size 的大小减去 ChunkID 和 ChunkSize 的大小,即 file_size=ChunkSize+8。

fmt chunk

typedef struct
{char FmtID[4];unsigned int FmtSize;unsigned short FmtTag;unsigned short FmtChannels;unsigned int SampleRate;unsigned int ByteRate;unsigned short BlockAilgn;unsigned short BitsPerSample;
}fmt_chunk;
size内容含义
4 bytesFmtIDfmt
4 bytesFmtSizefmt chunk 的大小,一般有 16/18/20/22/40 字节 (也有超过 40 字节的情况,如果不知道后面部分的含义,直接跳过即可),超过 16 字节部分为扩展块
4 bytesFmtTag编码格式代码,其值见下 常见编码格式 表,如果上述取值为 16,则此值通常为 1,代表该音频的编码方式是 PCM 编码
4 bytesFmtChannels声道数目,1 代表单声道,2 代表双声道
4 bytesSampleRate采样频率,8/11.025/12/16/22.05/24/32/44.1/48/64/88.2/96/176.4/192 kHZ
4 bytesByteRate传输速率,每秒的字节数,计算公式为:SampleRate * FmtChannels * BitsPerSample/8
4 bytesBlockAilgn块对齐,告知播放软件一次性需处理多少字节,公式为: BitsPerSample*FmtChannels/8
4 bytesBitsPerSample采样位数,一般有8/16/24/32/64,值越大,对声音的还原度越高

常见编码格式

格式编码格式名称fmt 块长度fact 块
0x01PCM / 非压缩格式16
0x02Microsoft ADPCM18
0x03IEEE float18
0x06ITU G.711 a-law18
0x07ITU G.711 μ-law18
0x031GSM 6.1020
0x040ITU G.721 ADPCM
0xFFFE见子格式块中的编码格式40

data chunk

struct DATA_CHUNK
{char DataID[4]; //'d','a','t','a'unsigned int DataSize;
};
size内容含义
4 bytesDataIDdata
4 bytesDataSize原始音频数据的大小

示例分析

Linux 平台下使用 mediainfo 分析 wav 文件

安装

 sudo apt-get install mediainfo

解析

执行命令:mediainfo test.wavGeneral
Complete name                            : test.wav
Format                                   : Wave
File size                                : 1.35 MiB
Duration                                 : 8 s 0 ms
Overall bit rate mode                    : Constant
Overall bit rate                         : 1 411 kb/sAudio
Format                                   : PCM
Format settings                          : Little / Signed
Codec ID                                 : 1
Duration                                 : 8 s 0 ms
Bit rate mode                            : Constant
Bit rate                                 : 1 411.2 kb/s
Channel(s)                               : 2 channels
Sampling rate                            : 44.1 kHz
Bit depth                                : 16 bits
Stream size                              : 1.35 MiB (100%)

查看文件大小

 ls test.wav -l
-rw-rw-r-- 1 tyustli tyustli 1411248 729 15:03 test.wav

hd 工具查看原始数据

hd test.wav -n 128
00000000  52 49 46 46 a8 88 15 00  57 41 56 45 66 6d 74 20  |RIFF....WAVEfmt |
00000010  10 00 00 00 01 00 02 00  44 ac 00 00 10 b1 02 00  |........D.......|
00000020  04 00 10 00 64 61 74 61  84 88 15 00 0e fc fa fe  |....data........|
00000030  6c fb 8a fe c2 fa 19 fe  1e fa b5 fd 85 f9 64 fd  |l.............d.|
00000040  f5 f8 20 fd 73 f8 df fc  09 f8 92 fc bb f7 28 fc  |.. .s.........(.|
00000050  83 f7 9d fb 5f f7 fe fa  46 f7 55 fa 2e f7 a3 f9  |...._...F.U.....|
00000060  23 f7 fa f8 36 f7 6b f8  57 f7 ef f7 84 f7 83 f7  |#...6.k.W.......|
00000070  c7 f7 2d f7 1e f8 eb f6  88 f8 c3 f6 0b f9 c5 f6  |..-.............|
  • 52 49 46 46:对应的 ASCII 字符为:RIFF
  • a8 88 15 00:ChunkSize,对应的十六进制是 0x1588a8=1411240 +8 和上面的文件大小一致
  • 57 41 56 45:对应的 ASCII 字符为 WAVE
  • 66 6d 74 20:对应的 ASCII 字符为 fmt
  • 10 00 00 00:FmtSize 0x10=16 代表PCM编码方式
  • 01 00:对应为1,代表PCM编码方式
  • 02 00:通道个数,通道数为2
  • 44 ac 00 00:采样频率 0xac44=44100=44.1KHz
  • 10 b1 02 00:每秒所需的字节数,转化为十六进制为: 0x2b110=176400 通过此值可以计算该音频的时长:1411240/176400 = 8s
  • 04 00:数据对齐单位
  • 10 00:采样位数 0x10=16
  • 64 61 74 61:对应的 ASCII 字符为 data
  • 84 88 15 00:对应该音频的raw数据的大小,转化为十六进制为 0x158884=1411204,此值等于 1411248-44

代码解析

/** Change Logs:* Date           Author       Notes* 2022-08-26     tyustli      first version*/#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>typedef struct {char ChunkID[4]; //'R','I','F','F'unsigned int ChunkSize;char Format[4]; //'W','A','V','E'
} riff_chunk;typedef struct {char FmtID[4];unsigned int FmtSize;unsigned short FmtTag;unsigned short FmtChannels;unsigned int SampleRate;unsigned int ByteRate;unsigned short BlockAilgn;unsigned short BitsPerSample;
} fmt_chunk;typedef struct {char DataID[4]; //'d','a','t','a'unsigned int DataSize;
} data_chunk;typedef struct {riff_chunk riff_region;fmt_chunk fmt_region;data_chunk data_region;
} wav_struct;static void *map_file(const char *path);
static void data_dump(wav_struct *data);int main(int argc, char *argv[]) {assert(sizeof(wav_struct) == 44); /* defensive */if (argc < 2) {printf("usage: %s file_path\r\n", argv[0]);exit(-1);}/* map file */wav_struct *map_data = map_file(argv[1]);/* data dump */data_dump(map_data);/* munmap file */munmap(map_data, map_data->riff_region.ChunkSize + 8);return 1;
}static void *map_file(const char *path) {assert(path != NULL);int fd = open(path, O_RDWR);if (fd == -1) {goto __release;}#if 0off_t size = lseek(fd, 0, SEEK_END);if (size == -1) {goto __release;}
#endif/* get file size */struct stat stat;int ret = fstat(fd, &stat);if (ret == -1) {goto __release;}size_t size = stat.st_size;/* map file */void *file_data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);if(file_data == (void *)-1) {goto __release;}close(fd);return file_data;/* error handle */
__release:perror("map file");if (fd > 0) {close(fd);}exit(1);
}static void data_dump(wav_struct *data) {/* riff chunkid */printf("riff chunk id          :");for(int i = 0; i < 4; i++) {printf("%c", data->riff_region.ChunkID[i]);}printf("\r\n");/* file size */printf("wav file size          :%d\r\n", data->riff_region.ChunkSize + 8);/* riff Format */printf("riff format id         :");for(int i = 0; i < 4; i++) {printf("%c", data->riff_region.Format[i]);}printf("\r\n");/* fmt chunkid */printf("fmt chunk id           :");for(int i = 0; i < 4; i++) {printf("%c", data->fmt_region.FmtID[i]);}printf("\r\n");printf("FmtChannels            :%d(1 单声道, 2 双声道)\r\n", data->fmt_region.FmtChannels);printf("FmtTag                 :%d(1 PCM 编码)\r\n", data->fmt_region.FmtTag);printf("SampleRate             :%d\r\n", data->fmt_region.SampleRate);printf("ByteRate               :%d\r\n", data->fmt_region.ByteRate);printf("BitsPerSample          :%d\r\n", data->fmt_region.BitsPerSample);/* data chunkid */printf("fmt chunk id           :");for(int i = 0; i < 4; i++) {printf("%c", data->data_region.DataID[i]);}printf("\r\n");
}
/*** 编译:gcc wav_parse.c* 运行:./a.out sample.wav* 结果:* riff chunk id          :RIFF* wav file size          :497904* riff format id         :WAVE* fmt chunk id           :fmt * FmtChannels            :2(1 单声道, 2 双声道)* FmtTag                 :1(1 PCM 编码)* SampleRate             :44100* ByteRate               :176400* BitsPerSample          :16* fmt chunk id           :data* 
*//*************** end of file ***************/

http://www.ppmy.cn/news/116639.html

相关文章

实听惠威M200MKII

想买一个好一点的书架式有源音响不是一天两天了。比较来比较去&#xff0c;最后还是把M200MKII买回家中。听了两天&#xff0c;感觉好极了。 首先是好听&#xff01;声音还原确实超好&#xff0c;不管是美国乡村摇滚&#xff0c;还是腾格尔、蔡琴和韩红&#xff0c;从前那种感…

音频功放PA

D类 D类功放接收模拟音频信号&#xff0c;用内部三角波发生器产生的三角波和它进行比较&#xff0c;其结果就是一个脉宽调制信号&#xff08;PWM&#xff09;&#xff0c;然后将PWM信号放大并还原成模拟音频信号。因此&#xff0c;D类功放是用脉冲宽度对模拟音频幅度进行模拟的…

A100 Jeston TX1TX2使用教程-接口说明

EdgeBox_Umate_A100是一款嵌入式人工智能计算机&#xff0c;能够为各类终端设备赋予人工智能的能力&#xff0c;降低终端智能的开发门槛。EdgeBox_Umate_A100搭载了移动处理器——NVIDIA Jetson TX1&#xff0c;并且兼容TX2&#xff0c;是最适合边缘计算的高性能平台。 A100 算…

泰克示波器MD03012-一款高性能、高可靠性的仪器

泰克示波器MD03012是一款常见的仪器&#xff0c;以其出色的性能和高可靠性被广泛应用于电子工程、教学演示等领域。它采用先进的电子技术&#xff0c;具有高精度、高灵敏度和高可靠性等特点&#xff0c;能够满足工程师们在实际工作中的要求。 泰克示波器MD03012拥有一套强大的功…

Hi3516E V200功能介绍

Hi3516EV200 作为新一代行业专用HD IP 摄像机SOC&#xff0c;集成新一代ISP 以及业界最新的H265视频压缩编码器&#xff0c;同时采用先进低功耗工艺和低功耗架构设计&#xff0c;使得Hi3516EV200 在低码率、高画质、低功耗等方面引领行业水平。集成POR、RTC、Audio Codec&#…

HT366 具有防破音功能的2×20W立体声D类音频功放IC

概述 HT366是一款高效D类音频功率放大器。 在14V供电的立体声&#xff08;BTL&#xff09;模式、THDN10% 条件下&#xff0c;能够持续提供2*20W/4Ω功率输出&#xff1b;在单声道&#xff08;PBTL&#xff09;、模式、THDN10%条件下&#xff0c;能够持续提供34W/4Ω功率输出。 …

HT513 I2S输入2.8W单声道D类音频功放IC

概述 HT513是一款低成本的I2S输入单声道输出D类 音频功率放大器。其在5V供电时可提供最大 2.8W的输出功率; 在6.5V供电时可提供最大 4.7W的输出功率。 HT513内部集成了DA转换器&#xff0c;其I2S输入最大 支持32-bit字节&#xff0c;并且可自动监测采样频率&#xff0c;最 高支…

关于Hi3531D V200 与V100差异的评估

V200 CPU 升级 ARM Cortex A53四核1.15GHz 取消 MPEG-4 SP&#xff0c;L0~L3/ASP L0~L5 解码 编解码性能没有变化 仍 1080P下 8编8解 支持 七种码率控制模式 输出码率最高20Mbps 支持 神经网络推理引擎&#xff08;NNIE&#xff09; 智能视觉引擎&#xff08;IVE&#xf…