@ -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 stre am , o r 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 , n">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 , n">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 , n">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 , n">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 ) ;
}
DRFLAC_ASSERT ( origin = = 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 ) ;
while ( bytesSeeked < offset ) {
int bytesRemainingToSeek = offset - bytesSeeked ;
DRFLAC_ASSERT ( bytesRemainingToSeek > = 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 ( 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 ;
}
/* 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 , on Meta , 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 , on Meta , 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,12 +8680,42 @@ 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 , 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
return fseek ( ( FILE * ) pUserData , offset , ( origin = = drflac_seek_origin_current ) ? SEEK_CUR : SEEK_SET ) = = 0 ;
* pCursor = result ;
return DRFLAC_TRUE ;
}
DRFLAC_API drflac * drflac_open_file ( const char * pFileName , const drflac_allocation_callbacks * pAllocationCallbacks )
{
drflac * pFlac ;
@ -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 , n">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 , n">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 , n">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 , n">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 , on Meta , 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 , on Meta , 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 , n">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 , n">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 , n">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 .