Commit 911bc61d authored by David Reid's avatar David Reid

Update external decoders.

parent c78a11be
/* /*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.12.2 - 2019-10-07 dr_flac - v0.12.3 - 2019-12-02
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
*/ */
...@@ -555,11 +555,14 @@ typedef struct ...@@ -555,11 +555,14 @@ typedef struct
{ {
/* /*
If the stream uses variable block sizes, this will be set to the index of the first PCM frame. If fixed block sizes are used, this will If the stream uses variable block sizes, this will be set to the index of the first PCM frame. If fixed block sizes are used, this will
always be set to 0. always be set to 0. This is 64-bit because the decoded PCM frame number will be 36 bits.
*/ */
drflac_uint64 pcmFrameNumber; drflac_uint64 pcmFrameNumber;
/* If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. */ /*
If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. This
is 32-bit because in fixed block sizes, the maximum frame number will be 31 bits.
*/
drflac_uint32 flacFrameNumber; drflac_uint32 flacFrameNumber;
/* The sample rate of this frame. */ /* The sample rate of this frame. */
...@@ -3141,14 +3144,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar_zeroorde ...@@ -3141,14 +3144,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar_zeroorde
static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar(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__scalar(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)
{ {
drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF}; drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
drflac_uint32 zeroCountPart0; drflac_uint32 zeroCountPart0 = 0;
drflac_uint32 zeroCountPart1; drflac_uint32 zeroCountPart1 = 0;
drflac_uint32 zeroCountPart2; drflac_uint32 zeroCountPart2 = 0;
drflac_uint32 zeroCountPart3; drflac_uint32 zeroCountPart3 = 0;
drflac_uint32 riceParamPart0; drflac_uint32 riceParamPart0 = 0;
drflac_uint32 riceParamPart1; drflac_uint32 riceParamPart1 = 0;
drflac_uint32 riceParamPart2; drflac_uint32 riceParamPart2 = 0;
drflac_uint32 riceParamPart3; drflac_uint32 riceParamPart3 = 0;
drflac_uint32 riceParamMask; drflac_uint32 riceParamMask;
const drflac_int32* pSamplesOutEnd; const drflac_int32* pSamplesOutEnd;
drflac_uint32 i; drflac_uint32 i;
...@@ -3316,14 +3319,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_32(drflac ...@@ -3316,14 +3319,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_32(drflac
drflac_uint32 riceParamMask; drflac_uint32 riceParamMask;
drflac_int32* pDecodedSamples = pSamplesOut; drflac_int32* pDecodedSamples = pSamplesOut;
drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3); drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
drflac_uint32 zeroCountParts0; drflac_uint32 zeroCountParts0 = 0;
drflac_uint32 zeroCountParts1; drflac_uint32 zeroCountParts1 = 0;
drflac_uint32 zeroCountParts2; drflac_uint32 zeroCountParts2 = 0;
drflac_uint32 zeroCountParts3; drflac_uint32 zeroCountParts3 = 0;
drflac_uint32 riceParamParts0; drflac_uint32 riceParamParts0 = 0;
drflac_uint32 riceParamParts1; drflac_uint32 riceParamParts1 = 0;
drflac_uint32 riceParamParts2; drflac_uint32 riceParamParts2 = 0;
drflac_uint32 riceParamParts3; drflac_uint32 riceParamParts3 = 0;
__m128i coefficients128_0; __m128i coefficients128_0;
__m128i coefficients128_4; __m128i coefficients128_4;
__m128i coefficients128_8; __m128i coefficients128_8;
...@@ -3521,14 +3524,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_64(drflac ...@@ -3521,14 +3524,14 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_64(drflac
drflac_uint32 riceParamMask; drflac_uint32 riceParamMask;
drflac_int32* pDecodedSamples = pSamplesOut; drflac_int32* pDecodedSamples = pSamplesOut;
drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3); drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
drflac_uint32 zeroCountParts0; drflac_uint32 zeroCountParts0 = 0;
drflac_uint32 zeroCountParts1; drflac_uint32 zeroCountParts1 = 0;
drflac_uint32 zeroCountParts2; drflac_uint32 zeroCountParts2 = 0;
drflac_uint32 zeroCountParts3; drflac_uint32 zeroCountParts3 = 0;
drflac_uint32 riceParamParts0; drflac_uint32 riceParamParts0 = 0;
drflac_uint32 riceParamParts1; drflac_uint32 riceParamParts1 = 0;
drflac_uint32 riceParamParts2; drflac_uint32 riceParamParts2 = 0;
drflac_uint32 riceParamParts3; drflac_uint32 riceParamParts3 = 0;
__m128i coefficients128_0; __m128i coefficients128_0;
__m128i coefficients128_4; __m128i coefficients128_4;
__m128i coefficients128_8; __m128i coefficients128_8;
...@@ -5078,10 +5081,10 @@ static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac* pFlac, drf ...@@ -5078,10 +5081,10 @@ static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac* pFlac, drf
firstPCMFrame = pFlac->currentFLACFrame.header.pcmFrameNumber; firstPCMFrame = pFlac->currentFLACFrame.header.pcmFrameNumber;
if (firstPCMFrame == 0) { if (firstPCMFrame == 0) {
firstPCMFrame = pFlac->currentFLACFrame.header.flacFrameNumber * pFlac->maxBlockSizeInPCMFrames; firstPCMFrame = ((drflac_uint64)pFlac->currentFLACFrame.header.flacFrameNumber) * pFlac->maxBlockSizeInPCMFrames;
} }
lastPCMFrame = firstPCMFrame + (pFlac->currentFLACFrame.header.blockSizeInPCMFrames); lastPCMFrame = firstPCMFrame + pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
if (lastPCMFrame > 0) { if (lastPCMFrame > 0) {
lastPCMFrame -= 1; /* Needs to be zero based. */ lastPCMFrame -= 1; /* Needs to be zero based. */
} }
...@@ -5349,7 +5352,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p ...@@ -5349,7 +5352,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
drflac_uint64 closestSeekOffsetBeforeTargetPCMFrame = byteRangeLo; drflac_uint64 closestSeekOffsetBeforeTargetPCMFrame = byteRangeLo;
drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096; drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
targetByte = byteRangeLo + (drflac_uint64)((pcmFrameIndex - pFlac->currentPCMFrame) * pFlac->channels * pFlac->bitsPerSample/8 * DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO); targetByte = byteRangeLo + (drflac_uint64)(((pcmFrameIndex - pFlac->currentPCMFrame) * pFlac->channels * pFlac->bitsPerSample/8.0f) * DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO);
if (targetByte > byteRangeHi) { if (targetByte > byteRangeHi) {
targetByte = byteRangeHi; targetByte = byteRangeHi;
} }
...@@ -5394,7 +5397,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p ...@@ -5394,7 +5397,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
byteRangeLo = byteRangeHi; byteRangeLo = byteRangeHi;
} }
/*targetByte = lastSuccessfulSeekOffset - (drflac_uint64)((pcmRangeLo-pcmFrameIndex) * pFlac->channels * pFlac->bitsPerSample/8 * approxCompressionRatio);*/
targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2); targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2);
if (targetByte < byteRangeLo) { if (targetByte < byteRangeLo) {
targetByte = byteRangeLo; targetByte = byteRangeLo;
...@@ -5415,10 +5417,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p ...@@ -5415,10 +5417,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
byteRangeHi = byteRangeLo; byteRangeHi = byteRangeLo;
} }
/*targetByte = byteRangeLo + (drflac_uint64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample/8 * approxCompressionRatio);*/ targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample/8.0f) * approxCompressionRatio);
targetByte = lastSuccessfulSeekOffset + (drflac_uint64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample/8 * approxCompressionRatio);
/*targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2);*/
if (targetByte > byteRangeHi) { if (targetByte > byteRangeHi) {
targetByte = byteRangeHi; targetByte = byteRangeHi;
} }
...@@ -5460,7 +5459,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search(drflac* pFlac, drf ...@@ -5460,7 +5459,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search(drflac* pFlac, drf
the entire file is included, even though most of the time it'll exceed the end of the actual stream. This is OK as the frame searching logic will handle it. the entire file is included, even though most of the time it'll exceed the end of the actual stream. This is OK as the frame searching logic will handle it.
*/ */
byteRangeLo = pFlac->firstFLACFramePosInBytes; byteRangeLo = pFlac->firstFLACFramePosInBytes;
byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample/8); byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample/8.0f);
return drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi); return drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi);
} }
...@@ -5494,7 +5493,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__seek_table(drflac* pFlac, drflac ...@@ -5494,7 +5493,7 @@ static drflac_bool32 drflac__seek_to_pcm_frame__seek_table(drflac* pFlac, drflac
drflac_uint64 byteRangeLo; drflac_uint64 byteRangeLo;
drflac_uint64 byteRangeHi; drflac_uint64 byteRangeHi;
byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample/8); byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample/8.0f);
byteRangeLo = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset; byteRangeLo = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset;
if (iClosestSeekpoint < pFlac->seekpointCount-1) { if (iClosestSeekpoint < pFlac->seekpointCount-1) {
...@@ -5671,6 +5670,8 @@ static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, ...@@ -5671,6 +5670,8 @@ static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader,
static DRFLAC_INLINE drflac_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize) static DRFLAC_INLINE drflac_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize)
{ {
drflac_uint32 blockHeader; drflac_uint32 blockHeader;
*blockSize = 0;
if (onRead(pUserData, &blockHeader, 4) != 4) { if (onRead(pUserData, &blockHeader, 4) != 4) {
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
...@@ -5780,8 +5781,10 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, ...@@ -5780,8 +5781,10 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
return NULL; return NULL;
} }
DRFLAC_COPY_MEMORY(p2, p, szOld); if (p != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); DRFLAC_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2; return p2;
} }
...@@ -5816,7 +5819,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s ...@@ -5816,7 +5819,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
drflac_uint8 isLastBlock = 0; drflac_uint8 isLastBlock = 0;
drflac_uint8 blockType; drflac_uint8 blockType;
drflac_uint32 blockSize; drflac_uint32 blockSize;
if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) { if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
runningFilePos += 4; runningFilePos += 4;
...@@ -6384,6 +6387,16 @@ drflac_result drflac_ogg__read_page_header_after_capture_pattern(drflac_read_pro ...@@ -6384,6 +6387,16 @@ drflac_result drflac_ogg__read_page_header_after_capture_pattern(drflac_read_pro
} }
*pBytesRead += 23; *pBytesRead += 23;
/*
It's not actually used, but set the capture pattern to 'OggS' for completeness. Not doing this will cause static analysers to complain about
us trying to access uninitialized data. We could alternatively just comment out this member of the drflac_ogg_page_header structure, but I
like to have it map to the structure of the underlying data.
*/
pHeader->capturePattern[0] = 'O';
pHeader->capturePattern[1] = 'g';
pHeader->capturePattern[2] = 'g';
pHeader->capturePattern[3] = 'S';
pHeader->structureVersion = data[0]; pHeader->structureVersion = data[0];
pHeader->headerType = data[1]; pHeader->headerType = data[1];
DRFLAC_COPY_MEMORY(&pHeader->granulePosition, &data[ 2], 8); DRFLAC_COPY_MEMORY(&pHeader->granulePosition, &data[ 2], 8);
...@@ -7152,7 +7165,7 @@ drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onR ...@@ -7152,7 +7165,7 @@ drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onR
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
void drflac__init_from_info(drflac* pFlac, drflac_init_info* pInit) void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
{ {
DRFLAC_ASSERT(pFlac != NULL); DRFLAC_ASSERT(pFlac != NULL);
DRFLAC_ASSERT(pInit != NULL); DRFLAC_ASSERT(pInit != NULL);
...@@ -7280,6 +7293,10 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p ...@@ -7280,6 +7293,10 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks); pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
drflac__init_from_info(pFlac, &init); drflac__init_from_info(pFlac, &init);
pFlac->allocationCallbacks = allocationCallbacks; pFlac->allocationCallbacks = allocationCallbacks;
pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE); pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE);
...@@ -7314,6 +7331,9 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p ...@@ -7314,6 +7331,9 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p
pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints); pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize); pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
/* Seek to the seektable, then just read directly into our seektable buffer. */ /* Seek to the seektable, then just read directly into our seektable buffer. */
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) { if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) { if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
...@@ -10717,6 +10737,14 @@ drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, ...@@ -10717,6 +10737,14 @@ drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter,
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.12.3 - 2019-12-02
- Fix some warnings when compiling with GCC and the -Og flag.
- Fix a crash in out-of-memory situations.
- Fix potential integer overflow bug.
- Fix some static analysis warnings.
- Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
- Fix a bug with binary search seeking where the bits per sample is not a multiple of 8.
v0.12.2 - 2019-10-07 v0.12.2 - 2019-10-07
- Internal code clean up. - Internal code clean up.
......
/* /*
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_mp3 - v0.5.1 - 2019-10-08 dr_mp3 - v0.5.4 - 2019-12-02
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
...@@ -41,11 +41,11 @@ To use the new system, you pass in a pointer to a drmp3_allocation_callbacks obj ...@@ -41,11 +41,11 @@ To use the new system, you pass in a pointer to a drmp3_allocation_callbacks obj
allocationCallbacks.onMalloc = my_malloc; allocationCallbacks.onMalloc = my_malloc;
allocationCallbacks.onRealloc = my_realloc; allocationCallbacks.onRealloc = my_realloc;
allocationCallbacks.onFree = my_free; allocationCallbacks.onFree = my_free;
drmp3_init_file(&mp3, "my_file.wav", NULL, &allocationCallbacks); drmp3_init_file(&mp3, "my_file.mp3", NULL, &allocationCallbacks);
The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines. The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
Passing in null for the allocation callbacks object will cause dr_wav to use defaults which is the same as DRMP3_MALLOC, Passing in null for the allocation callbacks object will cause dr_mp3 to use defaults which is the same as DRMP3_MALLOC,
DRMP3_REALLOC and DRMP3_FREE and the equivalent of how it worked in previous versions. DRMP3_REALLOC and DRMP3_FREE and the equivalent of how it worked in previous versions.
Every API that opens a drmp3 object now takes this extra parameter. These include the following: Every API that opens a drmp3 object now takes this extra parameter. These include the following:
...@@ -619,6 +619,7 @@ end: ...@@ -619,6 +619,7 @@ end:
} }
#elif defined(__ARM_NEON) || defined(__aarch64__) #elif defined(__ARM_NEON) || defined(__aarch64__)
#include <arm_neon.h> #include <arm_neon.h>
#define DRMP3_HAVE_SSE 0
#define DRMP3_HAVE_SIMD 1 #define DRMP3_HAVE_SIMD 1
#define DRMP3_VSTORE vst1q_f32 #define DRMP3_VSTORE vst1q_f32
#define DRMP3_VLD vld1q_f32 #define DRMP3_VLD vld1q_f32
...@@ -636,6 +637,7 @@ static int drmp3_have_simd() ...@@ -636,6 +637,7 @@ static int drmp3_have_simd()
return 1; return 1;
} }
#else #else
#define DRMP3_HAVE_SSE 0
#define DRMP3_HAVE_SIMD 0 #define DRMP3_HAVE_SIMD 0
#ifdef DR_MP3_ONLY_SIMD #ifdef DR_MP3_ONLY_SIMD
#error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled #error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled
...@@ -2421,8 +2423,10 @@ static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, ...@@ -2421,8 +2423,10 @@ static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
return NULL; return NULL;
} }
DRMP3_COPY_MEMORY(p2, p, szOld); if (p != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); DRMP3_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2; return p2;
} }
...@@ -4005,6 +4009,15 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3 ...@@ -4005,6 +4009,15 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.5.4 - 2019-12-02
- Fix a possible null pointer dereference when using custom memory allocators for realloc().
v0.5.3 - 2019-11-14
- Fix typos in documentation.
v0.5.2 - 2019-11-02
- Bring up to date with minimp3.
v0.5.1 - 2019-10-08 v0.5.1 - 2019-10-08
- Fix a warning with GCC. - Fix a warning with GCC.
......
/* /*
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_wav - v0.11.1 - 2019-10-07 dr_wav - v0.11.2 - 2019-12-02
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
*/ */
...@@ -1076,6 +1076,20 @@ void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks) ...@@ -1076,6 +1076,20 @@ void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
#endif #endif
#endif #endif
/*
These limits are used for basic validation when initializing the decoder. If you exceed these limits, first of all: what on Earth are
you doing?! (Let me know, I'd be curious!) Second, you can adjust these by #define-ing them before the dr_wav implementation.
*/
#ifndef DRWAV_MAX_SAMPLE_RATE
#define DRWAV_MAX_SAMPLE_RATE 384000
#endif
#ifndef DRWAV_MAX_CHANNELS
#define DRWAV_MAX_CHANNELS 256
#endif
#ifndef DRWAV_MAX_BITS_PER_SAMPLE
#define DRWAV_MAX_BITS_PER_SAMPLE 64
#endif
static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00}; /* 66666972-912E-11CF-A5D6-28DB04C10000 */ static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00}; /* 66666972-912E-11CF-A5D6-28DB04C10000 */
static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */ static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
static const drwav_uint8 drwavGUID_W64_JUNK[16] = {0x6A,0x75,0x6E,0x6B, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 6B6E756A-ACF3-11D3-8CD1-00C04F8EDB8A */ static const drwav_uint8 drwavGUID_W64_JUNK[16] = {0x6A,0x75,0x6E,0x6B, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 6B6E756A-ACF3-11D3-8CD1-00C04F8EDB8A */
...@@ -1446,8 +1460,10 @@ static void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, ...@@ -1446,8 +1460,10 @@ static void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
return NULL; return NULL;
} }
DRWAV_COPY_MEMORY(p2, p, szOld); if (p != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); DRWAV_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2; return p2;
} }
...@@ -1862,8 +1878,11 @@ drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* p ...@@ -1862,8 +1878,11 @@ drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* p
} }
/* Basic validation. */ /* Basic validation. */
if (fmt.sampleRate == 0 || fmt.channels == 0 || fmt.bitsPerSample == 0 || fmt.blockAlign == 0) { if ((fmt.sampleRate == 0 || fmt.sampleRate > DRWAV_MAX_SAMPLE_RATE) ||
return DRWAV_FALSE; /* Invalid channel count. Probably an invalid WAV file. */ (fmt.channels == 0 || fmt.channels > DRWAV_MAX_CHANNELS) ||
(fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
fmt.blockAlign == 0) {
return DRWAV_FALSE; /* Probably an invalid WAV file. */
} }
...@@ -2926,11 +2945,12 @@ drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex) ...@@ -2926,11 +2945,12 @@ drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex)
{ {
/* Seeking should be compatible with wave files > 2GB. */ /* Seeking should be compatible with wave files > 2GB. */
if (pWav->onWrite != NULL) { if (pWav == NULL || pWav->onSeek == NULL) {
return DRWAV_FALSE; /* No seeking in write mode. */ return DRWAV_FALSE;
} }
if (pWav == NULL || pWav->onSeek == NULL) { /* No seeking in write mode. */
if (pWav->onWrite != NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
...@@ -3060,10 +3080,10 @@ drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, ...@@ -3060,10 +3080,10 @@ drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite,
while (bytesToWrite > 0) { while (bytesToWrite > 0) {
size_t bytesJustWritten; size_t bytesJustWritten;
drwav_uint64 bytesToWriteThisIteration = bytesToWrite; drwav_uint64 bytesToWriteThisIteration;
if (bytesToWriteThisIteration > DRWAV_SIZE_MAX) {
bytesToWriteThisIteration = DRWAV_SIZE_MAX; bytesToWriteThisIteration = bytesToWrite;
} DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX); /* <-- This is checked above. */
bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData); bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
if (bytesJustWritten == 0) { if (bytesJustWritten == 0) {
...@@ -3106,9 +3126,7 @@ drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, ...@@ -3106,9 +3126,7 @@ drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite,
drwav_uint64 bytesToWriteThisIteration; drwav_uint64 bytesToWriteThisIteration;
bytesToWriteThisIteration = bytesToWrite; bytesToWriteThisIteration = bytesToWrite;
if (bytesToWriteThisIteration > DRWAV_SIZE_MAX) { DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX); /* <-- This is checked above. */
bytesToWriteThisIteration = DRWAV_SIZE_MAX;
}
/* /*
WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need
...@@ -3116,8 +3134,8 @@ drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, ...@@ -3116,8 +3134,8 @@ drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite,
*/ */
sampleCount = sizeof(temp)/bytesPerSample; sampleCount = sizeof(temp)/bytesPerSample;
if (bytesToWriteThisIteration > sampleCount*bytesPerSample) { if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
bytesToWriteThisIteration = sampleCount*bytesPerSample; bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
} }
DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration); DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
...@@ -5033,6 +5051,12 @@ void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks) ...@@ -5033,6 +5051,12 @@ void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.11.2 - 2019-12-02
- Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
- Fix an integer overflow bug.
- Fix a null pointer dereference bug.
- Add limits to sample rate, channels and bits per sample to tighten up some validation.
v0.11.1 - 2019-10-07 v0.11.1 - 2019-10-07
- Internal code clean up. - Internal code clean up.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment