/*****************************************************************************************************************/
声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创,转载or引用请注明出处,谢谢!
创作不易,如果文章对你有帮助,麻烦点赞 收藏支持~感谢
/*****************************************************************************************************************/
tinyalsa中可以直接传输的是wav文件格式,无论是tinycap还是tinyplay其使用的都是wav文件格式,想要对tinyalsa源码有更详细的了解,需要熟悉wav格式的文件内容。
在安卓音频中常见的两种格式为pcm格式和wav格式。本文分析这两种格式。
以录音为例说明:
音频驱动传输的数据一般都是原始数据,是由硬件处理得到的一系列数字信号(即由ADC得到的原始数据)。其本身不会包含对声音信息的记录,比如声道数、采样率、位深等等。故此如果你用音乐播放器播放pcm格式的音频文件的时候,就需要指定这个文件的声道数、采样率、位深等等信息。
那么能不能将音频的信息存储在音频文件中,让播放器去读取音频文件的时候,可以顺便读取到音频格式的信息呢?这样就不用每次播放都需要去指定音频格式了。
有的,那就是mp3、wav、aac等等音频格式,其会保存音频的信息(采样率、声道数、位深等信息),当播放器播放的时候,会在文件的指定位置读取音频信息去播放,这样就不用用户去指定音频的信息了,直接点击播放按钮,剩下的就交给软件处理就能让设备发出声音了!
简单理解,wav格式文件内容 = pcm格式文件内容 + 音频描述内容。
那为什么不用mp3或者aac格式或者其它格式?因为类似mp3和aac格式是有损且压缩的格式,不仅会丢掉一部分原始音频数据,还要需要编解码(解压 /压缩)处理。
那为什么不用其它无损且不压缩就好了?因为用了其它无损不压缩的格式,你又会问为啥不用wav,是伪逻辑。
如前面分析: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格式文件内容 = 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 | 实际的声音数据。 |
以霉霉的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。读者要实际根据想要的目标文件或者源文件的参数进行配置。