2013-07-31 2 views
0

Я пытаюсь загрузить файл WAVE в структуру данных, а затем сохранить его обратно на диск в качестве копии оригинала. Загрузка и сохранение будут работать нормально, но скопированный WAVE-файл не будет воспроизводить звук (хотя он открывается без ошибок). Мне интересно, если это имеет какое-либо отношение к энтианности?Загрузка и сохранение 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 и байт являются просто typedefs для unsigned short, unsigned int и unsigned char. size_ui32 переменные только это:

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

That't об этом, не могу показаться, чтобы выяснить, где я не так.

Приветствия за любую помощь.

ответ

1

После публикации этого вопроса я только что обнаружил проблему.

При чтении данных в я сделал это:

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

, которые должны быть:

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

работал, когда я удалил SizeOf(). Дурак я.

0

Это работает на большинстве волновых файлов, но некоторые заголовки могут содержать конкретные пользовательские данные. Вы можете использовать запись со слов struct WAVEHEADER:

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) 
Смежные вопросы