2013-07-31 93 views
0

我想將WAVE文件加載到數據結構中,然後將其作爲原始副本保存回磁盤。載入和保存似乎工作正常,但複製的WAVE文件不會播放任何聲音(儘管它的打開沒有錯誤)。我想知道這是否與endian-ness有關?加載和保存WAV文件

這是我的數據結構來保存WAVE文件:

struct WaveFile 
{ 
public: 

    static const uint16 NUM_CHARS = 4; 

public: 

    WaveFile() : Data(nullptr) {} 

    ~WaveFile() { delete[] Data; } 

    char ChunkID[NUM_CHARS]; 

    uint32 ChunkSize; 

    char Format[NUM_CHARS]; 

    char SubChunkID[NUM_CHARS]; 

    uint32 SubChunkSize; 

    uint16 AudioFormat; 

    uint16 NumChannels; 

    uint32 SampleRate; 

    uint32 ByteRate; 

    uint16 BlockAlign; 

    uint16 BitsPerSample; 

    char SubChunk2ID[NUM_CHARS]; 

    uint32 SubChunk2Size; 

    byte* Data; 
}; 

這是我如何加載它:

std::ifstream file(filename, std::ios::binary); 

if (file.good()) 
{ 
    file.read(waveFile.ChunkID, WaveFile::NUM_CHARS); 
    file.read(reinterpret_cast<char*>(&waveFile.ChunkSize), size_ui32); 
    file.read(waveFile.Format, WaveFile::NUM_CHARS); 
    file.read(waveFile.SubChunkID, WaveFile::NUM_CHARS); 
    file.read(reinterpret_cast<char*>(&waveFile.SubChunkSize), size_ui32); 
    file.read(reinterpret_cast<char*>(&waveFile.AudioFormat), size_ui16); 
    file.read(reinterpret_cast<char*>(&waveFile.NumChannels), size_ui16); 
    file.read(reinterpret_cast<char*>(&waveFile.SampleRate), size_ui32); 
    file.read(reinterpret_cast<char*>(&waveFile.ByteRate), size_ui32); 
    file.read(reinterpret_cast<char*>(&waveFile.BlockAlign), size_ui16); 
    file.read(reinterpret_cast<char*>(&waveFile.BitsPerSample), size_ui16); 
    file.read(waveFile.SubChunk2ID, WaveFile::NUM_CHARS); 
    file.read(reinterpret_cast<char*>(&waveFile.SubChunk2Size), size_ui32); 
    waveFile.Data = new byte[waveFile.SubChunk2Size]; 
    file.read(reinterpret_cast<char*>(waveFile.Data), sizeof(waveFile.SubChunk2Size)); 
    file.close(); 
} 

而且這是我寫的數據備份到一個文件:

std::ofstream file(outfile, std::ios::binary); 

if (file.good()) 
{ 
    file.flush(); 
    file.write(waveFile.ChunkID, WaveFile::NUM_CHARS); 
    file.write(reinterpret_cast<const char*>(&waveFile.ChunkSize), size_ui32); 
    file.write(waveFile.Format, WaveFile::NUM_CHARS); 
    file.write(waveFile.SubChunkID, WaveFile::NUM_CHARS); 
    file.write(reinterpret_cast<const char*>(&waveFile.SubChunkSize), size_ui32); 
    file.write(reinterpret_cast<const char*>(&waveFile.AudioFormat), size_ui16); 
    file.write(reinterpret_cast<const char*>(&waveFile.NumChannels), size_ui16); 
    file.write(reinterpret_cast<const char*>(&waveFile.SampleRate), size_ui32); 
    file.write(reinterpret_cast<const char*>(&waveFile.ByteRate), size_ui32); 
    file.write(reinterpret_cast<const char*>(&waveFile.BlockAlign), size_ui16); 
    file.write(reinterpret_cast<const char*>(&waveFile.BitsPerSample), size_ui16); 
    file.write(waveFile.SubChunk2ID, WaveFile::NUM_CHARS); 
    file.write(reinterpret_cast<const char*>(&waveFile.SubChunk2Size), size_ui32); 
    file.write(reinterpret_cast<const char*>(waveFile.Data), waveFile.SubChunk2Size); 
    file.close(); 
} 

副本的大小與原始大小相同。如果有人想知道,uint16,uint32和byte只是unsigned short,unsigned int和unsigned char的typedef。 size_ui32變量就是這樣:

static const uint32 size_ui32 = sizeof(uint32); 
static const uint32 size_ui16 = sizeof(uint16); 

沒關係,似乎無法找出我出錯的地方。

乾杯任何幫助。

回答

1

在發佈這個問題後,我剛剛發現了這個問題。

當讀取數據在我做這個:

file.read(reinterpret_cast<char*>(waveFile.Data), sizeof(waveFile.SubChunk2Size)); 

這應該是:當我刪除的sizeof

file.read(reinterpret_cast<char*>(waveFile.Data), waveFile.SubChunk2Size); 

曾任職()。傻我。

0

這適用於大多數wavefiles,但某些標題可能包含特定的用戶數據。您可以使用struct WAVEHEADER的sigle寫入:

struct WAVEFILEHEADER 
{ 
    // don't change the order of attributes 
    char m_lpcChunkId[4]; 
    int m_iChunkSize; 
    char m_lpcFormat[4]; 
    char m_lpcSubChunkFmt[4]; 
    int m_iSubChunkFmtSize; 
    short int m_siAudioFormat; 
    short int m_siNumChannels; 

    int m_iSampleRate; 
    int m_iByteRate; 
    short int m_siBlockAlign; 
    short int m_siBitsPerSample; 

    char m_lpcChunkData[4]; 
    int m_iSubChunkDataSize; 
    // unsigned char * m_data; 
}; 

WAVEFILEHEADER whdr; 
FILE* fid = fopen("newaudio.wav","wb"); // important to use binary file 

// some inicialization for whdr - RIFF etc. 
// You can use only 1 write to save whole header: 
fwrite(&whdr, 1, sizeof(WAVEFILEHEADER), fid); 

// or you can read wav header 
fread(&whdr, 1, sizeof(WAVEFILEHEADER), fid); 
// check chunk size, few headers have aditional 2 bytes (by definition user data, but they was always 0x0000)