[C++]我想从wav文件中获取PCM数据

Posted

技术标签:

【中文标题】[C++]我想从wav文件中获取PCM数据【英文标题】:[C++]I want to get PCM data from wav file 【发布时间】:2015-06-04 12:53:32 【问题描述】:

我知道 Wave 文件的结构。但我不知道 PCM DATA 的确切结构。

#include<iostream>
#include<fstream>
using namespace std;

struct WAVE_HEADER
    char Chunk[4];
    int ChunkSize;
    char format[4];
    char Sub_chunk1ID[4];
    int Sub_chunk1Size;
    short int AudioFormat;
    short int NumChannels;
    int SampleRate;
    int ByteRate;
    short int BlockAlign;
    short int BitsPerSample;
    char Sub_chunk2ID[4];
    int Sub_chunk2Size;
;

struct WAVE_HEADER waveheader;

int main()
    FILE *sound;
    sound = fopen("music.wav","rb");
    short D;
    fread(&waveheader,sizeof(waveheader),1,sound);
    cout << "BitsPerSample : "  << waveheader.BitsPerSample << endl;
    while(!feof(sound))
        fread(&D,sizeof(waveheader.BitsPerSample),1,sound);
        cout << int(D) << endl;
    

上面的代码是我到目前为止所做的。此外,此代码可以准确读取标题。但我不知道这是否可以准确读取 PCM 数据部分。有没有PCM数据结构的参考?没找到。

“music.wav”每个样本有 16 位,16 字节速率,立体声通道和两个块对齐。以上应该怎么改?

【问题讨论】:

PCM 具有 no 结构。原始样本作为 8、16、24 或 32 位有符号或无符号整数(或者,不太常见的是 floats 或 doubles。) 【参考方案1】:

如this description of wav specifications 中所述,PCM 数据使用 little-endian 字节顺序和二进制补码存储,分辨率大于每个样本 8 位。换句话说,在 Intel 处理器上,16 位样本通常对应于signed short。此外,对于立体声通道,数据是交错的(左/右样本)。

考虑到这一点,假设“music.wav”确实包含 16 位 PCM 样本,并且您正在使用 sizeof(short)==2 的编译器在 little-endian 平台上读取数据,那么您发布的代码应该读取正确采样。

【讨论】:

请记住,并非所有 .wav 文件都包含交错的 8、16、24、32 int PCM 数据。检查 short int AudioFormat,如果它不等于 1,则它是其他格式,并且几乎总是被压缩并且会有一个扩展的 header。如果不为其实现编解码器,您将无法读取压缩数据。或者使用外部程序将其转换为 PCM。

以上是关于[C++]我想从wav文件中获取PCM数据的主要内容,如果未能解决你的问题,请参考以下文章

获取 WAV 文件的 PCM 值

试图将原始 PCM 写入 WAV 并且只获取标题

在 .net 中处理 pcm wav 流

SoundPlayer 不播放任何捆绑的 Windows 声音 PCM wav 文件

C++ 在 Linux 中录制 PCM 流

使用 Android SDK 从原始 PCM 数据创建 WAV 文件