本文是上面文章的摘要,只用于自己快速浏览.
目录
播放器是无法直接播放PCM的,因为播放器并不知道PCM的采样率、声道数、位深度等参数。当PCM转成某种特定的音频文件格式后(比如转成WAV),就能够被播放器识别播放了。
本文通过2种方式(命令行、编程)演示一下:如何将PCM转成WAV。
WAV文件格式
WAV、AVI文件都是基于RIFF标准的文件格式
// WAV文件头(44字节)
typedef struct {
// RIFF chunk的id
uint8_t riffChunkId[4] = {'R', 'I', 'F', 'F'};
// RIFF chunk的data大小,即文件总长度减去8字节
uint32_t riffChunkDataSize;
// "WAVE"
uint8_t format[4] = {'W', 'A', 'V', 'E'};
/* fmt chunk */
// fmt chunk的id
uint8_t fmtChunkId[4] = {'f', 'm', 't', ' '};
// fmt chunk的data大小:存储PCM数据时,是16
uint32_t fmtChunkDataSize = 16;
// 音频编码,1表示PCM,3表示Floating Point
uint16_t audioFormat = AUDIO_FORMAT_PCM;
// 声道数
uint16_t numChannels;
// 采样率
uint32_t sampleRate;
// 字节率 = sampleRate * blockAlign
uint32_t byteRate;
// 一个样本的字节数 = bitsPerSample * numChannels >> 3
uint16_t blockAlign;
// 位深度
uint16_t bitsPerSample;
/* data chunk */
// data chunk的id
uint8_t dataChunkId[4] = {'d', 'a', 't', 'a'};
// data chunk的data大小:音频数据的总长度,即文件总长度减去文件头的长度(一般是44)
uint32_t dataChunkDataSize;
} WAVHeader;
命令行
通过下面的命令可以将PCM转成WAV。
ffmpeg -ar 44100 -ac 2 -f s16le -i out.pcm out.wav
加上一个输出文件参数-bitexact可以去掉LIST Chunk。
ffmpeg -ar 44100 -ac 2 -f s16le -i out.pcm -bitexact out2.wav
mono:单声道
stereo:立体声
编程
WAV文件 = 头信息数据(有些是固定的,有些从上下文的stream中可以获取) + PCM文件数据(采集的原始数据)
将头信息写入WAV文件,将PCM文件数据写入WAV文件
头信息定义一个结构体,将结构体数据写入:
结构体在内存中的存储方式跟系统一致(Mac是little end),不用我们自己手动处理大小端模式
可以有两种方式:
方式一:将录制好的PCM数据,转为WAV数据
- 打开pcmFile
- 打开wavFile
- 写入头部数据
- 写入pcm数据
方式二:边录制,边向WAV文件内些数据
- 写入头部数据(结构体),部分头部数据需要录制完成后才能获得,先占位
- 打开wavFile,边采集边写入数据
- 采集完成后通过seek定位到文件头部,将修改过的结构体,重新写入,覆盖头部数据.(或者通过seek一个一个找到占位数据,修改)
行者常至,为者常成!