[概念]PCM文件&WAV文件头

Posted ouyangshima

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[概念]PCM文件&WAV文件头相关的知识,希望对你有一定的参考价值。

PCM简介

PCM(Pulse Code Modulation),脉冲编码调制。人耳听到的是模拟信号,PCM是把声音从模拟信号转化为数字信号的技术原理是用一个固定的频率对模拟信号进行采样,采样后的信号在波形上看就像一串连续的幅值不一的脉冲(脉搏似的短暂起伏的电冲击),把这些脉冲的幅值按一定精度进行量化,这些量化后的数值被连续的输出、传输、处理或记录到存储介质中,所有这些组成了数字音频的产生过程(抽样、量化、编码三个过程)。要将这种信号转为 PCM 格式的方法,是使用三个參数来表示声音,它们是声道数、采样位数和采样频率。

PCM:其数据排列格式为左右声道每个样本点数据交错排列

采样频率

即取样频率,指每秒钟取得声音样本的次数,是设备一秒钟内对模拟信号的采样次数。採样频率越高,声音的质量也就越好,声音的还原也就越真实,但同一时候它占的资源比較多。因为人耳的分辨率非常有限,太高的频率并不能分辨出来。
在16位声卡中有22KHz、44KHz等几级,当中,8Khz的电话采样率就可以达到人的对话程度,22KHz相当于普通FM广播的音质,44KHz已相当于CD,MP3音质了,48KHz相当于miniDV、数字电视、DVD、电影和专业音频。

采样位数

即采样值或取样值(就是将採样样本幅度量化)。它是用来衡量声音波动变化的一个參数。也能够说是声卡的分辨率。它的数值越大,分辨率也就越高。所发出声音的能力越强。采样位数比如8bit(现在少见)、16bit(常用)和24bit,指的是描述数字信号所使用的位数。

声道数

声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号。有单声道和立体声之分,单声道的声音仅仅能使用一个喇叭发声(有的也处理成两个喇叭输出同一个声道的声音)。立体声的PCM 能够使两个喇叭都发声(一般左右声道有分工) ,更能感受到空间效果。单声道采样数据为8位的短整数(short);双声道采样数据为16位的整数,(int),高八位(左声道)和低八位(右声道)分别代表两个声道。

    [时长]s * [采样率]Hz * [采样位数]bit * [声道数] / 8 = [文件大小]byte
    某音频信号是采样率为8kHz、声道数2、位宽为16bit,时长为1s,则音频数据的大小为:
    1 * 8000 * 16 *2 = 256000 bit / 8 = 32000 byte / 1024 = 31.25 KB

wav文件头

/**
 * 获取WAV头获取文件
 * @param totalAudioLen 整个音频PCM数据大小
 * @param sampleRate 采样率,例如16000Hz
 * @param channels 声道数 单声道:1或双声道:2
 * @param bitNum 采样位数,8或16
 */
private byte[] getWaveFileHeader(long totalAudioLen,int sampleRate, int channels, int bitNum) 
    Log.d(TAG, "getWaveFileHeader filesize = " + String.valueOf(totalAudioLen));
    //采样字节byte率
    long byteRate = sampleRate * channels * bitNum / 8;
    //整个数据大小
    //总大小,由于不包括RIFF和WAVE,所以是44 - 8 = 36,在加上PCM文件大小
    long totalDataLen = totalAudioLen + 36;

    byte[] header = new byte[44];
    header[0] = 'R'; // RIFF
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (byte) (totalDataLen & 0xff);//数据大小
    header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    //WAVE
    header[8] = 'W';
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    //FMT Chunk
    header[12] = 'f'; // 'fmt '
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';//过渡字节
    //数据大小
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    //编码方式 10H为PCM编码格式
    header[20] = 1; // format = 1
    header[21] = 0;
    //通道数
    header[22] = (byte) channels;
    header[23] = 0;
    //采样率,每个通道的播放速度
    header[24] = (byte) (sampleRate & 0xff);
    header[25] = (byte) ((sampleRate >> 8) & 0xff);
    header[26] = (byte) ((sampleRate >> 16) & 0xff);
    header[27] = (byte) ((sampleRate >> 24) & 0xff);
    //音频数据传送速率,采样率*通道数*采样深度/8
    header[28] = (byte) (byteRate & 0xff);
    header[29] = (byte) ((byteRate >> 8) & 0xff);
    header[30] = (byte) ((byteRate >> 16) & 0xff);
    header[31] = (byte) ((byteRate >> 24) & 0xff);
    // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数
    header[32] = (byte) (channels * bitNum / 8);
    header[33] = 0;
    //每个样本的数据位数
    header[34] = (byte) bitNum;
    header[35] = 0;
    //Data chunk
    header[36] = 'd';//data
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (byte) (totalAudioLen & 0xff);
    header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
    header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
    header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

    return header;

RIFF全称为资源互换文件格式(Resources Interchange File Format),是Windows下大部分多媒体文件遵循的一种文件结构。RIFF文件所包含的数据类型由该文件的扩展名来标识,能以RIFF格式存储的数据有:

  • 音频视频交错格式数据 .AVI
  • 波形格式数据 .WAV
  • 位图数据格式 .RDI
  • MIDI格式数据 .RMI
  • 调色板格式 .PAL
  • 多媒体电影 .RMN
  • 动画光标 .ANI
  • 其他的RIFF文件 .BND

以上是关于[概念]PCM文件&WAV文件头的主要内容,如果未能解决你的问题,请参考以下文章

音视频开发进阶指南

PCM和WAV音频格式的区别,以及python自动转换

录音系列:pcm文件在线转wav文件

音频数据文件格式(PCM,WAV,MIDI)简记

在 HTC One 上以 16khz 单声道 PCM (WAV) 录制时出现断断续续的音频

PCM文件格式简单介绍