JHHK

欢迎来到我的个人网站
行者常至 为者常成

【MJ】10_PCM转WAV

参考:【秒懂音视频开发】10_PCM转WAV

本文是上面文章的摘要,只用于自己快速浏览.

目录

播放器是无法直接播放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数据

  1. 打开pcmFile
  2. 打开wavFile
  3. 写入头部数据
  4. 写入pcm数据

方式二:边录制,边向WAV文件内些数据

  1. 写入头部数据(结构体),部分头部数据需要录制完成后才能获得,先占位
  2. 打开wavFile,边采集边写入数据
  3. 采集完成后通过seek定位到文件头部,将修改过的结构体,重新写入,覆盖头部数据.(或者通过seek一个一个找到占位数据,修改)

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.