2013-04-18 175 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