mirror of
https://github.com/raysan5/raylib.git
synced 2025-09-05 19:08:13 +00:00
update dr_libs
This commit is contained in:
462
src/external/dr_flac.h
vendored
462
src/external/dr_flac.h
vendored
@@ -1,121 +1,12 @@
|
||||
/*
|
||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_flac - v0.12.42 - 2023-11-02
|
||||
dr_flac - v0.13.0 - TBD
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
GitHub: https://github.com/mackron/dr_libs
|
||||
*/
|
||||
|
||||
/*
|
||||
RELEASE NOTES - v0.12.0
|
||||
=======================
|
||||
Version 0.12.0 has breaking API changes including changes to the existing API and the removal of deprecated APIs.
|
||||
|
||||
|
||||
Improved Client-Defined Memory Allocation
|
||||
-----------------------------------------
|
||||
The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
|
||||
existing system of DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE are still in place and will be used by default when no custom
|
||||
allocation callbacks are specified.
|
||||
|
||||
To use the new system, you pass in a pointer to a drflac_allocation_callbacks object to drflac_open() and family, like this:
|
||||
|
||||
void* my_malloc(size_t sz, void* pUserData)
|
||||
{
|
||||
return malloc(sz);
|
||||
}
|
||||
void* my_realloc(void* p, size_t sz, void* pUserData)
|
||||
{
|
||||
return realloc(p, sz);
|
||||
}
|
||||
void my_free(void* p, void* pUserData)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
drflac_allocation_callbacks allocationCallbacks;
|
||||
allocationCallbacks.pUserData = &myData;
|
||||
allocationCallbacks.onMalloc = my_malloc;
|
||||
allocationCallbacks.onRealloc = my_realloc;
|
||||
allocationCallbacks.onFree = my_free;
|
||||
drflac* pFlac = drflac_open_file("my_file.flac", &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.
|
||||
|
||||
Passing in null for the allocation callbacks object will cause dr_flac to use defaults which is the same as DRFLAC_MALLOC,
|
||||
DRFLAC_REALLOC and DRFLAC_FREE and the equivalent of how it worked in previous versions.
|
||||
|
||||
Every API that opens a drflac object now takes this extra parameter. These include the following:
|
||||
|
||||
drflac_open()
|
||||
drflac_open_relaxed()
|
||||
drflac_open_with_metadata()
|
||||
drflac_open_with_metadata_relaxed()
|
||||
drflac_open_file()
|
||||
drflac_open_file_with_metadata()
|
||||
drflac_open_memory()
|
||||
drflac_open_memory_with_metadata()
|
||||
drflac_open_and_read_pcm_frames_s32()
|
||||
drflac_open_and_read_pcm_frames_s16()
|
||||
drflac_open_and_read_pcm_frames_f32()
|
||||
drflac_open_file_and_read_pcm_frames_s32()
|
||||
drflac_open_file_and_read_pcm_frames_s16()
|
||||
drflac_open_file_and_read_pcm_frames_f32()
|
||||
drflac_open_memory_and_read_pcm_frames_s32()
|
||||
drflac_open_memory_and_read_pcm_frames_s16()
|
||||
drflac_open_memory_and_read_pcm_frames_f32()
|
||||
|
||||
|
||||
|
||||
Optimizations
|
||||
-------------
|
||||
Seeking performance has been greatly improved. A new binary search based seeking algorithm has been introduced which significantly
|
||||
improves performance over the brute force method which was used when no seek table was present. Seek table based seeking also takes
|
||||
advantage of the new binary search seeking system to further improve performance there as well. Note that this depends on CRC which
|
||||
means it will be disabled when DR_FLAC_NO_CRC is used.
|
||||
|
||||
The SSE4.1 pipeline has been cleaned up and optimized. You should see some improvements with decoding speed of 24-bit files in
|
||||
particular. 16-bit streams should also see some improvement.
|
||||
|
||||
drflac_read_pcm_frames_s16() has been optimized. Previously this sat on top of drflac_read_pcm_frames_s32() and performed it's s32
|
||||
to s16 conversion in a second pass. This is now all done in a single pass. This includes SSE2 and ARM NEON optimized paths.
|
||||
|
||||
A minor optimization has been implemented for drflac_read_pcm_frames_s32(). This will now use an SSE2 optimized pipeline for stereo
|
||||
channel reconstruction which is the last part of the decoding process.
|
||||
|
||||
The ARM build has seen a few improvements. The CLZ (count leading zeroes) and REV (byte swap) instructions are now used when
|
||||
compiling with GCC and Clang which is achieved using inline assembly. The CLZ instruction requires ARM architecture version 5 at
|
||||
compile time and the REV instruction requires ARM architecture version 6.
|
||||
|
||||
An ARM NEON optimized pipeline has been implemented. To enable this you'll need to add -mfpu=neon to the command line when compiling.
|
||||
|
||||
|
||||
Removed APIs
|
||||
------------
|
||||
The following APIs were deprecated in version 0.11.0 and have been completely removed in version 0.12.0:
|
||||
|
||||
drflac_read_s32() -> drflac_read_pcm_frames_s32()
|
||||
drflac_read_s16() -> drflac_read_pcm_frames_s16()
|
||||
drflac_read_f32() -> drflac_read_pcm_frames_f32()
|
||||
drflac_seek_to_sample() -> drflac_seek_to_pcm_frame()
|
||||
drflac_open_and_decode_s32() -> drflac_open_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_s16() -> drflac_open_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_f32() -> drflac_open_and_read_pcm_frames_f32()
|
||||
drflac_open_and_decode_file_s32() -> drflac_open_file_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_file_s16() -> drflac_open_file_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_file_f32() -> drflac_open_file_and_read_pcm_frames_f32()
|
||||
drflac_open_and_decode_memory_s32() -> drflac_open_memory_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_memory_s16() -> drflac_open_memory_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_memory_f32() -> drflac_open_memroy_and_read_pcm_frames_f32()
|
||||
|
||||
Prior versions of dr_flac operated on a per-sample basis whereas now it operates on PCM frames. The removed APIs all relate
|
||||
to the old per-sample APIs. You now need to use the "pcm_frame" versions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Introduction
|
||||
============
|
||||
@@ -179,7 +70,7 @@ reports metadata to the application through the use of a callback, and every met
|
||||
|
||||
The main opening APIs (`drflac_open()`, etc.) will fail if the header is not present. The presents a problem in certain scenarios such as broadcast style
|
||||
streams or internet radio where the header may not be present because the user has started playback mid-stream. To handle this, use the relaxed APIs:
|
||||
|
||||
|
||||
`drflac_open_relaxed()`
|
||||
`drflac_open_with_metadata_relaxed()`
|
||||
|
||||
@@ -234,8 +125,8 @@ extern "C" {
|
||||
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
||||
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 12
|
||||
#define DRFLAC_VERSION_REVISION 42
|
||||
#define DRFLAC_VERSION_MINOR 13
|
||||
#define DRFLAC_VERSION_REVISION 0
|
||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@@ -348,11 +239,11 @@ but also more memory. In my testing there is diminishing returns after about 4KB
|
||||
#define DRFLAC_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
||||
#define DRFLAC_X64
|
||||
#elif defined(__i386) || defined(_M_IX86)
|
||||
#define DRFLAC_X86
|
||||
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
|
||||
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||
#define DRFLAC_ARM
|
||||
#endif
|
||||
/* End Architecture Detection */
|
||||
@@ -406,8 +297,9 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
drflac_seek_origin_start,
|
||||
drflac_seek_origin_current
|
||||
DRFLAC_SEEK_SET,
|
||||
DRFLAC_SEEK_CUR,
|
||||
DRFLAC_SEEK_END
|
||||
} drflac_seek_origin;
|
||||
|
||||
/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
|
||||
@@ -547,7 +439,7 @@ offset (in)
|
||||
The number of bytes to move, relative to the origin. Will never be negative.
|
||||
|
||||
origin (in)
|
||||
The origin of the seek - the current position or the start of the stream.
|
||||
The origin of the seek - the current position, the start of the stream, or the end of the stream.
|
||||
|
||||
|
||||
Return Value
|
||||
@@ -557,14 +449,32 @@ Whether or not the seek was successful.
|
||||
|
||||
Remarks
|
||||
-------
|
||||
The offset will never be negative. Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be
|
||||
either drflac_seek_origin_start or drflac_seek_origin_current.
|
||||
Seeking relative to the start and the current position must always be supported. If seeking from the end of the stream is not supported, return DRFLAC_FALSE.
|
||||
|
||||
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
|
||||
and handled by returning DRFLAC_FALSE.
|
||||
*/
|
||||
typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
|
||||
|
||||
/*
|
||||
Callback for when the current position in the stream needs to be retrieved.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pUserData (in)
|
||||
The user data that was passed to drflac_open() and family.
|
||||
|
||||
pCursor (out)
|
||||
A pointer to a variable to receive the current position in the stream.
|
||||
|
||||
|
||||
Return Value
|
||||
------------
|
||||
Whether or not the operation was successful.
|
||||
*/
|
||||
typedef drflac_bool32 (* drflac_tell_proc)(void* pUserData, drflac_int64* pCursor);
|
||||
|
||||
/*
|
||||
Callback for when a metadata block is read.
|
||||
|
||||
@@ -603,6 +513,9 @@ typedef struct
|
||||
/* The function to call when the current read position needs to be moved. */
|
||||
drflac_seek_proc onSeek;
|
||||
|
||||
/* The function to call when the current read position needs to be retrieved. */
|
||||
drflac_tell_proc onTell;
|
||||
|
||||
/* The user data to pass around to onRead and onSeek. */
|
||||
void* pUserData;
|
||||
|
||||
@@ -828,7 +741,7 @@ drflac_open_memory()
|
||||
drflac_open_with_metadata()
|
||||
drflac_close()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Opens a FLAC stream with relaxed validation of the header block.
|
||||
@@ -869,7 +782,7 @@ force your `onRead` callback to return 0, which dr_flac will use as an indicator
|
||||
|
||||
Use `drflac_open_with_metadata_relaxed()` if you need access to metadata.
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
|
||||
@@ -926,7 +839,7 @@ drflac_open_memory_with_metadata()
|
||||
drflac_open()
|
||||
drflac_close()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
|
||||
@@ -936,7 +849,7 @@ See Also
|
||||
drflac_open_with_metadata()
|
||||
drflac_open_relaxed()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Closes the given FLAC decoder.
|
||||
@@ -1234,13 +1147,13 @@ read samples into a dynamically sized buffer on the heap until no samples are le
|
||||
|
||||
Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
|
||||
*/
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
#ifndef DR_FLAC_NO_STDIO
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
|
||||
@@ -2960,25 +2873,25 @@ static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFro
|
||||
*/
|
||||
if (offsetFromStart > 0x7FFFFFFF) {
|
||||
drflac_uint64 bytesRemaining = offsetFromStart;
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
bytesRemaining -= 0x7FFFFFFF;
|
||||
|
||||
while (bytesRemaining > 0x7FFFFFFF) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
bytesRemaining -= 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (bytesRemaining > 0) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -5393,6 +5306,12 @@ static drflac_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Default to 0 for the LPC order. It's important that we always set this to 0 for non LPC
|
||||
and FIXED subframes because we'll be using it in a generic validation check later.
|
||||
*/
|
||||
pSubframe->lpcOrder = 0;
|
||||
|
||||
type = (header & 0x7E) >> 1;
|
||||
if (type == 0) {
|
||||
pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT;
|
||||
@@ -5465,6 +5384,18 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
|
||||
|
||||
pSubframe->pSamplesS32 = pDecodedSamplesOut;
|
||||
|
||||
/*
|
||||
pDecodedSamplesOut will be pointing to a buffer that was allocated with enough memory to store
|
||||
maxBlockSizeInPCMFrames samples (as specified in the FLAC header). We need to guard against an
|
||||
overflow here. At a higher level we are checking maxBlockSizeInPCMFrames from the header, but
|
||||
here we need to do an additional check to ensure this frame's block size fully encompasses any
|
||||
warmup samples which is determined by the LPC order. For non LPC and FIXED subframes, the LPC
|
||||
order will be have been set to 0 in drflac__read_subframe_header().
|
||||
*/
|
||||
if (frame->header.blockSizeInPCMFrames < pSubframe->lpcOrder) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
switch (pSubframe->subframeType)
|
||||
{
|
||||
case DRFLAC_SUBFRAME_CONSTANT:
|
||||
@@ -6312,6 +6243,7 @@ typedef struct
|
||||
{
|
||||
drflac_read_proc onRead;
|
||||
drflac_seek_proc onSeek;
|
||||
drflac_tell_proc onTell;
|
||||
drflac_meta_proc onMeta;
|
||||
drflac_container container;
|
||||
void* pUserData;
|
||||
@@ -6479,7 +6411,7 @@ static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbac
|
||||
}
|
||||
|
||||
|
||||
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
/*
|
||||
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
|
||||
@@ -6489,6 +6421,8 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
drflac_uint64 seektablePos = 0;
|
||||
drflac_uint32 seektableSize = 0;
|
||||
|
||||
(void)onTell;
|
||||
|
||||
for (;;) {
|
||||
drflac_metadata metadata;
|
||||
drflac_uint8 isLastBlock = 0;
|
||||
@@ -6702,10 +6636,10 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
|
||||
/* Skip to the index point count */
|
||||
pRunningData += 35;
|
||||
|
||||
|
||||
indexCount = pRunningData[0];
|
||||
pRunningData += 1;
|
||||
|
||||
|
||||
bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
|
||||
|
||||
/* Quick validation check. */
|
||||
@@ -6840,7 +6774,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
metadata.data.padding.unused = 0;
|
||||
|
||||
/* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||
} else {
|
||||
onMeta(pUserDataMD, &metadata);
|
||||
@@ -6852,7 +6786,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
{
|
||||
/* Invalid chunk. Just skip over this one. */
|
||||
if (onMeta) {
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||
}
|
||||
}
|
||||
@@ -6886,7 +6820,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
|
||||
/* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */
|
||||
if (onMeta == NULL && blockSize > 0) {
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -7220,6 +7154,7 @@ typedef struct
|
||||
{
|
||||
drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */
|
||||
drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */
|
||||
drflac_tell_proc onTell; /* The original onTell callback from drflac_open() and family. */
|
||||
void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */
|
||||
drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */
|
||||
drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */
|
||||
@@ -7241,32 +7176,32 @@ static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut,
|
||||
|
||||
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
|
||||
{
|
||||
if (origin == drflac_seek_origin_start) {
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
if (offset <= 0x7FFFFFFF) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos = offset;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
} else {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos = offset;
|
||||
|
||||
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
|
||||
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, DRFLAC_SEEK_CUR);
|
||||
}
|
||||
} else {
|
||||
while (offset > 0x7FFFFFFF) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos += 0x7FFFFFFF;
|
||||
offset -= 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) { /* <-- Safe cast thanks to the loop above. */
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_CUR)) { /* <-- Safe cast thanks to the loop above. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos += offset;
|
||||
@@ -7298,7 +7233,7 @@ static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs, drflac_og
|
||||
|
||||
if (header.serialNumber != oggbs->serialNumber) {
|
||||
/* It's not a FLAC page. Skip it. */
|
||||
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
|
||||
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
continue;
|
||||
@@ -7384,7 +7319,7 @@ static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
|
||||
At this point we will have found either the packet or the end of the page. If were at the end of the page we'll
|
||||
want to load the next page and keep searching for the end of the packet.
|
||||
*/
|
||||
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
|
||||
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, DRFLAC_SEEK_CUR);
|
||||
oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
|
||||
|
||||
if (atEndOfPage) {
|
||||
@@ -7462,8 +7397,8 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
|
||||
/* Seeking is always forward which makes things a lot simpler. */
|
||||
if (origin == drflac_seek_origin_start) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, drflac_seek_origin_start)) {
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
@@ -7471,38 +7406,50 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
|
||||
}
|
||||
return drflac__on_seek_ogg(pUserData, offset, DRFLAC_SEEK_CUR);
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
while (bytesSeeked < offset) {
|
||||
int bytesRemainingToSeek = offset - bytesSeeked;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
||||
|
||||
DRFLAC_ASSERT(origin == drflac_seek_origin_current);
|
||||
if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
|
||||
bytesSeeked += bytesRemainingToSeek;
|
||||
(void)bytesSeeked; /* <-- Silence a dead store warning emitted by Clang Static Analyzer. */
|
||||
oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
|
||||
break;
|
||||
}
|
||||
|
||||
while (bytesSeeked < offset) {
|
||||
int bytesRemainingToSeek = offset - bytesSeeked;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
||||
/* If we get here it means some of the requested data is contained in the next pages. */
|
||||
if (oggbs->bytesRemainingInPage > 0) {
|
||||
bytesSeeked += (int)oggbs->bytesRemainingInPage;
|
||||
oggbs->bytesRemainingInPage = 0;
|
||||
}
|
||||
|
||||
if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
|
||||
bytesSeeked += bytesRemainingToSeek;
|
||||
(void)bytesSeeked; /* <-- Silence a dead store warning emitted by Clang Static Analyzer. */
|
||||
oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we get here it means some of the requested data is contained in the next pages. */
|
||||
if (oggbs->bytesRemainingInPage > 0) {
|
||||
bytesSeeked += (int)oggbs->bytesRemainingInPage;
|
||||
oggbs->bytesRemainingInPage = 0;
|
||||
}
|
||||
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek > 0);
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
|
||||
/* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */
|
||||
return DRFLAC_FALSE;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek > 0);
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
|
||||
/* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
/* Seeking to the end is not supported. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_ogg(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
/*
|
||||
Not implemented for Ogg containers because we don't currently track the byte position of the logical bitstream. To support this, we'll need
|
||||
to track the position in drflac__on_read_ogg and drflac__on_seek_ogg.
|
||||
*/
|
||||
(void)pUserData;
|
||||
(void)pCursor;
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
|
||||
static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
|
||||
{
|
||||
@@ -7525,7 +7472,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
||||
runningGranulePosition = 0;
|
||||
for (;;) {
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||
drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
|
||||
drflac_oggbs__seek_physical(oggbs, originalBytePos, DRFLAC_SEEK_SET);
|
||||
return DRFLAC_FALSE; /* Never did find that sample... */
|
||||
}
|
||||
|
||||
@@ -7559,7 +7506,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
||||
a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
|
||||
we find the one containing the target sample.
|
||||
*/
|
||||
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||
@@ -7726,7 +7673,7 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
||||
The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
|
||||
be handling it in a generic way based on the serial number and packet types.
|
||||
*/
|
||||
if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, 2, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
@@ -7783,18 +7730,18 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
||||
}
|
||||
} else {
|
||||
/* Not a FLAC header. Skip it. */
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Not a FLAC header. Seek past the entire page and move on to the next. */
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -7819,18 +7766,19 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
||||
}
|
||||
#endif
|
||||
|
||||
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
||||
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
||||
{
|
||||
drflac_bool32 relaxed;
|
||||
drflac_uint8 id[4];
|
||||
|
||||
if (pInit == NULL || onRead == NULL || onSeek == NULL) {
|
||||
if (pInit == NULL || onRead == NULL || onSeek == NULL) { /* <-- onTell is optional. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
|
||||
pInit->onRead = onRead;
|
||||
pInit->onSeek = onSeek;
|
||||
pInit->onTell = onTell;
|
||||
pInit->onMeta = onMeta;
|
||||
pInit->container = container;
|
||||
pInit->pUserData = pUserData;
|
||||
@@ -7838,6 +7786,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
||||
|
||||
pInit->bs.onRead = onRead;
|
||||
pInit->bs.onSeek = onSeek;
|
||||
pInit->bs.onTell = onTell;
|
||||
pInit->bs.pUserData = pUserData;
|
||||
drflac__reset_cache(&pInit->bs);
|
||||
|
||||
@@ -7870,7 +7819,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
||||
headerSize += 10;
|
||||
}
|
||||
|
||||
if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, headerSize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE; /* Failed to seek past the tag. */
|
||||
}
|
||||
pInit->runningFilePos += headerSize;
|
||||
@@ -7922,7 +7871,7 @@ static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
|
||||
}
|
||||
|
||||
|
||||
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac_init_info init;
|
||||
drflac_uint32 allocationSize;
|
||||
@@ -7940,7 +7889,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
/* CPU support first. */
|
||||
drflac__init_cpu_caps();
|
||||
|
||||
if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
|
||||
if (!drflac__init_private(&init, onRead, onSeek, onTell, onMeta, container, pUserData, pUserDataMD)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7996,6 +7945,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
|
||||
pOggbs->onRead = onRead;
|
||||
pOggbs->onSeek = onSeek;
|
||||
pOggbs->onTell = onTell;
|
||||
pOggbs->pUserData = pUserData;
|
||||
pOggbs->currentBytePos = init.oggFirstBytePos;
|
||||
pOggbs->firstBytePos = init.oggFirstBytePos;
|
||||
@@ -8016,17 +7966,19 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
if (init.hasMetadataBlocks) {
|
||||
drflac_read_proc onReadOverride = onRead;
|
||||
drflac_seek_proc onSeekOverride = onSeek;
|
||||
drflac_tell_proc onTellOverride = onTell;
|
||||
void* pUserDataOverride = pUserData;
|
||||
|
||||
#ifndef DR_FLAC_NO_OGG
|
||||
if (init.container == drflac_container_ogg) {
|
||||
onReadOverride = drflac__on_read_ogg;
|
||||
onSeekOverride = drflac__on_seek_ogg;
|
||||
onTellOverride = drflac__on_tell_ogg;
|
||||
pUserDataOverride = (void*)pOggbs;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
||||
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onTellOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
||||
#ifndef DR_FLAC_NO_OGG
|
||||
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
||||
#endif
|
||||
@@ -8061,6 +8013,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
/* The Ogg bistream needs to be layered on top of the original bitstream. */
|
||||
pFlac->bs.onRead = drflac__on_read_ogg;
|
||||
pFlac->bs.onSeek = drflac__on_seek_ogg;
|
||||
pFlac->bs.onTell = drflac__on_tell_ogg;
|
||||
pFlac->bs.pUserData = (void*)pInternalOggbs;
|
||||
pFlac->_oggbs = (void*)pInternalOggbs;
|
||||
}
|
||||
@@ -8087,7 +8040,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
|
||||
|
||||
/* 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_SET)) {
|
||||
drflac_uint32 iSeekpoint;
|
||||
|
||||
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
|
||||
@@ -8105,7 +8058,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||
}
|
||||
|
||||
/* 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->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
|
||||
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, DRFLAC_SEEK_SET)) {
|
||||
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
|
||||
return NULL;
|
||||
}
|
||||
@@ -8276,7 +8229,7 @@ static drflac_result drflac_result_from_errno(int e)
|
||||
#ifdef ENOSYS
|
||||
case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
#ifdef ENOTEMPTY
|
||||
#if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST /* In AIX, ENOTEMPTY and EEXIST use the same value. */
|
||||
case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
@@ -8727,11 +8680,41 @@ 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)
|
||||
{
|
||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
int whence = SEEK_SET;
|
||||
if (origin == DRFLAC_SEEK_CUR) {
|
||||
whence = SEEK_CUR;
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
whence = SEEK_END;
|
||||
}
|
||||
|
||||
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
||||
return fseek((FILE*)pUserData, offset, whence) == 0;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
FILE* pFileStdio = (FILE*)pUserData;
|
||||
drflac_int64 result;
|
||||
|
||||
/* These were all validated at a higher level. */
|
||||
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
result = ftell(pFileStdio);
|
||||
#endif
|
||||
#else
|
||||
result = ftell(pFileStdio);
|
||||
#endif
|
||||
|
||||
*pCursor = result;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
@@ -8742,7 +8725,7 @@ DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocati
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return NULL;
|
||||
@@ -8761,7 +8744,7 @@ DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_all
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return NULL;
|
||||
@@ -8780,7 +8763,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return pFlac;
|
||||
@@ -8799,7 +8782,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, dr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return pFlac;
|
||||
@@ -8834,28 +8817,45 @@ static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t by
|
||||
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
|
||||
{
|
||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||
drflac_int64 newCursor;
|
||||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
|
||||
if (offset > (drflac_int64)memoryStream->dataSize) {
|
||||
newCursor = memoryStream->currentReadPos;
|
||||
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
newCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
newCursor = (drflac_int64)memoryStream->dataSize;
|
||||
} else {
|
||||
DRFLAC_ASSERT(!"Invalid seek origin");
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
if (origin == drflac_seek_origin_current) {
|
||||
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
|
||||
memoryStream->currentReadPos += offset;
|
||||
} else {
|
||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
||||
}
|
||||
} else {
|
||||
if ((drflac_uint32)offset <= memoryStream->dataSize) {
|
||||
memoryStream->currentReadPos = offset;
|
||||
} else {
|
||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
||||
}
|
||||
newCursor += offset;
|
||||
|
||||
if (newCursor < 0) {
|
||||
return DRFLAC_FALSE; /* Trying to seek prior to the start of the buffer. */
|
||||
}
|
||||
if ((size_t)newCursor > memoryStream->dataSize) {
|
||||
return DRFLAC_FALSE; /* Trying to seek beyond the end of the buffer. */
|
||||
}
|
||||
|
||||
memoryStream->currentReadPos = (size_t)newCursor;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_memory(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
*pCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
@@ -8867,7 +8867,7 @@ DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const
|
||||
memoryStream.data = (const drflac_uint8*)pData;
|
||||
memoryStream.dataSize = dataSize;
|
||||
memoryStream.currentReadPos = 0;
|
||||
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, &memoryStream, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -8898,7 +8898,7 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
||||
memoryStream.data = (const drflac_uint8*)pData;
|
||||
memoryStream.dataSize = dataSize;
|
||||
memoryStream.currentReadPos = 0;
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -8923,22 +8923,22 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
||||
|
||||
|
||||
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
DRFLAC_API void drflac_close(drflac* pFlac)
|
||||
@@ -11770,7 +11770,7 @@ DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s32, drflac_int32)
|
||||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
|
||||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
|
||||
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
@@ -11784,7 +11784,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
||||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -11792,7 +11792,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
||||
return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||
}
|
||||
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
@@ -11806,7 +11806,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
||||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -11814,7 +11814,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
||||
return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||
}
|
||||
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
@@ -11828,7 +11828,7 @@ DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, d
|
||||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -12077,6 +12077,26 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.13.0 - TBD
|
||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||
- DRFLAC_SEEK_END (new)
|
||||
- API CHANGE: A new seek origin has been added to allow seeking from the end of the file. If you implement your own `onSeek` callback, you should now detect and handle `DRFLAC_SEEK_END`. If seeking to the end is not supported, return `DRFLAC_FALSE`. If you only use `*_open_file()` or `*_open_memory()`, you need not change anything.
|
||||
- API CHANGE: An `onTell` callback has been added to the following functions:
|
||||
- drflac_open()
|
||||
- drflac_open_relaxed()
|
||||
- drflac_open_with_metadata()
|
||||
- drflac_open_with_metadata_relaxed()
|
||||
- drflac_open_and_read_pcm_frames_s32()
|
||||
- drflac_open_and_read_pcm_frames_s16()
|
||||
- drflac_open_and_read_pcm_frames_f32()
|
||||
- Fix compilation for AIX OS.
|
||||
|
||||
v0.12.43 - 2024-12-17
|
||||
- Fix a possible buffer overflow during decoding.
|
||||
- Improve detection of ARM64EC
|
||||
|
||||
v0.12.42 - 2023-11-02
|
||||
- Fix build for ARMv6-M.
|
||||
- Fix a compilation warning with GCC.
|
||||
|
899
src/external/dr_mp3.h
vendored
899
src/external/dr_mp3.h
vendored
File diff suppressed because it is too large
Load Diff
492
src/external/dr_wav.h
vendored
492
src/external/dr_wav.h
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user