语音文件的格式、字节计算、PCM头信息 2019-04-26

语音文件

PCM

我们在音频处理的时候经常会接触到PCM数据:它是模拟音频信号经模数转换(A/D变换)直接形成的二进制序列,该文件没有附加的文件头文件结束标志。

声音本身是模拟信号,而计算机只能识别数字信号,要在计算机中处理声音,就需要将声音数字化,这个过程叫经模数转换(A/D变换)。最常见的方式是透过脉冲编码调制PCM (Pulse Code Modulation) 。

运作原理如下:首先我们考虑声音经过麦克风,转换成一连串电压变化的信号,如下图所示。这张图的横座标为秒,纵座标为电压大小。


语音文件的格式、字节计算、PCM头信息 2019-04-26_第1张图片

要将这样的信号转为 PCM 时,需要将声音量化,我们一般从如下几个维度描述一段声音:

1.声道数  2.采样位数  3.采样频率  4.时长

采样频率:即取样频率,指每秒钟取得声音样本的次数。采样频率越高,声音的质量也就越好,声音的还原也就越真实,但同时它占的资源比较多。由于人耳的分辨率很有限,太高的频率并不能分辨出来。在16位声卡中有22KHz、44KHz等几级,其中,22KHz相当于普通FM广播的音质,44KHz已相当于CD音质了,目前的常用采样频率都不超过48KHz。

采样位数:即采样值或取样值(就是将采样样本幅度量化)。它是用来衡量声音波动变化的一个参数,也可以说是声卡的分辨率。它的数值越大,分辨率也就越高,所发出声音的能力越强。

声道数:很好理解,有单声道和立体声之分,单声道的声音只能使用一个喇叭发声(有的也处理成两个喇叭输出同一个声道的声音),立体声的PCM 可以使两个喇叭都发声(一般左右声道有分工) ,更能感受到空间效果。

时长: 采样的时长


下面再用图解来看看采样位数和采样频率的概念。让我们来看看这几幅图。

图中的黑色曲线表示的是PCM 文件录制的自然界的声波,

红色曲线表示的是PCM 文件输出的声波,

这个图中,采样点是离散的,每一个点对应pcm一个单元的数据。

采样频率越高,x轴采样点就越密集,声音越接近原始数据

采样位数越高,y轴采样点就越密集,声音越接近原始数据


语音文件的格式、字节计算、PCM头信息 2019-04-26_第2张图片

采样频率单位为Hz,表示每秒采样的次数:

一般有11025HZ(11KHz)、22050HZ(22KHz)、44100Hz(44KHz)三种。

采样位数单位为bit(位),一般有 8bit 和 16bit 。8bit 表示用 8bit 空间量化某时刻的声音,这一点基本是和图片用r、g、b三单位共 24bit 量化颜色一样。


综上所述,我们可以得到pcm文件的体积计算公式(这里我们把 采样位数/8 是因为电脑上是将bit转化为byte):

存储量

存储量 = (采样频率 × 采样位数/8) × 声道 × 时间.

每个采样数据记录的是振幅,采样精度取决于储存空间的大小。

1字节(8bit)只能记录256个数,也就是只能将振幅划分到256个等级。

2字符(16bit)可以记录个数,将振幅划分到65536个等级,是CD的标准。

4字节(32bit)细分到个数, 没有必要,太精细了。

以8k 16bit音频为例、采样率8k=8000个采样点/秒。

16bit音频是16位。每8位一个字节,所以16bit是两个字节。

上面的是单声道(nomo),如果是双声道,所有信息全部×2

 时间是这个音频的秒数

例如,数字激光唱盘(CD-DA,红皮书标准)的标准采样频率为44.l kHz,采样数位为16 位,立体声(2声道),可以几乎无失真地播出频率高达22 kHz的声音,这也是人类所能听到的最高频率声音。激光唱盘一分钟音乐需要的存储量为:

(44.1*1000* l6 *2)*60/8=10,584,000(字节)=10.584 M Bytes

这个数值就是 PCM 声音文件在硬盘中所占磁盘空间的存储量。


单双声道

 数据以二进制序列储存在文件里

 单声道8bit (1字节):        声音

