mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
Update external libraries.
This commit is contained in:
+435
-115
@@ -1,5 +1,5 @@
|
|||||||
// FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
// FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// dr_flac - v0.9.11 - 2018-08-29
|
// dr_flac - v0.10.0 - 2018-09-11
|
||||||
//
|
//
|
||||||
// David Reid - mackron@gmail.com
|
// David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@@ -80,16 +80,11 @@
|
|||||||
// #define these options before including this file.
|
// #define these options before including this file.
|
||||||
//
|
//
|
||||||
// #define DR_FLAC_NO_STDIO
|
// #define DR_FLAC_NO_STDIO
|
||||||
// Disable drflac_open_file().
|
// Disable drflac_open_file() and family.
|
||||||
//
|
//
|
||||||
// #define DR_FLAC_NO_OGG
|
// #define DR_FLAC_NO_OGG
|
||||||
// Disables support for Ogg/FLAC streams.
|
// Disables support for Ogg/FLAC streams.
|
||||||
//
|
//
|
||||||
// #define DR_FLAC_NO_WIN32_IO
|
|
||||||
// In the Win32 build, dr_flac uses the Win32 IO APIs for drflac_open_file() by default. This setting will make it use the
|
|
||||||
// standard FILE APIs instead. Ignored when DR_FLAC_NO_STDIO is #defined. (The rationale for this configuration is that
|
|
||||||
// there's a bug in one compiler's Win32 implementation of the FILE APIs which is not present in the Win32 IO APIs.)
|
|
||||||
//
|
|
||||||
// #define DR_FLAC_BUFFER_SIZE <number>
|
// #define DR_FLAC_BUFFER_SIZE <number>
|
||||||
// Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls
|
// Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls
|
||||||
// back to the client for more data. Larger values means more memory, but better performance. My tests show diminishing
|
// back to the client for more data. Larger values means more memory, but better performance. My tests show diminishing
|
||||||
@@ -109,8 +104,6 @@
|
|||||||
// - dr_flac does not currently support changing the sample rate nor channel count mid stream.
|
// - dr_flac does not currently support changing the sample rate nor channel count mid stream.
|
||||||
// - Audio data is output as signed 32-bit PCM, regardless of the bits per sample the FLAC stream is encoded as.
|
// - Audio data is output as signed 32-bit PCM, regardless of the bits per sample the FLAC stream is encoded as.
|
||||||
// - This has not been tested on big-endian architectures.
|
// - This has not been tested on big-endian architectures.
|
||||||
// - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody
|
|
||||||
// knows where I can find some test files for this, let me know.
|
|
||||||
// - dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
|
// - dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
|
||||||
// - When using Ogg encapsulation, a corrupted metadata block will result in drflac_open_with_metadata() and drflac_open()
|
// - When using Ogg encapsulation, a corrupted metadata block will result in drflac_open_with_metadata() and drflac_open()
|
||||||
// returning inconsistent samples.
|
// returning inconsistent samples.
|
||||||
@@ -276,7 +269,7 @@ typedef struct
|
|||||||
drflac_uint32 vendorLength;
|
drflac_uint32 vendorLength;
|
||||||
const char* vendor;
|
const char* vendor;
|
||||||
drflac_uint32 commentCount;
|
drflac_uint32 commentCount;
|
||||||
const char* comments;
|
const void* pComments;
|
||||||
} vorbis_comment;
|
} vorbis_comment;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@@ -285,7 +278,7 @@ typedef struct
|
|||||||
drflac_uint64 leadInSampleCount;
|
drflac_uint64 leadInSampleCount;
|
||||||
drflac_bool32 isCD;
|
drflac_bool32 isCD;
|
||||||
drflac_uint8 trackCount;
|
drflac_uint8 trackCount;
|
||||||
const drflac_uint8* pTrackData;
|
const void* pTrackData;
|
||||||
} cuesheet;
|
} cuesheet;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@@ -728,13 +721,49 @@ typedef struct
|
|||||||
|
|
||||||
// Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT
|
// Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT
|
||||||
// metadata block.
|
// metadata block.
|
||||||
void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const char* pComments);
|
void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
|
||||||
|
|
||||||
// Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The
|
// Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The
|
||||||
// returned string is NOT null terminated.
|
// returned string is NOT null terminated.
|
||||||
const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut);
|
const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut);
|
||||||
|
|
||||||
|
|
||||||
|
// Structure representing an iterator for cuesheet tracks in a CUESHEET metadata block.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
drflac_uint32 countRemaining;
|
||||||
|
const char* pRunningData;
|
||||||
|
} drflac_cuesheet_track_iterator;
|
||||||
|
|
||||||
|
// Packing is important on this structure because we map this directly to the raw data within the CUESHEET metadata block.
|
||||||
|
#pragma pack(4)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
drflac_uint64 offset;
|
||||||
|
drflac_uint8 index;
|
||||||
|
drflac_uint8 reserved[3];
|
||||||
|
} drflac_cuesheet_track_index;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
drflac_uint64 offset;
|
||||||
|
drflac_uint8 trackNumber;
|
||||||
|
char ISRC[12];
|
||||||
|
drflac_bool8 isAudio;
|
||||||
|
drflac_bool8 preEmphasis;
|
||||||
|
drflac_uint8 indexCount;
|
||||||
|
const drflac_cuesheet_track_index* pIndexPoints;
|
||||||
|
} drflac_cuesheet_track;
|
||||||
|
|
||||||
|
// Initializes a cuesheet track iterator. This can be used for iterating over the cuesheet tracks in a CUESHEET metadata
|
||||||
|
// block.
|
||||||
|
void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
|
||||||
|
|
||||||
|
// Goes to the next cuesheet track in the given iterator. If DRFLAC_FALSE is returned it means there are no more comments.
|
||||||
|
drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@@ -1295,15 +1324,12 @@ static DRFLAC_INLINE drflac_uint16 drflac_crc16(drflac_uint16 crc, drflac_cache_
|
|||||||
// from onRead() is read into.
|
// from onRead() is read into.
|
||||||
#define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache))
|
#define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache))
|
||||||
#define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8)
|
#define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8)
|
||||||
#define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - ((bs)->consumedBits))
|
#define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (bs)->consumedBits)
|
||||||
#ifdef DRFLAC_64BIT
|
#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~((~(drflac_cache_t)0) >> (_bitCount)))
|
||||||
#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((drflac_uint64)-1LL) >> (_bitCount)))
|
|
||||||
#else
|
|
||||||
#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((drflac_uint32)-1) >> (_bitCount)))
|
|
||||||
#endif
|
|
||||||
#define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount))
|
#define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount))
|
||||||
#define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount))
|
#define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount))
|
||||||
#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), _bitCount) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), _bitCount))
|
#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)))
|
||||||
|
#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, _bitCount)(DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> (DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)) & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1)))
|
||||||
#define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2))
|
#define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2))
|
||||||
#define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0]))
|
#define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0]))
|
||||||
#define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line)
|
#define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line)
|
||||||
@@ -1418,6 +1444,7 @@ static drflac_bool32 drflac__reload_cache(drflac_bs* bs)
|
|||||||
// data from the unaligned cache.
|
// data from the unaligned cache.
|
||||||
size_t bytesRead = bs->unalignedByteCount;
|
size_t bytesRead = bs->unalignedByteCount;
|
||||||
if (bytesRead == 0) {
|
if (bytesRead == 0) {
|
||||||
|
bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs); // <-- The stream has been exhausted, so marked the bits as consumed.
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1425,7 +1452,7 @@ static drflac_bool32 drflac__reload_cache(drflac_bs* bs)
|
|||||||
bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8;
|
bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8;
|
||||||
|
|
||||||
bs->cache = drflac__be2host__cache_line(bs->unalignedCache);
|
bs->cache = drflac__be2host__cache_line(bs->unalignedCache);
|
||||||
bs->cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_SIZE_BITS(bs) - bs->consumedBits); // <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property.
|
bs->cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_BITS_REMAINING(bs)); // <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property.
|
||||||
bs->unalignedByteCount = 0; // <-- At this point the unaligned bytes have been moved into the cache and we thus have no more unaligned bytes.
|
bs->unalignedByteCount = 0; // <-- At this point the unaligned bytes have been moved into the cache and we thus have no more unaligned bytes.
|
||||||
|
|
||||||
#ifndef DR_FLAC_NO_CRC
|
#ifndef DR_FLAC_NO_CRC
|
||||||
@@ -1464,15 +1491,26 @@ static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs* bs, unsigned i
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
|
if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
|
||||||
|
// If we want to load all 32-bits from a 32-bit cache we need to do it slightly differently because we can't do
|
||||||
|
// a 32-bit shift on a 32-bit integer. This will never be the case on 64-bit caches, so we can have a slightly
|
||||||
|
// more optimal solution for this.
|
||||||
|
#ifdef DRFLAC_64BIT
|
||||||
|
*pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
|
||||||
|
bs->consumedBits += bitCount;
|
||||||
|
bs->cache <<= bitCount;
|
||||||
|
#else
|
||||||
if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
|
if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
|
||||||
*pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
|
*pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
|
||||||
bs->consumedBits += bitCount;
|
bs->consumedBits += bitCount;
|
||||||
bs->cache <<= bitCount;
|
bs->cache <<= bitCount;
|
||||||
} else {
|
} else {
|
||||||
|
// Cannot shift by 32-bits, so need to do it differently.
|
||||||
*pResultOut = (drflac_uint32)bs->cache;
|
*pResultOut = (drflac_uint32)bs->cache;
|
||||||
bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs);
|
bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs);
|
||||||
bs->cache = 0;
|
bs->cache = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
} else {
|
} else {
|
||||||
// It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
|
// It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
|
||||||
@@ -1784,6 +1822,8 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
|
#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
|
||||||
|
#include <intrin.h> // For BitScanReverse().
|
||||||
|
|
||||||
static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
|
static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
|
||||||
{
|
{
|
||||||
drflac_uint32 n;
|
drflac_uint32 n;
|
||||||
@@ -2250,9 +2290,9 @@ static drflac_bool32 drflac__read_rice_parts__reference(drflac_bs* bs, drflac_ui
|
|||||||
|
|
||||||
static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
|
static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
|
||||||
{
|
{
|
||||||
drflac_cache_t riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam);
|
drflac_assert(riceParam > 0); // <-- riceParam should never be 0. drflac__read_rice_parts__param_equals_zero() should be used instead for this case.
|
||||||
drflac_cache_t resultHiShift = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParam;
|
|
||||||
|
|
||||||
|
drflac_cache_t riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam);
|
||||||
|
|
||||||
drflac_uint32 zeroCounter = 0;
|
drflac_uint32 zeroCounter = 0;
|
||||||
while (bs->cache == 0) {
|
while (bs->cache == 0) {
|
||||||
@@ -2270,19 +2310,17 @@ static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac
|
|||||||
drflac_uint32 riceParamPart;
|
drflac_uint32 riceParamPart;
|
||||||
drflac_uint32 riceLength = setBitOffsetPlus1 + riceParam;
|
drflac_uint32 riceLength = setBitOffsetPlus1 + riceParam;
|
||||||
if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
|
if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
|
||||||
riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> (DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceLength));
|
riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceLength));
|
||||||
|
|
||||||
bs->consumedBits += riceLength;
|
bs->consumedBits += riceLength;
|
||||||
bs->cache <<= riceLength;
|
bs->cache <<= riceLength;
|
||||||
} else {
|
} else {
|
||||||
bs->consumedBits += riceLength;
|
bs->consumedBits += riceLength;
|
||||||
if (setBitOffsetPlus1 < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
|
bs->cache <<= setBitOffsetPlus1 & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1); // <-- Equivalent to "if (setBitOffsetPlus1 < DRFLAC_CACHE_L1_SIZE_BITS(bs)) { bs->cache <<= setBitOffsetPlus1; }"
|
||||||
bs->cache <<= setBitOffsetPlus1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
|
// It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
|
||||||
drflac_uint32 bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
|
drflac_uint32 bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
|
||||||
drflac_cache_t resultHi = bs->cache & riceParamMask; // <-- This mask is OK because all bits after the first bits are always zero.
|
drflac_cache_t resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, riceParam); // <-- Use DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE() if ever this function allows riceParam=0.
|
||||||
|
|
||||||
if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
|
if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
|
||||||
#ifndef DR_FLAC_NO_CRC
|
#ifndef DR_FLAC_NO_CRC
|
||||||
@@ -2300,7 +2338,62 @@ static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
riceParamPart = (drflac_uint32)((resultHi >> resultHiShift) | DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo));
|
riceParamPart = (drflac_uint32)(resultHi | DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
|
||||||
|
|
||||||
|
bs->consumedBits += bitCountLo;
|
||||||
|
bs->cache <<= bitCountLo;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pZeroCounterOut = zeroCounter;
|
||||||
|
*pRiceParamPartOut = riceParamPart;
|
||||||
|
return DRFLAC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts__param_equals_zero(drflac_bs* bs, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
|
||||||
|
{
|
||||||
|
drflac_cache_t riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(0);
|
||||||
|
|
||||||
|
drflac_uint32 zeroCounter = 0;
|
||||||
|
while (bs->cache == 0) {
|
||||||
|
zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
|
||||||
|
if (!drflac__reload_cache(bs)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drflac_uint32 setBitOffsetPlus1 = drflac__clz(bs->cache);
|
||||||
|
zeroCounter += setBitOffsetPlus1;
|
||||||
|
setBitOffsetPlus1 += 1;
|
||||||
|
|
||||||
|
|
||||||
|
drflac_uint32 riceParamPart;
|
||||||
|
drflac_uint32 riceLength = setBitOffsetPlus1;
|
||||||
|
if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
|
||||||
|
riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceLength));
|
||||||
|
|
||||||
|
bs->consumedBits += riceLength;
|
||||||
|
bs->cache <<= riceLength;
|
||||||
|
} else {
|
||||||
|
// It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
|
||||||
|
drflac_uint32 bitCountLo = riceLength + bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
|
||||||
|
|
||||||
|
if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
|
||||||
|
#ifndef DR_FLAC_NO_CRC
|
||||||
|
drflac__update_crc16(bs);
|
||||||
|
#endif
|
||||||
|
bs->cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
|
||||||
|
bs->consumedBits = 0;
|
||||||
|
#ifndef DR_FLAC_NO_CRC
|
||||||
|
bs->crc16Cache = bs->cache;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// Slow path. We need to fetch more data from the client.
|
||||||
|
if (!drflac__reload_cache(bs)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
riceParamPart = (drflac_uint32)(DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
|
||||||
|
|
||||||
bs->consumedBits += bitCountLo;
|
bs->consumedBits += bitCountLo;
|
||||||
bs->cache <<= bitCountLo;
|
bs->cache <<= bitCountLo;
|
||||||
@@ -2391,12 +2484,94 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__simple(drflac_b
|
|||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static drflac_bool32 drflac__decode_samples_with_residual__rice__param_equals_zero(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
|
||||||
|
{
|
||||||
|
drflac_assert(bs != NULL);
|
||||||
|
drflac_assert(count > 0);
|
||||||
|
drflac_assert(pSamplesOut != NULL);
|
||||||
|
|
||||||
|
static drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
|
||||||
|
|
||||||
|
drflac_uint32 zeroCountPart0;
|
||||||
|
drflac_uint32 zeroCountPart1;
|
||||||
|
drflac_uint32 zeroCountPart2;
|
||||||
|
drflac_uint32 zeroCountPart3;
|
||||||
|
drflac_uint32 riceParamPart0;
|
||||||
|
drflac_uint32 riceParamPart1;
|
||||||
|
drflac_uint32 riceParamPart2;
|
||||||
|
drflac_uint32 riceParamPart3;
|
||||||
|
drflac_uint32 i4 = 0;
|
||||||
|
drflac_uint32 count4 = count >> 2;
|
||||||
|
while (i4 < count4) {
|
||||||
|
// Rice extraction.
|
||||||
|
if (!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart0, &riceParamPart0) ||
|
||||||
|
!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart1, &riceParamPart1) ||
|
||||||
|
!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart2, &riceParamPart2) ||
|
||||||
|
!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart3, &riceParamPart3)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
riceParamPart0 |= zeroCountPart0;
|
||||||
|
riceParamPart1 |= zeroCountPart1;
|
||||||
|
riceParamPart2 |= zeroCountPart2;
|
||||||
|
riceParamPart3 |= zeroCountPart3;
|
||||||
|
|
||||||
|
riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
|
||||||
|
riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
|
||||||
|
riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
|
||||||
|
riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
|
||||||
|
|
||||||
|
if (bitsPerSample > 16) {
|
||||||
|
pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
|
||||||
|
pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 1);
|
||||||
|
pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 2);
|
||||||
|
pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 3);
|
||||||
|
} else {
|
||||||
|
pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
|
||||||
|
pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 1);
|
||||||
|
pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 2);
|
||||||
|
pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
i4 += 1;
|
||||||
|
pSamplesOut += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
drflac_uint32 i = i4 << 2;
|
||||||
|
while (i < count) {
|
||||||
|
// Rice extraction.
|
||||||
|
if (!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart0, &riceParamPart0)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rice reconstruction.
|
||||||
|
riceParamPart0 |= zeroCountPart0;
|
||||||
|
riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
|
||||||
|
|
||||||
|
// Sample reconstruction.
|
||||||
|
if (bitsPerSample > 16) {
|
||||||
|
pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
|
||||||
|
} else {
|
||||||
|
pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
pSamplesOut += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DRFLAC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
|
static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
|
return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
|
||||||
#else
|
#else
|
||||||
|
if (riceParam != 0) {
|
||||||
return drflac__decode_samples_with_residual__rice__simple(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
|
return drflac__decode_samples_with_residual__rice__simple(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
|
||||||
|
} else {
|
||||||
|
return drflac__decode_samples_with_residual__rice__param_equals_zero(bs, bitsPerSample, count, order, shift, coefficients, pSamplesOut);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2406,13 +2581,22 @@ static drflac_bool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, drflac_
|
|||||||
drflac_assert(bs != NULL);
|
drflac_assert(bs != NULL);
|
||||||
drflac_assert(count > 0);
|
drflac_assert(count > 0);
|
||||||
|
|
||||||
for (drflac_uint32 i = 0; i < count; ++i) {
|
|
||||||
drflac_uint32 zeroCountPart;
|
drflac_uint32 zeroCountPart;
|
||||||
drflac_uint32 riceParamPart;
|
drflac_uint32 riceParamPart;
|
||||||
|
|
||||||
|
if (riceParam != 0) {
|
||||||
|
for (drflac_uint32 i = 0; i < count; ++i) {
|
||||||
if (!drflac__read_rice_parts(bs, riceParam, &zeroCountPart, &riceParamPart)) {
|
if (!drflac__read_rice_parts(bs, riceParam, &zeroCountPart, &riceParamPart)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (drflac_uint32 i = 0; i < count; ++i) {
|
||||||
|
if (!drflac__read_rice_parts__param_equals_zero(bs, &zeroCountPart, &riceParamPart)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
}
|
}
|
||||||
@@ -2421,13 +2605,17 @@ static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs*
|
|||||||
{
|
{
|
||||||
drflac_assert(bs != NULL);
|
drflac_assert(bs != NULL);
|
||||||
drflac_assert(count > 0);
|
drflac_assert(count > 0);
|
||||||
drflac_assert(unencodedBitsPerSample > 0 && unencodedBitsPerSample <= 32);
|
drflac_assert(unencodedBitsPerSample <= 31); // <-- unencodedBitsPerSample is a 5 bit number, so cannot exceed 31.
|
||||||
drflac_assert(pSamplesOut != NULL);
|
drflac_assert(pSamplesOut != NULL);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
|
if (unencodedBitsPerSample > 0) {
|
||||||
if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) {
|
if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pSamplesOut[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (bitsPerSample > 16) {
|
if (bitsPerSample > 16) {
|
||||||
pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
|
pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
|
||||||
@@ -2486,14 +2674,14 @@ static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_
|
|||||||
if (!drflac__read_uint8(bs, 4, &riceParam)) {
|
if (!drflac__read_uint8(bs, 4, &riceParam)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
if (riceParam == 16) {
|
if (riceParam == 15) {
|
||||||
riceParam = 0xFF;
|
riceParam = 0xFF;
|
||||||
}
|
}
|
||||||
} else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
|
} else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
|
||||||
if (!drflac__read_uint8(bs, 5, &riceParam)) {
|
if (!drflac__read_uint8(bs, 5, &riceParam)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
if (riceParam == 32) {
|
if (riceParam == 31) {
|
||||||
riceParam = 0xFF;
|
riceParam = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2552,6 +2740,17 @@ static drflac_bool32 drflac__read_and_seek_residual(drflac_bs* bs, drflac_uint32
|
|||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From the FLAC spec:
|
||||||
|
// The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
|
||||||
|
if (partitionOrder > 8) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation check.
|
||||||
|
if ((blockSize / (1 << partitionOrder)) <= order) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
drflac_uint32 samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
|
drflac_uint32 samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
|
||||||
drflac_uint32 partitionsRemaining = (1 << partitionOrder);
|
drflac_uint32 partitionsRemaining = (1 << partitionOrder);
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -2561,14 +2760,14 @@ static drflac_bool32 drflac__read_and_seek_residual(drflac_bs* bs, drflac_uint32
|
|||||||
if (!drflac__read_uint8(bs, 4, &riceParam)) {
|
if (!drflac__read_uint8(bs, 4, &riceParam)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
if (riceParam == 16) {
|
if (riceParam == 15) {
|
||||||
riceParam = 0xFF;
|
riceParam = 0xFF;
|
||||||
}
|
}
|
||||||
} else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
|
} else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
|
||||||
if (!drflac__read_uint8(bs, 5, &riceParam)) {
|
if (!drflac__read_uint8(bs, 5, &riceParam)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
if (riceParam == 32) {
|
if (riceParam == 31) {
|
||||||
riceParam = 0xFF;
|
riceParam = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2725,6 +2924,9 @@ static drflac_bool32 drflac__read_next_frame_header(drflac_bs* bs, drflac_uint8
|
|||||||
if (!drflac__read_uint8(bs, 1, &reserved)) {
|
if (!drflac__read_uint8(bs, 1, &reserved)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
if (reserved == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
crc8 = drflac_crc8(crc8, reserved, 1);
|
crc8 = drflac_crc8(crc8, reserved, 1);
|
||||||
|
|
||||||
|
|
||||||
@@ -2739,6 +2941,9 @@ static drflac_bool32 drflac__read_next_frame_header(drflac_bs* bs, drflac_uint8
|
|||||||
if (!drflac__read_uint8(bs, 4, &blockSize)) {
|
if (!drflac__read_uint8(bs, 4, &blockSize)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
if (blockSize == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
crc8 = drflac_crc8(crc8, blockSize, 4);
|
crc8 = drflac_crc8(crc8, blockSize, 4);
|
||||||
|
|
||||||
|
|
||||||
@@ -2753,6 +2958,9 @@ static drflac_bool32 drflac__read_next_frame_header(drflac_bs* bs, drflac_uint8
|
|||||||
if (!drflac__read_uint8(bs, 4, &channelAssignment)) {
|
if (!drflac__read_uint8(bs, 4, &channelAssignment)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
if (channelAssignment > 10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
crc8 = drflac_crc8(crc8, channelAssignment, 4);
|
crc8 = drflac_crc8(crc8, channelAssignment, 4);
|
||||||
|
|
||||||
|
|
||||||
@@ -2760,12 +2968,18 @@ static drflac_bool32 drflac__read_next_frame_header(drflac_bs* bs, drflac_uint8
|
|||||||
if (!drflac__read_uint8(bs, 3, &bitsPerSample)) {
|
if (!drflac__read_uint8(bs, 3, &bitsPerSample)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
if (bitsPerSample == 3 || bitsPerSample == 7) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
crc8 = drflac_crc8(crc8, bitsPerSample, 3);
|
crc8 = drflac_crc8(crc8, bitsPerSample, 3);
|
||||||
|
|
||||||
|
|
||||||
if (!drflac__read_uint8(bs, 1, &reserved)) {
|
if (!drflac__read_uint8(bs, 1, &reserved)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
if (reserved == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
crc8 = drflac_crc8(crc8, reserved, 1);
|
crc8 = drflac_crc8(crc8, reserved, 1);
|
||||||
|
|
||||||
|
|
||||||
@@ -2931,6 +3145,9 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to handle wasted bits per sample.
|
// Need to handle wasted bits per sample.
|
||||||
|
if (pSubframe->wastedBitsPerSample >= pSubframe->bitsPerSample) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample;
|
pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample;
|
||||||
pSubframe->pDecodedSamples = pDecodedSamplesOut;
|
pSubframe->pDecodedSamples = pDecodedSamplesOut;
|
||||||
|
|
||||||
@@ -2981,6 +3198,9 @@ static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to handle wasted bits per sample.
|
// Need to handle wasted bits per sample.
|
||||||
|
if (pSubframe->wastedBitsPerSample >= pSubframe->bitsPerSample) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample;
|
pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample;
|
||||||
pSubframe->pDecodedSamples = NULL;
|
pSubframe->pDecodedSamples = NULL;
|
||||||
|
|
||||||
@@ -3533,6 +3753,10 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
{
|
{
|
||||||
case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION:
|
case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION:
|
||||||
{
|
{
|
||||||
|
if (blockSize < 4) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = DRFLAC_MALLOC(blockSize);
|
void* pRawData = DRFLAC_MALLOC(blockSize);
|
||||||
if (pRawData == NULL) {
|
if (pRawData == NULL) {
|
||||||
@@ -3592,6 +3816,10 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
|
|
||||||
case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT:
|
case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT:
|
||||||
{
|
{
|
||||||
|
if (blockSize < 8) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = DRFLAC_MALLOC(blockSize);
|
void* pRawData = DRFLAC_MALLOC(blockSize);
|
||||||
if (pRawData == NULL) {
|
if (pRawData == NULL) {
|
||||||
@@ -3607,10 +3835,39 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
metadata.rawDataSize = blockSize;
|
metadata.rawDataSize = blockSize;
|
||||||
|
|
||||||
const char* pRunningData = (const char*)pRawData;
|
const char* pRunningData = (const char*)pRawData;
|
||||||
metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
const char* const pRunningDataEnd = (const char*)pRawData + blockSize;
|
||||||
|
|
||||||
|
metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
|
||||||
|
// Need space for the rest of the block
|
||||||
|
if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
|
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
|
||||||
metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
metadata.data.vorbis_comment.comments = pRunningData;
|
|
||||||
|
// Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment
|
||||||
|
if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
metadata.data.vorbis_comment.pComments = pRunningData;
|
||||||
|
|
||||||
|
// Check that the comments section is valid before passing it to the callback
|
||||||
|
for (drflac_uint32 i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
|
||||||
|
if (pRunningDataEnd - pRunningData < 4) {
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
const drflac_uint32 commentLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
pRunningData += commentLength;
|
||||||
|
}
|
||||||
|
|
||||||
onMeta(pUserDataMD, &metadata);
|
onMeta(pUserDataMD, &metadata);
|
||||||
|
|
||||||
DRFLAC_FREE(pRawData);
|
DRFLAC_FREE(pRawData);
|
||||||
@@ -3619,6 +3876,10 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
|
|
||||||
case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
|
case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
|
||||||
{
|
{
|
||||||
|
if (blockSize < 396) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = DRFLAC_MALLOC(blockSize);
|
void* pRawData = DRFLAC_MALLOC(blockSize);
|
||||||
if (pRawData == NULL) {
|
if (pRawData == NULL) {
|
||||||
@@ -3633,12 +3894,39 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
metadata.pRawData = pRawData;
|
metadata.pRawData = pRawData;
|
||||||
metadata.rawDataSize = blockSize;
|
metadata.rawDataSize = blockSize;
|
||||||
|
|
||||||
const char* pRunningData = (const char*)pRawData;
|
char* pRunningData = (char*)pRawData;
|
||||||
|
const char* const pRunningDataEnd = (const char*)pRawData + blockSize;
|
||||||
|
|
||||||
drflac_copy_memory(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
|
drflac_copy_memory(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
|
||||||
metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(drflac_uint64*)pRunningData); pRunningData += 4;
|
metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
|
||||||
metadata.data.cuesheet.isCD = ((pRunningData[0] & 0x80) >> 7) != 0; pRunningData += 259;
|
metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
|
||||||
metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
|
metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
|
||||||
metadata.data.cuesheet.pTrackData = (const drflac_uint8*)pRunningData;
|
metadata.data.cuesheet.pTrackData = pRunningData;
|
||||||
|
|
||||||
|
// Check that the cuesheet tracks are valid before passing it to the callback
|
||||||
|
for (drflac_uint8 i = 0; i < metadata.data.cuesheet.trackCount; ++i) {
|
||||||
|
if (pRunningDataEnd - pRunningData < 36) {
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip to the index point count
|
||||||
|
pRunningData += 35;
|
||||||
|
const drflac_uint8 indexCount = pRunningData[0]; pRunningData += 1;
|
||||||
|
const drflac_uint32 indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
|
||||||
|
if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endian swap.
|
||||||
|
for (drflac_uint8 index = 0; index < indexCount; ++index) {
|
||||||
|
drflac_cuesheet_track_index* pTrack = (drflac_cuesheet_track_index*)pRunningData;
|
||||||
|
pRunningData += sizeof(drflac_cuesheet_track_index);
|
||||||
|
pTrack->offset = drflac__be2host_64(pTrack->offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMeta(pUserDataMD, &metadata);
|
onMeta(pUserDataMD, &metadata);
|
||||||
|
|
||||||
DRFLAC_FREE(pRawData);
|
DRFLAC_FREE(pRawData);
|
||||||
@@ -3647,6 +3935,10 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
|
|
||||||
case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
|
case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
|
||||||
{
|
{
|
||||||
|
if (blockSize < 32) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = DRFLAC_MALLOC(blockSize);
|
void* pRawData = DRFLAC_MALLOC(blockSize);
|
||||||
if (pRawData == NULL) {
|
if (pRawData == NULL) {
|
||||||
@@ -3662,17 +3954,38 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
|
|||||||
metadata.rawDataSize = blockSize;
|
metadata.rawDataSize = blockSize;
|
||||||
|
|
||||||
const char* pRunningData = (const char*)pRawData;
|
const char* pRunningData = (const char*)pRawData;
|
||||||
metadata.data.picture.type = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
const char* const pRunningDataEnd = (const char*)pRawData + blockSize;
|
||||||
metadata.data.picture.mimeLength = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
|
||||||
|
metadata.data.picture.type = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
metadata.data.picture.mimeLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
|
||||||
|
// Need space for the rest of the block
|
||||||
|
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
||||||
metadata.data.picture.descriptionLength = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
metadata.data.picture.descriptionLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
metadata.data.picture.description = pRunningData;
|
|
||||||
metadata.data.picture.width = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
// Need space for the rest of the block
|
||||||
metadata.data.picture.height = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
metadata.data.picture.colorDepth = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
DRFLAC_FREE(pRawData);
|
||||||
metadata.data.picture.indexColorCount = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
return DRFLAC_FALSE;
|
||||||
metadata.data.picture.pictureDataSize = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4;
|
}
|
||||||
|
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
|
||||||
|
metadata.data.picture.width = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
metadata.data.picture.height = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
metadata.data.picture.colorDepth = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
metadata.data.picture.indexColorCount = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
metadata.data.picture.pictureDataSize = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
||||||
|
|
||||||
|
// Need space for the picture after the block
|
||||||
|
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { // <-- Note the order of operations to avoid overflow to a valid value
|
||||||
|
DRFLAC_FREE(pRawData);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
onMeta(pUserDataMD, &metadata);
|
onMeta(pUserDataMD, &metadata);
|
||||||
|
|
||||||
DRFLAC_FREE(pRawData);
|
DRFLAC_FREE(pRawData);
|
||||||
@@ -4265,7 +4578,7 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||||||
{
|
{
|
||||||
drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
|
drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
|
||||||
drflac_assert(oggbs != NULL);
|
drflac_assert(oggbs != NULL);
|
||||||
drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start));
|
drflac_assert(offset >= 0); // <-- Never seek backwards.
|
||||||
|
|
||||||
// Seeking is always forward which makes things a lot simpler.
|
// Seeking is always forward which makes things a lot simpler.
|
||||||
if (origin == drflac_seek_origin_start) {
|
if (origin == drflac_seek_origin_start) {
|
||||||
@@ -4819,6 +5132,7 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p
|
|||||||
|
|
||||||
// We need to seek back to where we were. If this fails it's a critical error.
|
// We need to seek back to where we were. If this fails it's a critical error.
|
||||||
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFramePos, drflac_seek_origin_start)) {
|
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFramePos, drflac_seek_origin_start)) {
|
||||||
|
DRFLAC_FREE(pFlac);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -4861,9 +5175,6 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p
|
|||||||
|
|
||||||
|
|
||||||
#ifndef DR_FLAC_NO_STDIO
|
#ifndef DR_FLAC_NO_STDIO
|
||||||
typedef void* drflac_file;
|
|
||||||
|
|
||||||
#if defined(DR_FLAC_NO_WIN32_IO) || !defined(_WIN32)
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
|
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
|
||||||
@@ -4873,12 +5184,12 @@ static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t byt
|
|||||||
|
|
||||||
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
||||||
{
|
{
|
||||||
drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start));
|
drflac_assert(offset >= 0); // <-- Never seek backwards.
|
||||||
|
|
||||||
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static drflac_file drflac__open_file_handle(const char* filename)
|
static FILE* drflac__fopen(const char* filename)
|
||||||
{
|
{
|
||||||
FILE* pFile;
|
FILE* pFile;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -4892,65 +5203,20 @@ static drflac_file drflac__open_file_handle(const char* filename)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (drflac_file)pFile;
|
return pFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drflac__close_file_handle(drflac_file file)
|
|
||||||
{
|
|
||||||
fclose((FILE*)file);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
// This doesn't seem to be defined for VC6.
|
|
||||||
#ifndef INVALID_SET_FILE_POINTER
|
|
||||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
|
|
||||||
{
|
|
||||||
drflac_assert(bytesToRead < 0xFFFFFFFF); // dr_flac will never request huge amounts of data at a time. This is a safe assertion.
|
|
||||||
|
|
||||||
DWORD bytesRead;
|
|
||||||
ReadFile((HANDLE)pUserData, bufferOut, (DWORD)bytesToRead, &bytesRead, NULL);
|
|
||||||
|
|
||||||
return (size_t)bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
|
||||||
{
|
|
||||||
drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start));
|
|
||||||
|
|
||||||
return SetFilePointer((HANDLE)pUserData, offset, NULL, (origin == drflac_seek_origin_current) ? FILE_CURRENT : FILE_BEGIN) != INVALID_SET_FILE_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
static drflac_file drflac__open_file_handle(const char* filename)
|
|
||||||
{
|
|
||||||
HANDLE hFile = CreateFileA(filename, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (drflac_file)hFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drflac__close_file_handle(drflac_file file)
|
|
||||||
{
|
|
||||||
CloseHandle((HANDLE)file);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
drflac* drflac_open_file(const char* filename)
|
drflac* drflac_open_file(const char* filename)
|
||||||
{
|
{
|
||||||
drflac_file file = drflac__open_file_handle(filename);
|
FILE* file = drflac__fopen(filename);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drflac* pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)file);
|
drflac* pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)file);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
drflac__close_file_handle(file);
|
fclose(file);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4959,14 +5225,14 @@ drflac* drflac_open_file(const char* filename)
|
|||||||
|
|
||||||
drflac* drflac_open_file_with_metadata(const char* filename, drflac_meta_proc onMeta, void* pUserData)
|
drflac* drflac_open_file_with_metadata(const char* filename, drflac_meta_proc onMeta, void* pUserData)
|
||||||
{
|
{
|
||||||
drflac_file file = drflac__open_file_handle(filename);
|
FILE* file = drflac__fopen(filename);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drflac* pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)file, pUserData);
|
drflac* pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)file, pUserData);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
drflac__close_file_handle(file);
|
fclose(file);
|
||||||
return pFlac;
|
return pFlac;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4997,20 +5263,23 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_
|
|||||||
{
|
{
|
||||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||||
drflac_assert(memoryStream != NULL);
|
drflac_assert(memoryStream != NULL);
|
||||||
drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start));
|
drflac_assert(offset >= 0); // <-- Never seek backwards.
|
||||||
drflac_assert(offset <= (drflac_int64)memoryStream->dataSize);
|
|
||||||
|
if (offset > (drflac_int64)memoryStream->dataSize) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (origin == drflac_seek_origin_current) {
|
if (origin == drflac_seek_origin_current) {
|
||||||
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
|
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
|
||||||
memoryStream->currentReadPos += offset;
|
memoryStream->currentReadPos += offset;
|
||||||
} else {
|
} else {
|
||||||
memoryStream->currentReadPos = memoryStream->dataSize; // Trying to seek too far forward.
|
return DRFLAC_FALSE; // Trying to seek too far forward.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((drflac_uint32)offset <= memoryStream->dataSize) {
|
if ((drflac_uint32)offset <= memoryStream->dataSize) {
|
||||||
memoryStream->currentReadPos = offset;
|
memoryStream->currentReadPos = offset;
|
||||||
} else {
|
} else {
|
||||||
memoryStream->currentReadPos = memoryStream->dataSize; // Trying to seek too far forward.
|
return DRFLAC_FALSE; // Trying to seek too far forward.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5105,7 +5374,7 @@ void drflac_close(drflac* pFlac)
|
|||||||
// If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file()
|
// If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file()
|
||||||
// was used by looking at the callbacks.
|
// was used by looking at the callbacks.
|
||||||
if (pFlac->bs.onRead == drflac__on_read_stdio) {
|
if (pFlac->bs.onRead == drflac__on_read_stdio) {
|
||||||
drflac__close_file_handle((drflac_file)pFlac->bs.pUserData);
|
fclose((FILE*)pFlac->bs.pUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DR_FLAC_NO_OGG
|
#ifndef DR_FLAC_NO_OGG
|
||||||
@@ -5114,7 +5383,7 @@ void drflac_close(drflac* pFlac)
|
|||||||
drflac_assert(pFlac->bs.onRead == drflac__on_read_ogg);
|
drflac_assert(pFlac->bs.onRead == drflac__on_read_ogg);
|
||||||
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
|
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
|
||||||
if (oggbs->onRead == drflac__on_read_stdio) {
|
if (oggbs->onRead == drflac__on_read_stdio) {
|
||||||
drflac__close_file_handle((drflac_file)oggbs->pUserData);
|
fclose((FILE*)oggbs->pUserData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5718,14 +5987,14 @@ void drflac_free(void* pSampleDataReturnedByOpenAndDecode)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const char* pComments)
|
void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments)
|
||||||
{
|
{
|
||||||
if (pIter == NULL) {
|
if (pIter == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pIter->countRemaining = commentCount;
|
pIter->countRemaining = commentCount;
|
||||||
pIter->pRunningData = pComments;
|
pIter->pRunningData = (const char*)pComments;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut)
|
const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut)
|
||||||
@@ -5737,7 +6006,7 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drflac_uint32 length = drflac__le2host_32(*(drflac_uint32*)pIter->pRunningData);
|
drflac_uint32 length = drflac__le2host_32(*(const drflac_uint32*)pIter->pRunningData);
|
||||||
pIter->pRunningData += 4;
|
pIter->pRunningData += 4;
|
||||||
|
|
||||||
const char* pComment = pIter->pRunningData;
|
const char* pComment = pIter->pRunningData;
|
||||||
@@ -5747,11 +6016,62 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
|
|||||||
if (pCommentLengthOut) *pCommentLengthOut = length;
|
if (pCommentLengthOut) *pCommentLengthOut = length;
|
||||||
return pComment;
|
return pComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData)
|
||||||
|
{
|
||||||
|
if (pIter == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pIter->countRemaining = trackCount;
|
||||||
|
pIter->pRunningData = (const char*)pTrackData;
|
||||||
|
}
|
||||||
|
|
||||||
|
drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack)
|
||||||
|
{
|
||||||
|
if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
drflac_cuesheet_track cuesheetTrack;
|
||||||
|
|
||||||
|
const char* pRunningData = pIter->pRunningData;
|
||||||
|
|
||||||
|
drflac_uint64 offsetHi = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
drflac_uint64 offsetLo = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
|
||||||
|
cuesheetTrack.offset = offsetLo | (offsetHi << 32);
|
||||||
|
cuesheetTrack.trackNumber = pRunningData[0]; pRunningData += 1;
|
||||||
|
drflac_copy_memory(cuesheetTrack.ISRC, pRunningData, sizeof(cuesheetTrack.ISRC)); pRunningData += 12;
|
||||||
|
cuesheetTrack.isAudio = (pRunningData[0] & 0x80) != 0;
|
||||||
|
cuesheetTrack.preEmphasis = (pRunningData[0] & 0x40) != 0; pRunningData += 14;
|
||||||
|
cuesheetTrack.indexCount = pRunningData[0]; pRunningData += 1;
|
||||||
|
cuesheetTrack.pIndexPoints = (const drflac_cuesheet_track_index*)pRunningData; pRunningData += cuesheetTrack.indexCount * sizeof(drflac_cuesheet_track_index);
|
||||||
|
|
||||||
|
pIter->pRunningData = pRunningData;
|
||||||
|
pIter->countRemaining -= 1;
|
||||||
|
|
||||||
|
if (pCuesheetTrack) *pCuesheetTrack = cuesheetTrack;
|
||||||
|
return DRFLAC_TRUE;
|
||||||
|
}
|
||||||
#endif //DR_FLAC_IMPLEMENTATION
|
#endif //DR_FLAC_IMPLEMENTATION
|
||||||
|
|
||||||
|
|
||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
//
|
//
|
||||||
|
// v0.10.0 - 2018-09-11
|
||||||
|
// - Remove the DR_FLAC_NO_WIN32_IO option and the Win32 file IO functionality. If you need to use Win32 file IO you
|
||||||
|
// need to do it yourself via the callback API.
|
||||||
|
// - Fix the clang build.
|
||||||
|
// - Fix undefined behavior.
|
||||||
|
// - Fix errors with CUESHEET metdata blocks.
|
||||||
|
// - Add an API for iterating over each cuesheet track in the CUESHEET metadata block. This works the same way as the
|
||||||
|
// Vorbis comment API.
|
||||||
|
// - Other miscellaneous bug fixes, mostly relating to invalid FLAC streams.
|
||||||
|
// - Minor optimizations.
|
||||||
|
//
|
||||||
// v0.9.11 - 2018-08-29
|
// v0.9.11 - 2018-08-29
|
||||||
// - Fix a bug with sample reconstruction.
|
// - Fix a bug with sample reconstruction.
|
||||||
//
|
//
|
||||||
|
|||||||
+9
-1
@@ -1,5 +1,5 @@
|
|||||||
// MP3 audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
// MP3 audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// dr_mp3 - v0.3.1 - 2018-08-25
|
// dr_mp3 - v0.3.2 - 2018-09-11
|
||||||
//
|
//
|
||||||
// David Reid - mackron@gmail.com
|
// David Reid - mackron@gmail.com
|
||||||
//
|
//
|
||||||
@@ -315,7 +315,9 @@ void drmp3_free(void* p);
|
|||||||
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
||||||
|
|
||||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||||
|
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
||||||
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||||
|
|
||||||
@@ -2583,11 +2585,13 @@ drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek
|
|||||||
srcConfig.channels = pMP3->channels;
|
srcConfig.channels = pMP3->channels;
|
||||||
srcConfig.algorithm = drmp3_src_algorithm_linear;
|
srcConfig.algorithm = drmp3_src_algorithm_linear;
|
||||||
if (!drmp3_src_init(&srcConfig, drmp3_read_src, pMP3, &pMP3->src)) {
|
if (!drmp3_src_init(&srcConfig, drmp3_read_src, pMP3, &pMP3->src)) {
|
||||||
|
drmp3_uninit(pMP3);
|
||||||
return DRMP3_FALSE;
|
return DRMP3_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the first frame to confirm that it is indeed a valid MP3 stream.
|
// Decode the first frame to confirm that it is indeed a valid MP3 stream.
|
||||||
if (!drmp3_decode_next_frame(pMP3)) {
|
if (!drmp3_decode_next_frame(pMP3)) {
|
||||||
|
drmp3_uninit(pMP3);
|
||||||
return DRMP3_FALSE; // Not a valid MP3 stream.
|
return DRMP3_FALSE; // Not a valid MP3 stream.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2888,6 +2892,10 @@ void drmp3_free(void* p)
|
|||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
// ===============
|
// ===============
|
||||||
//
|
//
|
||||||
|
// v0.3.2 - 2018-09-11
|
||||||
|
// - Fix a couple of memory leaks.
|
||||||
|
// - Bring up to date with minimp3.
|
||||||
|
//
|
||||||
// v0.3.1 - 2018-08-25
|
// v0.3.1 - 2018-08-25
|
||||||
// - Fix C++ build.
|
// - Fix C++ build.
|
||||||
//
|
//
|
||||||
|
|||||||
+22
-15
@@ -1,5 +1,5 @@
|
|||||||
// WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file.
|
// WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// dr_wav - v0.8.4 - 2018-08-07
|
// dr_wav - v0.8.5 - 2018-09-11
|
||||||
//
|
//
|
||||||
// David Reid - mackron@gmail.com
|
// David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@@ -909,13 +909,16 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
|||||||
|
|
||||||
|
|
||||||
// Skip non-fmt chunks.
|
// Skip non-fmt chunks.
|
||||||
if ((container == drwav_container_riff && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
while ((container == drwav_container_riff && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||||
if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
|
if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
*pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
|
*pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
|
||||||
|
|
||||||
return drwav__read_fmt(onRead, onSeek, pUserData, container, pRunningBytesReadOut, fmtOut);
|
// Try the next header.
|
||||||
|
if (!drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header)) {
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1140,11 +1143,11 @@ static drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_see
|
|||||||
if (origin == drwav_seek_origin_current) {
|
if (origin == drwav_seek_origin_current) {
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
if (memory->currentReadPos + offset > memory->dataSize) {
|
if (memory->currentReadPos + offset > memory->dataSize) {
|
||||||
offset = (int)(memory->dataSize - memory->currentReadPos); // Trying to seek too far forward.
|
return DRWAV_FALSE; // Trying to seek too far forward.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (memory->currentReadPos < (size_t)-offset) {
|
if (memory->currentReadPos < (size_t)-offset) {
|
||||||
offset = -(int)memory->currentReadPos; // Trying to seek too far backwards.
|
return DRWAV_FALSE; // Trying to seek too far backwards.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,7 +1157,7 @@ static drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_see
|
|||||||
if ((drwav_uint32)offset <= memory->dataSize) {
|
if ((drwav_uint32)offset <= memory->dataSize) {
|
||||||
memory->currentReadPos = offset;
|
memory->currentReadPos = offset;
|
||||||
} else {
|
} else {
|
||||||
memory->currentReadPos = memory->dataSize; // Trying to seek too far forward.
|
return DRWAV_FALSE; // Trying to seek too far forward.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2424,7 +2427,7 @@ static void drwav__pcm_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_
|
|||||||
// Slightly more optimal implementation for common formats.
|
// Slightly more optimal implementation for common formats.
|
||||||
if (bytesPerSample == 2) {
|
if (bytesPerSample == 2) {
|
||||||
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
||||||
*pOut++ = ((drwav_int16*)pIn)[i];
|
*pOut++ = ((const drwav_int16*)pIn)[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2464,10 +2467,10 @@ static void drwav__pcm_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_
|
|||||||
static void drwav__ieee_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
static void drwav__ieee_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
||||||
{
|
{
|
||||||
if (bytesPerSample == 4) {
|
if (bytesPerSample == 4) {
|
||||||
drwav_f32_to_s16(pOut, (float*)pIn, totalSampleCount);
|
drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
} else if (bytesPerSample == 8) {
|
} else if (bytesPerSample == 8) {
|
||||||
drwav_f64_to_s16(pOut, (double*)pIn, totalSampleCount);
|
drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
@@ -2614,7 +2617,7 @@ void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCo
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
for (size_t i = 0; i < sampleCount; ++i) {
|
for (size_t i = 0; i < sampleCount; ++i) {
|
||||||
int x = ((int)(((unsigned int)(((unsigned char*)pIn)[i*3+0]) << 8) | ((unsigned int)(((unsigned char*)pIn)[i*3+1]) << 16) | ((unsigned int)(((unsigned char*)pIn)[i*3+2])) << 24)) >> 8;
|
int x = ((int)(((unsigned int)(((const unsigned char*)pIn)[i*3+0]) << 8) | ((unsigned int)(((const unsigned char*)pIn)[i*3+1]) << 16) | ((unsigned int)(((const unsigned char*)pIn)[i*3+2])) << 24)) >> 8;
|
||||||
r = x >> 8;
|
r = x >> 8;
|
||||||
pOut[i] = (short)r;
|
pOut[i] = (short)r;
|
||||||
}
|
}
|
||||||
@@ -2724,11 +2727,11 @@ static void drwav__ieee_to_f32(float* pOut, const unsigned char* pIn, size_t sam
|
|||||||
{
|
{
|
||||||
if (bytesPerSample == 4) {
|
if (bytesPerSample == 4) {
|
||||||
for (unsigned int i = 0; i < sampleCount; ++i) {
|
for (unsigned int i = 0; i < sampleCount; ++i) {
|
||||||
*pOut++ = ((float*)pIn)[i];
|
*pOut++ = ((const float*)pIn)[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (bytesPerSample == 8) {
|
} else if (bytesPerSample == 8) {
|
||||||
drwav_f64_to_f32(pOut, (double*)pIn, sampleCount);
|
drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
@@ -3034,7 +3037,7 @@ static void drwav__pcm_to_s32(drwav_int32* pOut, const unsigned char* pIn, size_
|
|||||||
}
|
}
|
||||||
if (bytesPerSample == 4) {
|
if (bytesPerSample == 4) {
|
||||||
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
||||||
*pOut++ = ((drwav_int32*)pIn)[i];
|
*pOut++ = ((const drwav_int32*)pIn)[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3066,10 +3069,10 @@ static void drwav__pcm_to_s32(drwav_int32* pOut, const unsigned char* pIn, size_
|
|||||||
static void drwav__ieee_to_s32(drwav_int32* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
static void drwav__ieee_to_s32(drwav_int32* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
||||||
{
|
{
|
||||||
if (bytesPerSample == 4) {
|
if (bytesPerSample == 4) {
|
||||||
drwav_f32_to_s32(pOut, (float*)pIn, totalSampleCount);
|
drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
} else if (bytesPerSample == 8) {
|
} else if (bytesPerSample == 8) {
|
||||||
drwav_f64_to_s32(pOut, (double*)pIn, totalSampleCount);
|
drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
@@ -3581,6 +3584,10 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
|
|||||||
|
|
||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
//
|
//
|
||||||
|
// v0.8.5 - 2018-09-11
|
||||||
|
// - Const correctness.
|
||||||
|
// - Fix a potential stack overflow.
|
||||||
|
//
|
||||||
// v0.8.4 - 2018-08-07
|
// v0.8.4 - 2018-08-07
|
||||||
// - Improve 64-bit detection.
|
// - Improve 64-bit detection.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user