【TinyALSA全解析(二)】wav和pcm音频文件格式详解

wav和pcm音频文件格式详解

/*****************************************************************************************************************/

声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创,转载or引用请注明出处,谢谢!

创作不易,如果文章对你有帮助,麻烦点赞 收藏支持~感谢

/*****************************************************************************************************************/

一、本文的目的

tinyalsa中可以直接传输的是wav文件格式,无论是tinycap还是tinyplay其使用的都是wav文件格式,想要对tinyalsa源码有更详细的了解,需要熟悉wav格式的文件内容。

在安卓音频中常见的两种格式为pcm格式和wav格式。本文分析这两种格式。

二、wav和pcm格式文件介绍

以录音为例说明:

音频驱动传输的数据一般都是原始数据,是由硬件处理得到的一系列数字信号(即由ADC得到的原始数据)。其本身不会包含对声音信息的记录,比如声道数、采样率、位深等等。故此如果你用音乐播放器播放pcm格式的音频文件的时候,就需要指定这个文件的声道数、采样率、位深等等信息。

那么能不能将音频的信息存储在音频文件中,让播放器去读取音频文件的时候,可以顺便读取到音频格式的信息呢?这样就不用每次播放都需要去指定音频格式了。

有的,那就是mp3、wav、aac等等音频格式,其会保存音频的信息(采样率、声道数、位深等信息),当播放器播放的时候,会在文件的指定位置读取音频信息去播放,这样就不用用户去指定音频的信息了,直接点击播放按钮,剩下的就交给软件处理就能让设备发出声音了!

简单理解,wav格式文件内容 = pcm格式文件内容 + 音频描述内容。

那为什么不用mp3或者aac格式或者其它格式?因为类似mp3和aac格式是有损且压缩的格式,不仅会丢掉一部分原始音频数据,还要需要编解码(解压 /压缩)处理。

那为什么不用其它无损且不压缩就好了?因为用了其它无损不压缩的格式,你又会问为啥不用wav,是伪逻辑。

三、pcm格式文件解析

如前面分析:pcm格式文件的内容是仅且包含音频原始数据的(原始就是未压缩未丢失的意思)。那么这个文件格式展开就是一系列的声音表示数据了。以某个PCM文件的片段数据"0x01 0x02 0x03 0x04"为例,假如地址是从低到高,不同的音频格式的声音内容如下表示:

音频格式\原始数据 0x01 0x02 0x03 0x04 0x...
8位单声道 0声道 0声道 0声道 0声道 0声道
8位双声道 左声道 右声道 左声道 右声道 左声道
16位单声道 0声道数据1-低字节 0声道数据1-高字节 0声道数据2-低字节 0声道数据2-高字节 0声道数据3-低字节
16位双声道 左声道数据1-低字节 左声道数据1-高字节 右声道数据1-告字节 右声道数据1-高字节 左声道数据2-低字节

四、wav文件内容解析

4.1 文件内容描述

如前面分析:wav格式文件内容 = pcm格式文件内容 + 音频描述内容

wav文件的格式是怎么样的呢?

可参考网站:http://soundfile.sapp.org/doc/WaveFormat/

文件内容的数据框图:

关于这张图的描述:

偏移与大小 名称 说明
0 4 ChunkID 包含 ASCII 形式的字母"RIFF"(0x52494646 大端形式)。
4 4 ChunkSize 36 + SubChunk2Size,或更准确地说:4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)这是此数字之后的块的其余部分的大小。这是整个文件的大小(以字节为单位)减去未包含在此计数中的两个字段的 8 字节:ChunkID 和 ChunkSize。
8 4 格式 包含字母"WAVE"(0x57415645 大端形式)。
12 4 Subchunk1ID 包含字母"fmt"(0x666d7420 大端格式)。
16 4 Subchunk1Size 16 用于 PCM。这是该数字之后的其余子块的大小。
20 2 AudioFormat PCM = 1(即线性量化)1 以外的值表示某种形式的压缩。
22 2 NumChannels Mono = 1、Stereo = 2 等
24 4 SampleRate 8000、44100 等
28 4 ByteRate == SampleRate * NumChannels * BitsPerSample/8
32 2 BlockAlign == NumChannels * BitsPerSample/8 1 的字节数样本包括所有通道。
34 2 BitsPerSample 8 位 = 8,16 位 = 16,等等
2 ExtraParamSize 如果是 PCM,则不存在
X ExtraParams 用于额外参数的空间
36 4 Subchunk2ID 包含字母"数据"(0x64617461 大端形式)。
40 4 Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 这是数据中的字节数。您还可以将其视为该数字后面的子块的读取大小。
44 * Data 实际的声音数据。

