2015-11-01 57 views
0

我正在編寫讀取波形文件的代碼。從wavfile標題讀取採樣率

我使用this document作爲我的指導原則。

它指定標題的字節22是波形文件的通道數,標題的字節24是採樣率。

我正在使用由Ableton輸出的測試文件作爲2通道16位44100hz。我已經確認測試波形文件的格式是大膽的,以確保它確實是44100hz的採樣率。

當我讀取wave文件時,我得到一個採樣率值-21436。我很確定我的代碼讀取一個小端的整數是正確的。我確定我的測試wavfile是正確的。所以,現在我不知道爲什麼讀取的採樣率是不正確的....

我的int讀取代碼如下。

int ReadInt(char* bytes , int start) { return (bytes[start+3] << 24) + (bytes[start+2] << 16) + (bytes[start+1] << 8) + bytes[start]; } 

讀取波形文件是如下的功能...

WavFile::WavFile(std::string filename) 
{ 
    std::ifstream ifs;  
    ifs.open(filename, std::ios::binary | std::ios::in); 

    LogStream(LOG_DEBUG) << "WavFile::WavFile - - - - BEGIN READING WAV - - - -"; 

    if(ifs.fail()) 
     throw std::invalid_argument("WavFile::WavFile : Failed to open wavFile "+filename); 

    char hbytes[HEADER_SIZE]; 

    ifs.read(hbytes , HEADER_SIZE); 

    // check that this is actually a wave file 
    bool valid_riff = hbytes[0]=='R' && hbytes[1]=='I' && hbytes[2]=='F' && hbytes[3]=='F'; 
    bool valid_wave = hbytes[8]=='W' && hbytes[9]=='A' && hbytes[10]=='V' && hbytes[11]=='E'; 
    bool valid_ftm = (hbytes[12]=='f' && hbytes[13]=='m' && hbytes[14]=='t' && hbytes[15]==' '); 
    bool valid_data = (hbytes[36]=='d' && hbytes[37]=='a' && hbytes[38]=='t' && hbytes[39]=='a'); 

    LogStream(LOG_DEBUG) << "WavFile::WavFile - valid_riff="<<valid_riff<<" valid_wave="<<valid_wave<<" valid_ftm="<<valid_ftm<<" valid_data="<<valid_data; 
    if(!(valid_data && valid_ftm && valid_riff)) 
     throw std::invalid_argument("WavFile::WavFile : Invalid argument - unable to open wavfile "+filename); 

    int audioFormat = ReadShort(hbytes , 20); 
    int SubChunk1Size = ReadInt(hbytes , 16); 

    if(audioFormat != 1 || SubChunk1Size != 16) 
     throw std::invalid_argument("WavFile::WavFile : Only uncompressed PCM wave format supported."+filename);  

    int subChunk2size = ReadInt(hbytes , 40); 
    m_header.num_channels = ReadShort(hbytes , 22); 
    m_header.sample_rate = ReadInt(hbytes , 24); 
    m_header.bits_per_sample = ReadShort(hbytes , 34); 

    LogStream(LOG_DEBUG) << "WavFile::WavFile num_channels="<<m_header.num_channels << " sample_rate="<<m_header.sample_rate<<" bits_per_sample="<<m_header.bits_per_sample; 

    m_pcm_data.resize(subChunk2size/sizeof(int16_t)); 

    LogStream(LOG_DEBUG) << "WavFile::WavFile - subChunk2size = "<<subChunk2size; 
    LogStream(LOG_DEBUG) << "WavFile::WavFile - m_pcm_data.size() = "<<m_pcm_data.size(); 
    ifs.read((char*)m_pcm_data.data() , subChunk2size); 

    LogStream(LOG_DEBUG) << "WavFile: ifstream failbit="<<ifs.fail()<<" badbit="<<ifs.bad()<<" goodbit="<<ifs.good(); 

    ifs.close(); 

    LogStream(LOG_DEBUG) << "WavFile::WavFile - - - - END READING WAV - - - -\n"; 
    LogStream(LOG_DEBUG) << "WavFile::WavFile"; 
} 
+2

如果你的字符導致負整數,我不確定添加它們會正常工作。在你的類型上使用按位或'unsigned'。 –

回答

1

44100有十六進制值44ac(無符號INT16)和-21436也有十六進制值44ac(簽署INT16) - 中問題在於編譯器在移位之前將每個帶符號的char隱式轉換爲有符號整數。您可避免通過鑄造如下(其中輸出44100):

int main() 
{ 
    char bytes[4] = { 0x44, 0xac, 0x00, 0x00 }; 

    printf("%i\n", (((unsigned char)bytes[3]) << 24) | (((unsigned char)bytes[2]) << 16) | (((unsigned char)bytes[1]) << 8) | ((unsigned char)bytes[0])); 
    return 0; 
} 

或簡單地讀成無符號字節 - 這將避免對其他領域一樣的問題:

int main() 
{ 
    unsigned char bytes[4] = { 0x44, 0xac, 0x00, 0x00 }; 

    printf("%i\n", (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]); 
    return 0; 
} 
+0

將中間值轉換爲無符號仍然給了我值-21436。另外我應該補充說,這個值被存儲爲int。我嘗試存儲爲無符號整數,我得到了值4294945860 – ScottF

+0

第一個解決方案並不適合我。但第二項建議解決了這個問題。讀入一個unsigned char數組以開始。 – ScottF