用C/C++读取和处理WAV文件数据

Lux*_*uxk 13 c c++ voice voice-recognition

我目前正在做一个非常重要的学校项目.我需要在C/C++中提取WAVE文件的信息,并使用该信息来获取语音信号的LPC.但是,为了做到这一点,我需要对信号进行一些预处理,比如进行零交叉和能量分析等.这意味着我需要标志和真正的价值.问题是我不知道如何获得有用的信息和正确的格式.我已经读过文件中的每个字段,但我不确定我做得对.建议好吗?

这是我此刻阅读文件的方式:

readI = fread(&bps,1,2,audio); printf("每个样本的位数=%d \n",bps);

提前致谢.

小智 16

我的第一个建议是使用某种类型的库来帮助你.大多数声音解决方案看起来都是矫枉过正的,所以一个简单的库(就像你的问题评论中建议的一样,libsndfile)应该可以解决问题.

如果你只是想知道如何阅读WAV文件,这样你就可以编写自己的文件(因为你的学校可能会因为你像任何其他普通人一样使用图书馆而嗤之以鼻),快速谷歌搜索会给你所有的信息需要加上一些已经写过许多关于阅读.wav格式教程的人.

如果你仍然没有得到它,这里是我自己的一些代码,我读取WAV/RIFF数据文件的标题和所有其他块,直到我到达数据块.它完全基于WAV格式规范.提取实际的声音数据并不是很难:您既可以原始读取也可以原始使用它,或者转换为内部更舒适的格式(32位PCM未压缩数据或其他内容).

查看下面的代码时,请reader.Read...( ... )使用等效fread调用替换指定类型的整数值和字节大小.WavChunks是一个枚举,它是WAV文件块内ID的Little Endian值,该format变量是可以包含在WAV文件格式中的Wav格式类型之一:

enum class WavChunks {
    RiffHeader = 0x46464952,
    WavRiff = 0x54651475,
    Format = 0x020746d66,
    LabeledText = 0x478747C6,
    Instrumentation = 0x478747C6,
    Sample = 0x6C706D73,
    Fact = 0x47361666,
    Data = 0x61746164,
    Junk = 0x4b4e554a,
};

enum class WavFormat {
    PulseCodeModulation = 0x01,
    IEEEFloatingPoint = 0x03,
    ALaw = 0x06,
    MuLaw = 0x07,
    IMAADPCM = 0x11,
    YamahaITUG723ADPCM = 0x16,
    GSM610 = 0x31,
    ITUG721ADPCM = 0x40,
    MPEG = 0x50,
    Extensible = 0xFFFE
};

int32 chunkid = 0;
bool datachunk = false;
while ( !datachunk ) {
    chunkid = reader.ReadInt32( );
    switch ( (WavChunks)chunkid ) {
    case WavChunks::Format:
        formatsize = reader.ReadInt32( );
        format = (WavFormat)reader.ReadInt16( );
        channels = (Channels)reader.ReadInt16( );
        channelcount = (int)channels;
        samplerate = reader.ReadInt32( );
        bitspersecond = reader.ReadInt32( );
        formatblockalign = reader.ReadInt16( );
        bitdepth = reader.ReadInt16( );
        if ( formatsize == 18 ) {
            int32 extradata = reader.ReadInt16( );
            reader.Seek( extradata, SeekOrigin::Current );
        }
        break;
    case WavChunks::RiffHeader:
        headerid = chunkid;
        memsize = reader.ReadInt32( );
        riffstyle = reader.ReadInt32( );
        break;
    case WavChunks::Data:
        datachunk = true;
        datasize = reader.ReadInt32( );
        break;
    default:
        int32 skipsize = reader.ReadInt32( );
        reader.Seek( skipsize, SeekOrigin::Current );
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么 RIFF 以十六进制向后写入?我知道小/大端,但我使用过的所有十六进制编辑器都将它显示为 RIFF,而不是 FFIR,他们是否在幕后进行了一些奇怪的转换,或者还有其他事情发生吗? (3认同)