(PCM) WAVE のヘッダーを表す密集した構造体がある場合、次のようになります。
struct Riff
{
char chunkId[4]; // "RIFF" (assuming char is 8 bits)
int chunkSize; // (assuming int is 32 bits)
char format[4]; // "WAVE"
};
struct Format
{
char chunkId[4]; // "fmt "
int chunkSize;
short format; // assuming short is 16 bits
short numChannels;
int sampleRate;
int byteRate;
short align;
short bitsPerSample;
};
struct Data
{
char chunkId[4]; // "data"
int chunkSize; // length of data
char* data;
};
struct Wave // Actual structure of a PCM WAVE file
{
Riff riffHeader;
Format formatHeader;
Data dataHeader;
};
基本的に、あなたの問題は、コード内のformat_length
( Format::chunkSize
in my struct) とavg_bytes_sec
( Format::byteRate
in my struct) がそれぞれ2バイトですが、それぞれ4バイトである必要があります。データサブチャンクのヘッダーも読み取っていませんが、それは意図的だと思いますか?
読むには、次のようなことができます。
void readWave(std::ifstream& file, Wave& wave)
{
// First read the RIFF header
file.read(wave.riffHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize), 4);
file.read(wave.riffHeader.format, 4);
// Now read the FORMAT header
file.read(wave.formatHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.format), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.align), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);
// Now read the DATA header
file.read(wave.dataHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize), 4);
// The actual data goes in wave.dataHeader.data, so you can allocate it
// and then read direclty into it now
}
Michael のリンクは、私が WAVE ファイルを読み書きする必要があるときにいつも使用するものです(何度かやらなければなりませんでした)。注意深く読むことをお勧めします。
「データ」チャンクの前に WAVE ファイルに余分なチャンクがある場合、このコードはそれらをスキップできるはずです。
void readWave(std::ifstream& file, Wave& wave)
{
// First read the RIFF header
file.read(wave.riffHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize), 4);
file.read(wave.riffHeader.format, 4);
// Now read the FORMAT header
file.read(wave.formatHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.format), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.align), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);
// WAVE files are just a special type of RIFF file, so it's possible
// there are other chunks, like "fact" chunks. We'll skip over these
// extra chunks until we find a "data" chunk
char chunkId[4] = {0};
int chunkSize = 0;
while (file.read(chunkId, 4) &&
(chunkId[0] != 'd' ||
chunkId[1] != 'a' ||
chunkId[2] != 't' ||
chunkId[3] != 'a'))
{
file.read(reinterpret_cast<char*>(&chunkSize), 4); // Read the chunk's size
file.seekg(chunkSize, std::ios_base::cur); // Skip the chunk
}
// We've found the DATA chunk and header
wave.dataHeader.chunkId[0] = chunkId[0];
wave.dataHeader.chunkId[1] = chunkId[1];
wave.dataHeader.chunkId[2] = chunkId[2];
wave.dataHeader.chunkId[3] = chunkId[3];
file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize), 4);
// The actual data goes in wave.dataHeader.data, so you can allocate it
// and then read direclty into it now
}