4.2 实战分析

以霉霉的stay歌曲为例分析,首先解析文件成二进制的格式,文件前面的部分的内容如下:

xxd -l 176  /d/music/stay.wav
00000000: 5249 4646 9a56 2f02 5741 5645 666d 7420  RIFF.V/.WAVEfmt
00000010: 1000 0000 0100 0200 44ac 0000 10b1 0200  ........D.......
00000020: 0400 1000 4c49 5354 6e00 0000 494e 464f  ....LISTn...INFO
00000030: 4941 5254 0d00 0000 5461 796c 6f72 2053  IART....Taylor S
00000040: 7769 6674 0000 494e 414d 2100 0000 5374  wift..INAM!...St
00000050: 6179 2053 7461 7920 5374 6179 2028 4b61  ay Stay Stay (Ka
00000060: 7261 6f6b 6520 5665 7273 696f 6e29 0000  raoke Version)..
00000070: 4950 5244 0c00 0000 5265 6420 4b61 7261  IPRD....Red Kara
00000080: 6f6b 6500 4953 4654 0e00 0000 4c61 7666  oke.ISFT....Lavf
00000090: 3539 2e33 342e 3130 3100 6461 7461 0056  59.34.101.data.V
000000a0: 2f02 0000 0000 0000 0000 0000 0000 0000  /...............

这个数据是自左向右,自上而下查看,对数据的分析如下:

5249 4646:这是 "RIFF" 的 ASCII 码的十六进制表示,表示这是一个 RIFF 文件格式。

9a56 2f02:这是文件大小字段,表示文件的大小(减去前8个字节)。

5741 5645:这是 "WAVE" 的 ASCII 码的十六进制表示,表示这是一个 WAVE 格式的音频文件。

666d 7420:这是 "fmt " 的 ASCII 码的十六进制表示,表示接下来是音频格式的子块。

1000 0000:这是子块的大小,值为16,表示接下来的16个字节描述音频格式。

0100:这是音频格式代码,值为1,表示这是 PCM 格式的音频。

0200:这是声道数,值为2,表示这是立体声音频。

44ac 0000:这是采样率,值为44100,表示每秒采样44100次。

10b1 0200:这是字节率,值为 176400,表示每秒数据的字节数。

0400:这是块对齐,值为4,表示每个采样包含的字节数。

1000:这是每个样本的位数,值为16,表示这是16位的音频。

接下来的部分包含了一些元数据,如艺术家名字(Taylor Swift)、歌曲名字(Stay Stay Stay (Karaoke Version))、产品名(Red Karaoke)和软件名(Lavf59.34.101)。

最后的 6461 7461 是 "data" 的 ASCII 码的十六进制表示,表示接下来是音频数据的子块。0056 2f02 是子块的大小,表示接下来的音频数据的大小。

接下来的 0000 是音频数据的开始部分,文件的后面的其它内容都是实际的声音数据了。

五、如何在各种音频格式之间进行转换

一般用FFmpeg软件进行转换,先在当前的设备安装好FFmpeg软件,然后用命令行就可以进行转换了,常用的示范如下:

将mp4视频提取wav格式:
ffmpeg -i D:\input.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 D:\output.wav

将wav格式转变为pcm格式:
ffmpeg -i D:\output.wav -f s16le -acodec pcm_s16le D:\output.pcm

将pcm格式转变为wav格式:
ffmpeg -f s16le -ar 44100 -ac 2 -i D:\output.pcm c:\output.wav

注意上面的命令中指定的采样率为44.1k ,双声道,存储格式是s16le。读者要实际根据想要的目标文件或者源文件的参数进行配置。

相关推荐
kaixin_learn_qt_ing9 分钟前
Linux export命令
linux
余额不足1213811 分钟前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
众拾达人12 分钟前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.14 分钟前
Mybatis-Plus
java·开发语言
不良人天码星14 分钟前
lombok插件不生效
java·开发语言·intellij-idea
冷曦_sole16 分钟前
linux-19 根文件系统(一)
linux·运维·服务器
AI大模型学徒18 分钟前
Linux(二)_清理空间
linux·运维·服务器
云川之下28 分钟前
【linux】 unshare -user -r /bin/bash命令详解
linux·bash·unshare
守护者17035 分钟前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
源码哥_博纳软云37 分钟前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台