Загрузка и сохранение файла WAV

Я пытаюсь загрузить файл WAVE в структуру данных, а затем сохранить его на диск как копию оригинала. Загрузка и сохранение работают нормально, но скопированный файл WAVE не воспроизводит звук (хотя он открывается без ошибок). Мне интересно, это как-то связано с порядком байтов?

Это моя структура данных для хранения файла 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 являются просто typedefs для unsigned short, unsigned int и unsigned char. Переменные size_ui32 это просто:

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

Дело не в этом, похоже, не могу понять, где я ошибся.

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

0

Решение

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

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

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

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

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

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

1

Другие решения

Это работает на большинстве волновых файлов, но некоторые заголовки могут содержать определенные пользовательские данные. Вы можете использовать sigle write для 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)
0

По вопросам рекламы [email protected]