2013-04-18 171 views
10

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

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

readI =的fread(& BPS,1,2,音频); printf(“每个样本的位数=%d \ n”,bps);

在此先感谢。

+3

http://www.mega-nerd.com/libsndfile/ http://ccrma.stanford.edu/software/snd/sndlib/是可以帮助您使用WAV的两个库 – Patashu 2013-04-18 05:39:55

回答

15

我的第一个建议是使用某种图书馆来帮助你。大多数声音解决方案看起来过于矫枉过正,所以一个简单的库(就像你的问题的评论libsndfile中推荐的那个)应该可以做到。

如果你只是想知道如何阅读WAV文件,所以你可以自己写(因为你的学校可能会像其他普通人一样使用图书馆),快速谷歌搜索会给你所有你需要的信息plus some people who have already wrote many tutorials on reading the .wav format

如果你仍然没有得到它,这里是我自己的一些代码,在这里我读取了WAV/RIFF数据文件的头文件和所有其他数据块,直到到达数据块。它基于exclusively off the WAV Format Specification。提取实际的声音数据并不难:您可以将其读取为原始数据并将其转换为原始格式,或者转换为内部格式(32位PCM未压缩数据或其他)。

查看下面的代码时,请将reader.Read...(...)替换为调用指定类型的整数值和字节大小的等效freadWavChunks是一个枚举其为WAV文件组块的内部的ID的小端值,并且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; 
    } 
} 
+1

为什么RIFF以十六进制向后写?我知道小/大端,但我用过的所有十六进制编辑器都将其显示为RIFF,而不是FFIR,他们在幕后做了一些奇怪的转换,还是其他事情正在进行? – MarcusJ 2014-05-22 01:04:15

+0

我相信@MarcusJ是正确的应该阅读RIFF,这里是波形格式的描述http://soundfile.sapp.org/doc/WaveFormat/所以我相信它应该是RiffHeader = 0x52494646作为格式说明它是一个大 - 印地安场 – alexm 2017-01-11 13:43:02