双声道8bit  (2字节):        左声道  右声道

单声道8bit  (2字节):        声音低字节  声音高字节

单声道16bit(4字节): 左音道低字节 左声道高字节 右声道低字节 右声道高字节 


双声道音频的存储方式是LRLRLRLR,16bit音频是每个声道都是16bit(2字节)么?PCM是interleaved的方式存储,具体存储的时候还有小端(little endian)和 (big endian)的问题,一般的存储是小端的,也就是2字节,低位在前,高位在后一个采样点16位是0x 1234 存储的时候是 0x34 和 0x12 , 如果是大端就反过来。

一个单声道的pcm无头音频1M ,转成 双声道就变成2M了,就算是有一条声道没信息(或者微弱信号噪声),但是 转成双声道的时候就算是静音,数据大小是0x0000他也是要占着位数的,所以不管怎样,只要是双声道就会变成2倍大小。



WAV和PCM的关系

前面也介绍到了,PCM 数据本身只是一个裸码流,它是由声道、采样位数、采样频率、时长共同决定的,因此我们至少要知道其中的三个才能将 PCM 所代表的数据提取出来。

因此,纯PCM数据是无法播放的,因此还需要一段描述数据。计算机系统中的一个比较常见的做法是将pcm码流和描述信息封装在一起,形成一个音频文件。这样就可以直接播放了。

一种常见的方式是使用wav格式定义的规范将pcm码流和描述信息封装起来。查看 pcm 和对应wav文件的 hex(16进制)文件,可以发现,wav文件只是在pcm文件的开头多了44字节 ,来表征其声道数、采样频率和采样位数等信息。这个其实和bmp非常类似。


多种音频格式

WAV、G729、G723 、MP3 等音频格式都是8k 16bit wav音频经过压缩的格式。

由于厂商众多、 很多音频格式 应运而生,比如nice公司出品的 nmf 其实音频,其实就是一个经过多层再包装的g729;vox 格式是华为公司出品的音频。

VOX格式

vox 格式是华为的格式、他的后缀一种是 V3 的,直接把后缀改成vox就可以听;还有一种后缀就是vox。

vox格式因为本身是没有头信息的看不到,所以不知道采样率不能转码、这时候用 cooledit 打开听一下,选择8k的采样率打开如果语速很快音频实际是6k;如果选择6k的采样率打开如果语速很快音频实际是8k。现在 得知采样率之后就可以用工具转码,下面会说到工具ffmpeg以及他的轻量版sox。

G729

G729以10字节作为一个解码单元,G729转码时先把头去掉再转。

G729是十六倍压缩。8k 16bit 8kb/s (正常是128kb/s 压缩16倍)

MP3

和g729一样是16倍压缩,但是由于压缩算法不一样,G729的频谱是光滑的、而MP3音频的损失很多。是最差的一种音频格式。

Alaw

8k 8bit stereo 128kb/s音频格式,应该是非压缩的格式


音频转码

首先音频格式之间转码,比如g729 转 mp3 流程是g729->8k、16bit wav -> mp3,都是要先经过wav的。


抓码工具

<1> 8k8bit nist --> 8k16bit pcm

sox -r 8000 -b 8 -c 1 -t nist 1.nist -s -r 8000 -b 16 1.wav dither

<2> wav->amr->wav

ffmpeg -i inFile1.wav -ab 12.2k outFile.amr

ffmpeg -i outFile.amr outFile.wav

or

ffmpeg -acodec libopencore_amrnb -i outFile.amr outFile.wav

<3> wav-alaw->wav

ffmpeg -i inFile1.wav -acodec pcm_alaw -ar 8000 outFile1.wav

ffmpeg -i outFile1.wav outFile.wav

<4> mulaw->wav

ffmpeg -i inFile.wav outFile.wav

<5> mp3->wav

ffmpeg -i inFile.mp3 outFile.wav

<6> alaw->wav

sox -e a-law alaw.wav -r 8000 -b 16 out.wav

<7> music.mp3 -> wav

ffmpeg -i music.mp3 -ar 8000 -ac 1 outFile.wav

<8> pcm add header -> wav

