Added support for extensible format PCM wave files.
This commit is contained in:
parent
2aa70def6f
commit
fc54dba3d7
@ -31,6 +31,7 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace
|
||||
@ -88,6 +89,14 @@ namespace
|
||||
}
|
||||
|
||||
const sf::Uint64 mainChunkSize = 12;
|
||||
|
||||
const sf::Uint16 waveFormatPcm = 1;
|
||||
|
||||
const sf::Uint16 waveFormatExtensible= 65534;
|
||||
|
||||
const char* waveSubformatPcm =
|
||||
"\x01\x00\x00\x00\x00\x00\x10\x00"
|
||||
"\x80\x00\x00\xAA\x00\x38\x9B\x71";
|
||||
}
|
||||
|
||||
namespace sf
|
||||
@ -226,6 +235,9 @@ bool SoundFileReaderWav::parseHeader(Info& info)
|
||||
Uint32 subChunkSize = 0;
|
||||
if (!decode(*m_stream, subChunkSize))
|
||||
return false;
|
||||
Int64 subChunkStart = m_stream->tell();
|
||||
if (subChunkStart == -1)
|
||||
return false;
|
||||
|
||||
// Check which chunk it is
|
||||
if ((subChunkId[0] == 'f') && (subChunkId[1] == 'm') && (subChunkId[2] == 't') && (subChunkId[3] == ' '))
|
||||
@ -236,7 +248,7 @@ bool SoundFileReaderWav::parseHeader(Info& info)
|
||||
Uint16 format = 0;
|
||||
if (!decode(*m_stream, format))
|
||||
return false;
|
||||
if (format != 1) // PCM
|
||||
if ((format != waveFormatPcm) && (format != waveFormatExtensible))
|
||||
return false;
|
||||
|
||||
// Channel count
|
||||
@ -272,12 +284,45 @@ bool SoundFileReaderWav::parseHeader(Info& info)
|
||||
}
|
||||
m_bytesPerSample = bitsPerSample / 8;
|
||||
|
||||
// Skip potential extra information (should not exist for PCM)
|
||||
if (subChunkSize > 16)
|
||||
if (format == waveFormatExtensible)
|
||||
{
|
||||
if (m_stream->seek(m_stream->tell() + subChunkSize - 16) == -1)
|
||||
// Extension size
|
||||
Uint16 extensionSize = 0;
|
||||
if (!decode(*m_stream, extensionSize))
|
||||
return false;
|
||||
|
||||
// Valid bits per sample
|
||||
Uint16 validBitsPerSample = 0;
|
||||
if (!decode(*m_stream, validBitsPerSample))
|
||||
return false;
|
||||
|
||||
// Channel mask
|
||||
Uint32 channelMask = 0;
|
||||
if (!decode(*m_stream, channelMask))
|
||||
return false;
|
||||
|
||||
// Subformat
|
||||
char subformat[16];
|
||||
if (m_stream->read(subformat, sizeof(subformat)) != sizeof(subformat))
|
||||
return false;
|
||||
|
||||
if (std::memcmp(subformat, waveSubformatPcm, sizeof(subformat)) != 0)
|
||||
{
|
||||
err() << "Unsupported format: extensible format with non-PCM subformat" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validBitsPerSample != bitsPerSample)
|
||||
{
|
||||
err() << "Unsupported format: sample size (" << validBitsPerSample << " bits) and "
|
||||
"sample container size (" << bitsPerSample << " bits) differ" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip potential extra information
|
||||
if (m_stream->seek(subChunkStart + subChunkSize) == -1)
|
||||
return false;
|
||||
}
|
||||
else if ((subChunkId[0] == 'd') && (subChunkId[1] == 'a') && (subChunkId[2] == 't') && (subChunkId[3] == 'a'))
|
||||
{
|
||||
@ -287,7 +332,7 @@ bool SoundFileReaderWav::parseHeader(Info& info)
|
||||
info.sampleCount = subChunkSize / m_bytesPerSample;
|
||||
|
||||
// Store the start and end position of samples in the file
|
||||
m_dataStart = m_stream->tell();
|
||||
m_dataStart = subChunkStart;
|
||||
m_dataEnd = m_dataStart + info.sampleCount * m_bytesPerSample;
|
||||
|
||||
dataChunkFound = true;
|
||||
|
Loading…
Reference in New Issue
Block a user