本文转自【 https://www.cnblogs.com/renhui/p/12148330.html 】,有大量删改。
CONTENTS
名词解析
PCM(Pulse Code Modulation)也被称为脉码编码调制,PCM中的声音数据没有被压缩,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。采样转换方式参考下图进行了解:
音频采样包含以下几大要素:
采样率
采样率表示音频信号每秒的数字快照数。该速率决定了音频文件的频率范围。采样率越高,数字波形的形状越接近原始模拟波形。低采样率会限制可录制的频率范围,这可导致录音表现原始声音的效果不佳。根据奈奎斯特采样定理,为了重现给定频率,采样率必须至少是该频率的两倍。例如,一般CD唱片的采样率为每秒 44,100 个采样,因此可重现最高为 22,050 Hz 的频率,此频率刚好超过人类的听力极限 20,000 Hz。
图中A是低采样率的音频信号,其效果已经将原始声波进行了扭曲,B则是完全重现原始声波的高采样率的音频信号。数字音频常用的采样率如下:
位深度
位深度决定动态范围。采样声波时,为每个采样指定最接近原始声波振幅的振幅值。较高的位深度可提供更多可能的振幅值,产生更大的动态范围、更低的噪声基准和更高的保真度。位深度越高,提供的动态范围越大。
PCM
在上面的名词解析中我们应该对PCM有了一定的理解和认识,下面我们将对PCM做更多的讲解。
PCM音频数据存储方式
如果是单声道的音频文件,采样数据按时间的先后顺序依次存入(也可能采用 LRLRLR 方式存储,只是另一个声道的数据为 0)。
如果是双声道的话通常按照 LRLRLR 的方式存储,存储的时候还和机器的大小端有关。(关于字节序大小端的相关内容可参考《字节序问题之大小端模式讲解》进行了解)
PCM的存储方式为小端模式,存储Data数据排列如下图所示:
PCM 音频数据的参数
描述 PCM 音频数据的参数的时候有如下描述方式:
44100HZ 16bit stereo: 每秒钟有 44100 次采样, 采样数据用 16 位(2 字节)记录, 双声道(立体声) 22050HZ 8bit mono: 每秒钟有 22050 次采样, 采样数据用 8 位(1 字节)记录, 单声道 48000HZ 32bit 51ch: 每秒钟有 48000 次采样, 采样数据用 32 位(4 字节浮点型)记录, 5.1 声道
44100Hz 指的是采样率,它的意思是每秒取样 44100 次。采样率越大,存储数字音频所占的空间就越大。
16bit 指的是采样精度,意思是原始模拟信号被采样后,每一个采样点在计算机中用 16 位(两个字节)来表示。采样精度越高越能精细地表示模拟信号的差异。
Stereo 指的是声道数,也即采样时用到的麦克风的数量,麦克风越多就越能还原真实的采样环境(当然麦克风的放置位置也是有规定的)。
WAV
WAV 是 Microsoft 和 IBM 为 PC 开发的一种声音文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所广泛支持。WAVE 文件通常只是一个具有单个 “WAVE” 块的 RIFF 文件,该块由两个子块(”fmt” 子数据块和 ”data” 子数据块),它的格式如下图所示:
WAV 格式定义
该格式的实质就是在 PCM 文件的前面加了一个文件头,每个字段的的含义如下:
typedef struct { char ChunkID[4]; //内容为"RIFF" unsigned long ChunkSize; //存储文件的字节数(不包含ChunkID和ChunkSize这8个字节) char Format[4]; //内容为"WAVE“ } WAVE_HEADER; typedef struct { char Subchunk1ID[4]; //内容为"fmt" unsigned long Subchunk1Size; //存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节) unsigned short AudioFormat; //存储音频文件的编码格式,例如若为PCM则其存储值为1。 unsigned short NumChannels; //声道数,单声道(Mono)值为1,双声道(Stereo)值为2,等等 unsigned long SampleRate; //采样率,如8k,44.1k等 unsigned long ByteRate; //每秒存储的bit数,其值 = SampleRate * NumChannels * BitsPerSample / 8 unsigned short BlockAlign; //块对齐大小,其值 = NumChannels * BitsPerSample / 8 unsigned short BitsPerSample; //每个采样点的bit数,一般为8,16,32等。 } WAVE_FMT; typedef struct { char Subchunk2ID[4]; //内容为“data” unsigned long Subchunk2Size; //接下来的正式的数据部分的字节数,其值 = NumSamples * NumChannels * BitsPerSample / 8 } WAVE_DATA;
WAV 文件头解析
这里是一个 WAVE 文件的开头 72 字节,字节显示为十六进制数字:
52 49 46 46 | 24 08 00 00 | 57 41 56 45 66 6d 74 20 | 10 00 00 00 | 01 00 02 00 22 56 00 00 | 88 58 01 00 | 04 00 10 00 64 61 74 61 | 00 08 00 00 | 00 00 00 00 24 17 1E F3 | 3C 13 3C 14 | 16 F9 18 F9 34 E7 23 A6 | 3C F2 24 F2 | 11 CE 1A 0D
字段解析如下图:
发表评论