sox -s -t raw -r 8000 -c 1 -2 in.pcm out.wav

ffmpeg -acodec pcm_s16le -f s16le -ar 8000 -i in.pcm -ar 8000 -ac 1 -ab 128k out.wav

<9> sphere-->wav (wsj data)

sph2pipe 1.WV1 -f wav 1.wav

<10> vox-->wav

./ffmpeg -acodec adpcm_ima_oki -f s16le -ar 6000 -i 1211452.V3 12.wav

<11> two path->mono注:mono.wav -> 单声道 stereo.wav -> 双声道(立体声)

ffmpeg -i left.wav -i right.wav -filter_complex amix=inputs=2 mono.wav

ffmpeg -i left.wav -i right.wav -filter_complex "amovie=left.wav [l];amovie=right.wav [r]; [l] [r] amerge" stereo.wav

<12> stereo filter

ffmpeg -i fa.mp3 -map_channel 0.0.0 -ar 8000 -ab 128k left.wav -map_channel 0.0.1 -ar 8000 -ab 128k right.wav

<13> wav speed up #声音加速

ffmpeg -i 16k.wav -filter:a "atempo=1.75" 16k_fast.wav

<14>g729 tranfer

removeHead xx.V3 58 xx.g729

ffmpeg -acodec g729 -f g729 -i xx.g729 xx.wav

<15> nmf->g729->wav

./nmf2g729 1.nmf 1.nmf.g729ffmpeg -acodec g729 -f g729 -i xx.g729 xx.wav


sox

一般会内置的轻量级ffmpeg工具。

合并多个音频

sox 1.wav 2.wav 3.wav 1_2_3.wav

hexdump查看音频文件头信息

hexdump -Cv in.wav | less


音频头字节信息

标准音频的头字节是44位 

查看音频字节信息是:hexdump -C in.wav

语音文件的格式、字节计算、PCM头信息 2019-04-26_第3张图片

看红色部分

其中音频大小可以在第40-43位(从0位开始)倒着看是音频大小:0x 00 02 53 a0 

转换成十进制是152480 加上标准头字节 44 是152524字节

查看音频的文件大小152524字节 与计算结果吻合

其实看4-7位也行,4-7位查看下来是152516字节

152516+8=152524字节其实这个152516就是除了头字节的八个字节后面的字节数

看蓝色部分

24-25位是0x 40 1f  = 8k 这个位置标记的是音频的采样率大小标准音频的头字节是44位 


PCM头信息

一个裸的PCM格式音频数据,如果不带头信息,不知道其采样率等相关信息,就无法用播放器播放出来。下面是默认的头信息格式:

//音频头部格式

struct wave_pcm_hdr

{

    char                      riff[4];                           // = "RIFF"

    SR_DWORD        size_8;                        // = FileSize - 8

    char                      wave[4];                      // = "WAVE"

    char                       fmt[4];                        // = "fmt "

    SR_DWORD        dwFmtSize;                // = 下一个结构体的大小 : 16

    SR_WORD          format_tag;                  // = PCM : 1

    SR_WORD          channels;                    // = 通道数 : 1

    SR_DWORD       samples_per_sec;      // = 采样率 : 8000 | 6000 | 11025 | 16000

    SR_DWORD       avg_bytes_per_sec;    // = 每秒字节数 : dwSamplesPerSec *wBitsPerSample / 8

    SR_WORD          block_align;                // = 每采样点字节数 : wBitsPerSample / 8

    SR_WORD          bits_per_sample;        // = 量化比特数: 8 | 16

    char                     data[4];                       // = "data";

    SR_DWORD       data_size;                 // = 纯数据长度 : FileSize - 44

} ;

//默认音频头部数据

struct wave_pcm_hdr default_pcmwavhdr =

{

    { 'R', 'I', 'F', 'F' },

    0,

    {'W', 'A', 'V', 'E'},

    {'f', 'm', 't', ' '},

    16,

    1,

    1,

    16000,

    32000,

    2,

    16,

    {'d', 'a', 't', 'a'},

    0 

};


你可能感兴趣的:(语音文件的格式、字节计算、PCM头信息 2019-04-26)