• 音视频之PCM转WAV(八)


    前引

    我们之前录制的PCM音频,是无法被播放器播放的,因为播放器并不知道PCM的采样率、声道数、位深度等参数。当PCM转成某种特定的音频文件后(比如转成WAV),就能被播放器识别播放了。

    WAV文件格式

    在进行PCM转WAV之前,先来认识一下WAV的文件格式。

    • WAV、AVI文件都是基于RIFF标准的文件格式
    • RIFF( Resource Interchange File Format ,资源交换文件格式) 由Microsoft和IBM提出
    • 所以WAV、AVI文件的最前面4个字节都是RIFF四个字符

    数据构成

    每一个chunk(数据块)都由3部分组成:

    • id: chunk的标识
    • data size: chunk的数据部分大小,字节为单位
    • data: chunk的数据部分

    整个WAV文件是一个RIFF chunk,它的data由3部分组成:

    • format: 文件类型
    • fmt chunk
      • 音频数据相关的chunk
      • 它的data就是真正的音频数据(比如PCM数据)

    RIFF chunk除去data chunk的data(音频数据)后,剩下的内容可以称为: WAV文件头,一般是44字节

    WAV44字节具体构成

    代码实现

    .h

    #ifndef FFMPEGS_H
    #define FFMPEGS_H
    
    #include <stdint.h>
    
    #define AUDIO_FORMAT_PCM 1
    #define AUDIO_FORMAT_FLOAT 3
    
    // 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', 'F'};
        /* 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;
    
    class FFmpegs
    {
    public:
        FFmpegs();
        static void pcmToWav(WAVHeader &header, const char *pcmFilename, const char *wavFilename);
    };
    
    #endif // FFMPEGS_H

    .CPP

    #include "ffmpegs.h"
    #include <QFile>
    #include <QDebug>
    
    FFmpegs::FFmpegs()
    {
    
    }
    
    void FFmpegs::pcmToWav(WAVHeader &header, const char *pcmFilename, const char *wavFilename) {
        header.blockAlign = header.bitsPerSample * header.numChannels >> 3;
        header.byteRate = header.sampleRate * header.blockAlign;
    
        // 打开pcm文件
        QFile pcmFile(pcmFilename);
        if (!pcmFile.open(QFile::ReadOnly)) {
            qDebug() << "打开文件失败" << pcmFilename;
            return;
        }
        header.dataChunkDataSize = pcmFile.size();
        header.riffChunkDataSize = header.dataChunkDataSize + sizeof (WAVHeader) - sizeof (header.riffChunkId) - sizeof (header.riffChunkDataSize);
    
        // 打开wav文件
        QFile wavFile(wavFilename);
        if (!wavFile.open(QFile::WriteOnly)) {
            qDebug() << "文件打开失败" << wavFilename;
            pcmFile.close();
            return;
        }
    
        // 写入头部
        wavFile.write((const char *) &header, sizeof (WAVHeader));
    
        // 打开wav文件
        char buf[1024];
        int size;
        while ((size = pcmFile.read(buf, sizeof(buf))) > 0) {
            wavFile.write(buf, size);
        }
    
        // 关闭文件
        pcmFile.close();
        wavFile.close();
    }
  • 相关阅读:
    常用SQL语句大全总结
    修改 Mac 默认 PHP 运行环境
    mac下更新自带的PHP版本到5.6或7.0
    apache php 开启伪静态
    酒店迎接新技术变革:用智能手机开门
    百度地图显示多个标注点
    百度地图api简单使用方法
    Spring mvc 配置详解
    Spring MVC入门知识总结
    Bootstrap 按钮
  • 原文地址:https://www.cnblogs.com/muzichenyu/p/15514361.html
Copyright © 2020-2023  润新知