Commit 90ae3091 authored by David Reid's avatar David Reid

Update dr_mp3.

parent e438ab0c
/*
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_mp3 - v0.6.4 - 2020-04-19
dr_mp3 - v0.6.8 - 2020-04-26
David Reid - mackron@gmail.com
......@@ -352,6 +352,7 @@ typedef struct
drmp3_uint32 seekPointCount; /* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
size_t dataSize;
size_t dataCapacity;
size_t dataConsumed;
drmp3_uint8* pData;
drmp3_bool32 atEnd : 1;
struct
......@@ -671,7 +672,7 @@ static int drmp3_have_simd(void)
#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__)
#define DRMP3_HAVE_ARMV6 1
static __inline__ __attribute__((always_inline)) drmp32_int32 drmp3_clip_int16_arm(int32_t a)
static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_arm(int32_t a)
{
drmp3_int32 x = 0;
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
......@@ -2356,6 +2357,13 @@ DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num
#define DRMP3_SEEK_LEADING_MP3_FRAMES 2
#endif
#define DRMP3_MIN_DATA_CHUNK_SIZE 16384
/* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends at least 16K, but in an attempt to reduce data movement I'm making this slightly larger. */
#ifndef DRMP3_DATA_CHUNK_SIZE
#define DRMP3_DATA_CHUNK_SIZE DRMP3_MIN_DATA_CHUNK_SIZE*4
#endif
/* Standard library stuff. */
#ifndef DRMP3_ASSERT
......@@ -2382,8 +2390,6 @@ DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num
#define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
#define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
#define DRMP3_DATA_CHUNK_SIZE 16384 /* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends 16K. */
#ifndef DRMP3_PI_D
#define DRMP3_PI_D 3.14159265358979323846264
#endif
......@@ -2459,8 +2465,6 @@ static void drmp3__free_default(void* p, void* pUserData)
}
/* Only used without DR_MP3_NO_STDIO. */
#ifndef DR_MP3_NO_STDIO
static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
......@@ -2478,7 +2482,6 @@ static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_call
return NULL;
}
#endif
static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
......@@ -2595,7 +2598,7 @@ static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_se
}
static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames, drmp3_bool32 discard)
static drmp3_uint32 drmp3_decode_next_frame_ex__callbacks(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
drmp3_uint32 pcmFramesRead = 0;
......@@ -2608,12 +2611,15 @@ static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPC
for (;;) {
drmp3dec_frame_info info;
size_t leftoverDataSize;
/* minimp3 recommends doing data submission in 16K chunks. If we don't have at least 16K bytes available, get more. */
if (pMP3->dataSize < DRMP3_DATA_CHUNK_SIZE) {
/* minimp3 recommends doing data submission in chunks of at least 16K. If we don't have at least 16K bytes available, get more. */
if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
size_t bytesRead;
/* First we need to move the data down. */
memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
pMP3->dataConsumed = 0;
if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
drmp3_uint8* pNewData;
size_t newDataCap;
......@@ -2645,20 +2651,16 @@ static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPC
return 0; /* File too big. */
}
pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData, (int)pMP3->dataSize, pPCMFrames, &info); /* <-- Safe size_t -> int conversion thanks to the check above. */
pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info); /* <-- Safe size_t -> int conversion thanks to the check above. */
/* Consume the data. */
leftoverDataSize = (pMP3->dataSize - (size_t)info.frame_bytes);
if (info.frame_bytes > 0) {
memmove(pMP3->pData, pMP3->pData + info.frame_bytes, leftoverDataSize);
pMP3->dataSize = leftoverDataSize;
pMP3->dataConsumed += (size_t)info.frame_bytes;
pMP3->dataSize -= (size_t)info.frame_bytes;
}
/*
pcmFramesRead will be equal to 0 if decoding failed. If it is zero and info.frame_bytes > 0 then we have successfully
decoded the frame. A special case is if we are wanting to discard the frame, in which case we return successfully.
*/
if (pcmFramesRead > 0 || (info.frame_bytes > 0 && discard)) {
/* pcmFramesRead will be equal to 0 if decoding failed. If it is zero and info.frame_bytes > 0 then we have successfully decoded the frame. */
if (pcmFramesRead > 0) {
pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
......@@ -2666,9 +2668,13 @@ static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPC
pMP3->mp3FrameSampleRate = info.hz;
break;
} else if (info.frame_bytes == 0) {
/* Need more data. minimp3 recommends doing data submission in 16K chunks. */
size_t bytesRead;
/* Need more data. minimp3 recommends doing data submission in 16K chunks. */
/* First we need to move the data down. */
memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
pMP3->dataConsumed = 0;
if (pMP3->dataCapacity == pMP3->dataSize) {
/* No room. Expand. */
drmp3_uint8* pNewData;
......@@ -2699,10 +2705,44 @@ static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPC
return pcmFramesRead;
}
static drmp3_uint32 drmp3_decode_next_frame_ex__memory(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
drmp3_uint32 pcmFramesRead = 0;
drmp3dec_frame_info info;
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(pMP3->memory.pData != NULL);
if (pMP3->atEnd) {
return 0;
}
pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
pMP3->mp3FrameChannels = info.channels;
pMP3->mp3FrameSampleRate = info.hz;
/* Consume the data. */
pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
return pcmFramesRead;
}
static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
} else {
return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
}
}
static drmp3_uint32 drmp3_decode_next_frame(drmp3* pMP3)
{
DRMP3_ASSERT(pMP3 != NULL);
return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames, DRMP3_FALSE);
return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames);
}
#if 0
......@@ -3515,6 +3555,7 @@ static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesTo
#endif
}
pMP3->currentPCMFrame += framesToConsume;
pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
pMP3->pcmFramesRemainingInMP3Frame -= framesToConsume;
totalFramesRead += framesToConsume;
......@@ -3749,8 +3790,8 @@ static drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3* pMP3, drmp3_uint6
pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames;
}
/* We first need to decode the next frame, and then we need to flush the resampler. */
pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames, DRMP3_TRUE);
/* We first need to decode the next frame. */
pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames);
if (pcmFramesRead == 0) {
return DRMP3_FALSE;
}
......@@ -3790,7 +3831,6 @@ DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint
drmp3_uint64 currentPCMFrame;
drmp3_uint64 totalPCMFrameCount;
drmp3_uint64 totalMP3FrameCount;
float totalPCMFrameCountFractionalPart;
if (pMP3 == NULL) {
return DRMP3_FALSE;
......@@ -3816,25 +3856,15 @@ DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint
totalPCMFrameCount = 0;
totalMP3FrameCount = 0;
totalPCMFrameCountFractionalPart = 0; /* <-- With resampling there will be a fractional part to each MP3 frame that we need to accumulate. */
for (;;) {
drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
float srcRatio;
float pcmFramesInCurrentMP3FrameOutF;
drmp3_uint32 pcmFramesInCurrentMP3FrameOut;
drmp3_uint32 pcmFramesInCurrentMP3Frame;
pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_FALSE);
if (pcmFramesInCurrentMP3FrameIn == 0) {
pcmFramesInCurrentMP3Frame = drmp3_decode_next_frame_ex(pMP3, NULL);
if (pcmFramesInCurrentMP3Frame == 0) {
break;
}
srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate;
DRMP3_ASSERT(srcRatio > 0);
pcmFramesInCurrentMP3FrameOutF = totalPCMFrameCountFractionalPart + (pcmFramesInCurrentMP3FrameIn / srcRatio);
pcmFramesInCurrentMP3FrameOut = (drmp3_uint32)pcmFramesInCurrentMP3FrameOutF;
totalPCMFrameCountFractionalPart = pcmFramesInCurrentMP3FrameOutF - pcmFramesInCurrentMP3FrameOut;
totalPCMFrameCount += pcmFramesInCurrentMP3FrameOut;
totalPCMFrameCount += pcmFramesInCurrentMP3Frame;
totalMP3FrameCount += 1;
}
......@@ -3967,7 +3997,7 @@ DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pS
mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
/* We need to get information about this frame so we can know how many samples it contained. */
pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_FALSE);
pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
if (pcmFramesInCurrentMP3FrameIn == 0) {
return DRMP3_FALSE; /* This should never happen. */
}
......@@ -4011,7 +4041,7 @@ DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pS
Go to the next MP3 frame. This shouldn't ever fail, but just in case it does we just set the seek point and break. If it happens, it
should only ever do it for the last seek point.
*/
pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_TRUE);
pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
if (pcmFramesInCurrentMP3FrameIn == 0) {
pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
......@@ -4360,6 +4390,19 @@ counts rather than sample counts.
/*
REVISION HISTORY
================
v0.6.8 - 2020-04-26
- Optimizations to decoding when initializing from memory.
v0.6.7 - 2020-04-25
- Fix a compilation error with DR_MP3_NO_STDIO
- Optimization to decoding by reducing some data movement.
v0.6.6 - 2020-04-23
- Fix a minor bug with the running PCM frame counter.
v0.6.5 - 2020-04-19
- Fix compilation error on ARM builds.
v0.6.4 - 2020-04-19
- Bring up to date with changes to minimp3.
......
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