view release on metacpan or search on metacpan
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
/*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.12.38 - 2022-04-10
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()
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
/*
Callback for when data needs to be seeked.
Parameters
----------
pUserData (in)
The user data that was passed to drflac_open() and family.
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.
Return Value
------------
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.
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 a metadata block is read.
Parameters
----------
pUserData (in)
The user data that was passed to drflac_open() and family.
pMetadata (in)
A pointer to a structure containing the data of the metadata block.
Remarks
-------
Use pMetadata->type to determine which metadata block is being handled and how to read the data. This
will be set to one of the DRFLAC_METADATA_BLOCK_TYPE_* tokens.
*/
typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata);
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} drflac_allocation_callbacks;
/* Structure for internal use. Only used for decoders opened with drflac_open_memory. */
typedef struct
{
const drflac_uint8* data;
size_t dataSize;
size_t currentReadPos;
} drflac__memory_stream;
/* Structure for internal use. Used for bit streaming. */
typedef struct
{
/* The function to call when more data needs to be read. */
drflac_read_proc onRead;
/* The function to call when the current read position needs to be moved. */
drflac_seek_proc onSeek;
/* The user data to pass around to onRead and onSeek. */
void* pUserData;
/*
The number of unaligned bytes in the L2 cache. This will always be 0 until the end of the stream is hit. At the end of the
stream there will be a number of bytes that don't cleanly fit in an L1 cache line, so we use this variable to know whether
or not the bistreamer needs to run on a slower path to read those last bytes. This will never be more than sizeof(drflac_cache_t).
*/
size_t unalignedByteCount;
/* The content of the unaligned bytes. */
drflac_cache_t unalignedCache;
/* The index of the next valid cache line in the "L2" cache. */
drflac_uint32 nextL2Line;
/* The number of bits that have been consumed by the cache. This is used to determine how many valid bits are remaining. */
drflac_uint32 consumedBits;
/*
The cached data which was most recently read from the client. There are two levels of cache. Data flows as such:
Client -> L2 -> L1. The L2 -> L1 movement is aligned and runs on a fast path in just a few instructions.
*/
drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)];
drflac_cache_t cache;
/*
CRC-16. This is updated whenever bits are read from the bit stream. Manually set this to 0 to reset the CRC. For FLAC, this
is reset to 0 at the beginning of each frame.
*/
drflac_uint16 crc16;
drflac_cache_t crc16Cache; /* A cache for optimizing CRC calculations. This is filled when when the L1 cache is reloaded. */
drflac_uint32 crc16CacheIgnoredBytes; /* The number of bytes to ignore when updating the CRC-16 from the CRC-16 cache. */
} drflac_bs;
typedef struct
{
/* The type of the subframe: SUBFRAME_CONSTANT, SUBFRAME_VERBATIM, SUBFRAME_FIXED or SUBFRAME_LPC. */
drflac_uint8 subframeType;
/* The number of wasted bits per sample as specified by the sub-frame header. */
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
/* A pointer to the buffer containing the decoded samples in the subframe. This pointer is an offset from drflac::pExtraData. */
drflac_int32* pSamplesS32;
} drflac_subframe;
typedef struct
{
/*
If the stream uses variable block sizes, this will be set to the index of the first PCM frame. If fixed block sizes are used, this will
always be set to 0. This is 64-bit because the decoded PCM frame number will be 36 bits.
*/
drflac_uint64 pcmFrameNumber;
/*
If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. This
is 32-bit because in fixed block sizes, the maximum frame number will be 31 bits.
*/
drflac_uint32 flacFrameNumber;
/* The sample rate of this frame. */
drflac_uint32 sampleRate;
/* The number of PCM frames in each sub-frame within this frame. */
drflac_uint16 blockSizeInPCMFrames;
/*
The channel assignment of this frame. This is not always set to the channel count. If interchannel decorrelation is being used this
will be set to DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE, DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE or DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE.
*/
drflac_uint8 channelAssignment;
/* The number of bits per sample within this frame. */
drflac_uint8 bitsPerSample;
/* The frame's CRC. */
drflac_uint8 crc8;
} drflac_frame_header;
typedef struct
{
/* The header. */
drflac_frame_header header;
/*
The number of PCM frames left to be read in this FLAC frame. This is initially set to the block size. As PCM frames are read,
this will be decremented. When it reaches 0, the decoder will see this frame as fully consumed and load the next frame.
*/
drflac_uint32 pcmFramesRemaining;
/* The list of sub-frames within the frame. There is one sub-frame for each channel, and there's a maximum of 8 channels. */
drflac_subframe subframes[8];
} drflac_frame;
typedef struct
{
/* The function to call when a metadata block is read. */
drflac_meta_proc onMeta;
/* The user data posted to the metadata callback function. */
void* pUserDataMD;
/* Memory allocation callbacks. */
drflac_allocation_callbacks allocationCallbacks;
/* The sample rate. Will be set to something like 44100. */
drflac_uint32 sampleRate;
/*
The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. Maximum 8. This is set based on the
value specified in the STREAMINFO block.
*/
drflac_uint8 channels;
/* The bits per sample. Will be set to something like 16, 24, etc. */
drflac_uint8 bitsPerSample;
/* The maximum block size, in samples. This number represents the number of samples in each channel (not combined). */
drflac_uint16 maxBlockSizeInPCMFrames;
/*
The total number of PCM Frames making up the stream. Can be 0 in which case it's still a valid stream, but just means
the total PCM frame count is unknown. Likely the case with streams like internet radio.
*/
drflac_uint64 totalPCMFrameCount;
/* The container type. This is set based on whether or not the decoder was opened from a native or Ogg stream. */
drflac_container container;
/* The number of seekpoints in the seektable. */
drflac_uint32 seekpointCount;
/* Information about the frame the decoder is currently sitting on. */
drflac_frame currentFLACFrame;
/* The index of the PCM frame the decoder is currently sitting on. This is only used for seeking. */
drflac_uint64 currentPCMFrame;
/* The position of the first FLAC frame in the stream. This is only ever used for seeking. */
drflac_uint64 firstFLACFramePosInBytes;
/* A hack to avoid a malloc() when opening a decoder with drflac_open_memory(). */
drflac__memory_stream memoryStream;
/* A pointer to the decoded sample data. This is an offset of pExtraData. */
drflac_int32* pDecodedSamples;
/* A pointer to the seek table. This is an offset of pExtraData, or NULL if there is no seek table. */
drflac_seekpoint* pSeekpoints;
/* Internal use only. Only used with Ogg containers. Points to a drflac_oggbs object. This is an offset of pExtraData. */
void* _oggbs;
/* Internal use only. Used for profiling and testing different seeking modes. */
drflac_bool32 _noSeekTableSeek : 1;
drflac_bool32 _noBinarySearchSeek : 1;
drflac_bool32 _noBruteForceSeek : 1;
/* The bit streamer. The raw FLAC data is fed through this object. */
drflac_bs bs;
/* Variable length extra data. We attach this to the end of the object so we can avoid unnecessary mallocs. */
drflac_uint8 pExtraData[1];
} drflac;
/*
Opens a FLAC decoder.
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
onSeek (in)
The function to call when the read position of the client data needs to move.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead and onSeek.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
Returns a pointer to an object representing the decoder.
Remarks
-------
Close the decoder with `drflac_close()`.
`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated FLAC, both of which should work seamlessly
without any manual intervention. Ogg encapsulation also works with multiplexed streams which basically means it can play FLAC encoded audio tracks in videos.
This is the lowest level function for opening a FLAC stream. You can also use `drflac_open_file()` and `drflac_open_memory()` to open the stream from a file or
from a block of memory respectively.
The STREAMINFO block must be present for this to succeed. Use `drflac_open_relaxed()` to open a FLAC stream where the header may not be present.
Use `drflac_open_with_metadata()` if you need access to metadata.
Seek Also
---------
drflac_open_file()
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);
/*
Opens a FLAC stream with relaxed validation of the header block.
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
onSeek (in)
The function to call when the read position of the client data needs to move.
container (in)
Whether or not the FLAC stream is encapsulated using standard FLAC encapsulation or Ogg encapsulation.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead and onSeek.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
The same as drflac_open(), except attempts to open the stream even when a header block is not present.
Because the header is not necessarily available, the caller must explicitly define the container (Native or Ogg). Do not set this to `drflac_container_unknown`
as that is for internal use only.
Opening in relaxed mode will continue reading data from onRead until it finds a valid frame. If a frame is never found it will continue forever. To abort,
force your `onRead` callback to return 0, which dr_flac will use as an indicator that the end of the stream was found.
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);
/*
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
onSeek (in)
The function to call when the read position of the client data needs to move.
onMeta (in)
The function to call for every metadata block.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead, onSeek and onMeta.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
Close the decoder with `drflac_close()`.
`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
This is slower than `drflac_open()`, so avoid this one if you don't need metadata. Internally, this will allocate and free memory on the heap for every
metadata block except for STREAMINFO and PADDING blocks.
The caller is notified of the metadata via the `onMeta` callback. All metadata blocks will be handled before the function returns. This callback takes a
pointer to a `drflac_metadata` object which is a union containing the data of all relevant metadata blocks. Use the `type` member to discriminate against
the different metadata types.
The STREAMINFO block must be present for this to succeed. Use `drflac_open_with_metadata_relaxed()` to open a FLAC stream where the header may not be present.
Note that this will behave inconsistently with `drflac_open()` if the stream is an Ogg encapsulated stream and a metadata block is corrupted. This is due to
the way the Ogg stream recovers from corrupted pages. When `drflac_open_with_metadata()` is being used, the open routine will try to read the contents of the
metadata block, whereas `drflac_open()` will simply seek past it (for the sake of efficiency). This inconsistency can result in different samples being
returned depending on whether or not the stream is being opened with metadata.
Seek Also
---------
drflac_open_file_with_metadata()
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);
/*
The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
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);
/*
Closes the given FLAC decoder.
Parameters
----------
pFlac (in)
The decoder to close.
Remarks
-------
This will destroy the decoder object.
See Also
--------
drflac_open()
drflac_open_with_metadata()
drflac_open_file()
drflac_open_file_w()
drflac_open_file_with_metadata()
drflac_open_file_with_metadata_w()
drflac_open_memory()
drflac_open_memory_with_metadata()
*/
DRFLAC_API void drflac_close(drflac* pFlac);
/*
Reads sample data from the given FLAC decoder, output as interleaved signed 32-bit PCM.
Parameters
----------
pFlac (in)
The decoder.
framesToRead (in)
The number of PCM frames to read.
pBufferOut (out, optional)
A pointer to the buffer that will receive the decoded samples.
Return Value
------------
Returns the number of PCM frames actually read. If the return value is less than `framesToRead` it has reached the end.
Remarks
-------
pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of frames seeked.
*/
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s32(drflac* pFlac, drflac_uint64 framesToRead, drflac_int32* pBufferOut);
/*
Reads sample data from the given FLAC decoder, output as interleaved signed 16-bit PCM.
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
Reads sample data from the given FLAC decoder, output as interleaved 32-bit floating point PCM.
Parameters
----------
pFlac (in)
The decoder.
framesToRead (in)
The number of PCM frames to read.
pBufferOut (out, optional)
A pointer to the buffer that will receive the decoded samples.
Return Value
------------
Returns the number of PCM frames actually read. If the return value is less than `framesToRead` it has reached the end.
Remarks
-------
pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of frames seeked.
Note that this should be considered lossy due to the nature of floating point numbers not being able to exactly represent every possible number.
*/
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut);
/*
Seeks to the PCM frame at the given index.
Parameters
----------
pFlac (in)
The decoder.
pcmFrameIndex (in)
The index of the PCM frame to seek to. See notes below.
Return Value
-------------
`DRFLAC_TRUE` if successful; `DRFLAC_FALSE` otherwise.
*/
DRFLAC_API drflac_bool32 drflac_seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex);
#ifndef DR_FLAC_NO_STDIO
/*
Opens a FLAC decoder from the file at the given path.
Parameters
----------
pFileName (in)
The path of the file to open, either absolute or relative to the current directory.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
Close the decoder with drflac_close().
Remarks
-------
This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the number of files a process can have open
at any given time, so keep this mind if you have many decoders open at the same time.
See Also
--------
drflac_open_file_with_metadata()
drflac_open()
drflac_close()
*/
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
/*
Opens a FLAC decoder from the file at the given path and notifies the caller of the metadata chunks (album art, etc.)
Parameters
----------
pFileName (in)
The path of the file to open, either absolute or relative to the current directory.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
onMeta (in)
The callback to fire for each metadata block.
pUserData (in)
A pointer to the user data to pass to the metadata callback.
pAllocationCallbacks (in)
A pointer to application defined callbacks for managing memory allocations.
Remarks
-------
Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
See Also
--------
drflac_open_with_metadata()
drflac_open()
drflac_close()
*/
DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
#endif
/*
Opens a FLAC decoder from a pre-allocated block of memory
Parameters
----------
pData (in)
A pointer to the raw encoded FLAC data.
dataSize (in)
The size in bytes of `data`.
pAllocationCallbacks (in)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for the lifetime of the decoder.
See Also
--------
drflac_open()
drflac_close()
*/
DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks);
/*
Opens a FLAC decoder from a pre-allocated block of memory and notifies the caller of the metadata chunks (album art, etc.)
Parameters
----------
pData (in)
A pointer to the raw encoded FLAC data.
dataSize (in)
The size in bytes of `data`.
onMeta (in)
The callback to fire for each metadata block.
pUserData (in)
A pointer to the user data to pass to the metadata callback.
pAllocationCallbacks (in)
A pointer to application defined callbacks for managing memory allocations.
Remarks
-------
Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
See Also
-------
drflac_open_with_metadata()
drflac_open()
drflac_close()
*/
DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
/* High Level APIs */
/*
Opens a FLAC stream from the given callbacks and fully decodes it in a single operation. The return value is a
pointer to the sample data as interleaved signed 32-bit PCM. The returned data must be freed with drflac_free().
You can pass in custom memory allocation callbacks via the pAllocationCallbacks parameter. This can be NULL in which
case it will use DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE.
Sometimes a FLAC file won't keep track of the total sample count. In this situation the function will continuously
read samples into a dynamically sized buffer on the heap until no samples are left.
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* pA...
/* 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* pA...
/* 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* pAllocati...
#ifndef DR_FLAC_NO_STDIO
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
/* Same as drflac_open_file_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
/* Same as drflac_open_file_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
#endif
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a block of memory. */
DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
/* Same as drflac_open_memory_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
/* Same as drflac_open_memory_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
/*
Frees memory that was allocated internally by dr_flac.
Set pAllocationCallbacks to the same object that was passed to drflac_open_*_and_read_pcm_frames_*(). If you originally passed in NULL, pass in NULL for this.
*/
DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks);
/* Structure representing an iterator for vorbis comments in a VORBIS_COMMENT metadata block. */
typedef struct
{
drflac_uint32 countRemaining;
const char* pRunningData;
} drflac_vorbis_comment_iterator;
/*
Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT
metadata block.
*/
DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
/*
Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The
returned string is NOT null terminated.
*/
DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut);
/* Structure representing an iterator for cuesheet tracks in a CUESHEET metadata block. */
typedef struct
{
drflac_uint32 countRemaining;
const char* pRunningData;
} drflac_cuesheet_track_iterator;
/* Packing is important on this structure because we map this directly to the raw data within the CUESHEET metadata block. */
#pragma pack(4)
typedef struct
{
drflac_uint64 offset;
drflac_uint8 index;
drflac_uint8 reserved[3];
} drflac_cuesheet_track_index;
#pragma pack()
typedef struct
{
drflac_uint64 offset;
drflac_uint8 trackNumber;
char ISRC[12];
drflac_bool8 isAudio;
drflac_bool8 preEmphasis;
drflac_uint8 indexCount;
const drflac_cuesheet_track_index* pIndexPoints;
} drflac_cuesheet_track;
/*
Initializes a cuesheet track iterator. This can be used for iterating over the cuesheet tracks in a CUESHEET metadata
block.
*/
DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
/* Goes to the next cuesheet track in the given iterator. If DRFLAC_FALSE is returned it means there are no more comments. */
DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack);
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
} else
#endif
{
#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
return drflac__clz_msvc(x);
#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
#else
return drflac__clz_software(x);
#endif
}
}
static DRFLAC_INLINE drflac_bool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut)
{
drflac_uint32 zeroCounter = 0;
drflac_uint32 setBitOffsetPlus1;
while (bs->cache == 0) {
zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
if (!drflac__reload_cache(bs)) {
return DRFLAC_FALSE;
}
}
if (bs->cache == 1) {
/* Not catching this would lead to undefined behaviour: a shift of a 32-bit number by 32 or more is undefined */
*pOffsetOut = zeroCounter + (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs) - 1;
if (!drflac__reload_cache(bs)) {
return DRFLAC_FALSE;
}
return DRFLAC_TRUE;
}
setBitOffsetPlus1 = drflac__clz(bs->cache);
setBitOffsetPlus1 += 1;
if (setBitOffsetPlus1 > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
/* This happens when we get to end of stream */
return DRFLAC_FALSE;
}
bs->consumedBits += setBitOffsetPlus1;
bs->cache <<= setBitOffsetPlus1;
*pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1;
return DRFLAC_TRUE;
}
static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFromStart)
{
DRFLAC_ASSERT(bs != NULL);
DRFLAC_ASSERT(offsetFromStart > 0);
/*
Seeking from the start is not quite as trivial as it sounds because the onSeek callback takes a signed 32-bit integer (which
is intentional because it simplifies the implementation of the onSeek callbacks), however offsetFromStart is unsigned 64-bit.
To resolve we just need to do an initial seek from the start, and then a series of offset seeks to make up the remainder.
*/
if (offsetFromStart > 0x7FFFFFFF) {
drflac_uint64 bytesRemaining = offsetFromStart;
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
return DRFLAC_FALSE;
}
bytesRemaining -= 0x7FFFFFFF;
while (bytesRemaining > 0x7FFFFFFF) {
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
return DRFLAC_FALSE;
}
bytesRemaining -= 0x7FFFFFFF;
}
if (bytesRemaining > 0) {
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
return DRFLAC_FALSE;
}
}
} else {
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
return DRFLAC_FALSE;
}
}
/* The cache should be reset to force a reload of fresh data from the client. */
drflac__reset_cache(bs);
return DRFLAC_TRUE;
}
static drflac_result drflac__read_utf8_coded_number(drflac_bs* bs, drflac_uint64* pNumberOut, drflac_uint8* pCRCOut)
{
drflac_uint8 crc;
drflac_uint64 result;
drflac_uint8 utf8[7] = {0};
int byteCount;
int i;
DRFLAC_ASSERT(bs != NULL);
DRFLAC_ASSERT(pNumberOut != NULL);
DRFLAC_ASSERT(pCRCOut != NULL);
crc = *pCRCOut;
if (!drflac__read_uint8(bs, 8, utf8)) {
*pNumberOut = 0;
return DRFLAC_AT_END;
}
crc = drflac_crc8(crc, utf8[0], 8);
if ((utf8[0] & 0x80) == 0) {
*pNumberOut = utf8[0];
*pCRCOut = crc;
return DRFLAC_SUCCESS;
}
/*byteCount = 1;*/
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
drflac_uint64 importantProps;
drflac_uint8 md5[16];
/* min/max block size. */
if (onRead(pUserData, &blockSizes, 4) != 4) {
return DRFLAC_FALSE;
}
/* min/max frame size. */
if (onRead(pUserData, &frameSizes, 6) != 6) {
return DRFLAC_FALSE;
}
/* Sample rate, channels, bits per sample and total sample count. */
if (onRead(pUserData, &importantProps, 8) != 8) {
return DRFLAC_FALSE;
}
/* MD5 */
if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) {
return DRFLAC_FALSE;
}
blockSizes = drflac__be2host_32(blockSizes);
frameSizes = drflac__be2host_64(frameSizes);
importantProps = drflac__be2host_64(importantProps);
pStreamInfo->minBlockSizeInPCMFrames = (drflac_uint16)((blockSizes & 0xFFFF0000) >> 16);
pStreamInfo->maxBlockSizeInPCMFrames = (drflac_uint16) (blockSizes & 0x0000FFFF);
pStreamInfo->minFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 24)) >> 40);
pStreamInfo->maxFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 0)) >> 16);
pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (((drflac_uint64)0x000FFFFF << 16) << 28)) >> 44);
pStreamInfo->channels = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000000E << 16) << 24)) >> 41) + 1;
pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000001F << 16) << 20)) >> 36) + 1;
pStreamInfo->totalPCMFrameCount = ((importantProps & ((((drflac_uint64)0x0000000F << 16) << 16) | 0xFFFFFFFF)));
DRFLAC_COPY_MEMORY(pStreamInfo->md5, md5, sizeof(md5));
return DRFLAC_TRUE;
}
static void* drflac__malloc_default(size_t sz, void* pUserData)
{
(void)pUserData;
return DRFLAC_MALLOC(sz);
}
static void* drflac__realloc_default(void* p, size_t sz, void* pUserData)
{
(void)pUserData;
return DRFLAC_REALLOC(p, sz);
}
static void drflac__free_default(void* p, void* pUserData)
{
(void)pUserData;
DRFLAC_FREE(p);
}
static void* drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onMalloc != NULL) {
return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
}
/* Try using realloc(). */
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
}
return NULL;
}
static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
}
/* Try emulating realloc() in terms of malloc()/free(). */
if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
void* p2;
p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
if (p2 == NULL) {
return NULL;
}
if (p != NULL) {
DRFLAC_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2;
}
return NULL;
}
static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (p == NULL || pAllocationCallbacks == NULL) {
return;
}
if (pAllocationCallbacks->onFree != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
}
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* pSeektabl...
{
/*
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
we'll be sitting on byte 42.
*/
drflac_uint64 runningFilePos = 42;
drflac_uint64 seektablePos = 0;
drflac_uint32 seektableSize = 0;
for (;;) {
drflac_metadata metadata;
drflac_uint8 isLastBlock = 0;
drflac_uint8 blockType;
drflac_uint32 blockSize;
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
return DRFLAC_FALSE;
}
runningFilePos += 4;
metadata.type = blockType;
metadata.pRawData = NULL;
metadata.rawDataSize = 0;
switch (blockType)
{
case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION:
{
if (blockSize < 4) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData);
metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32));
metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32);
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE:
{
seektablePos = runningFilePos;
seektableSize = blockSize;
if (onMeta) {
drflac_uint32 iSeekpoint;
void* pRawData;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
/* Endian swap. */
for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT:
{
if (blockSize < 8) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
drflac_uint32 i;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
metadata.data.vorbis_comment.vendorLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for the rest of the block */
if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */
if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.vorbis_comment.pComments = pRunningData;
/* Check that the comments section is valid before passing it to the callback */
for (i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
drflac_uint32 commentLength;
if (pRunningDataEnd - pRunningData < 4) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
commentLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
pRunningData += commentLength;
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
{
if (blockSize < 396) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
drflac_uint8 iTrack;
drflac_uint8 iIndex;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
DRFLAC_COPY_MEMORY(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
metadata.data.cuesheet.pTrackData = pRunningData;
/* Check that the cuesheet tracks are valid before passing it to the callback */
for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
drflac_uint8 indexCount;
drflac_uint32 indexPointSize;
if (pRunningDataEnd - pRunningData < 36) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
/* Skip to the index point count */
pRunningData += 35;
indexCount = pRunningData[0]; pRunningData += 1;
indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
/* Endian swap. */
for (iIndex = 0; iIndex < indexCount; ++iIndex) {
drflac_cuesheet_track_index* pTrack = (drflac_cuesheet_track_index*)pRunningData;
pRunningData += sizeof(drflac_cuesheet_track_index);
pTrack->offset = drflac__be2host_64(pTrack->offset);
}
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
{
if (blockSize < 32) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for the rest of the block */
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for the rest of the block */
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
/* Need space for the picture after the block */
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_PADDING:
{
if (onMeta) {
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)) {
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);
}
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_INVALID:
{
/* Invalid chunk. Just skip over this one. */
if (onMeta) {
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
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. */
}
}
} break;
default:
{
/*
It's an unknown chunk, but not necessarily invalid. There's a chance more metadata blocks might be defined later on, so we
can at the very least report the chunk to the application and let it look at the raw data.
*/
if (onMeta) {
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
}
/* 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)) {
isLastBlock = DRFLAC_TRUE;
}
}
runningFilePos += blockSize;
if (isLastBlock) {
break;
}
}
*pSeektablePos = seektablePos;
*pSeektableSize = seektableSize;
*pFirstFramePos = runningFilePos;
return DRFLAC_TRUE;
}
static drflac_bool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed)
{
/* Pre Condition: The bit stream should be sitting just past the 4-byte id header. */
drflac_uint8 isLastBlock;
drflac_uint8 blockType;
drflac_uint32 blockSize;
(void)onSeek;
pInit->container = drflac_container_native;
/* The first metadata block should be the STREAMINFO block. */
if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
return DRFLAC_FALSE;
}
if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
if (!relaxed) {
/* We're opening in strict mode and the first block is not the STREAMINFO block. Error. */
return DRFLAC_FALSE;
} else {
/*
Relaxed mode. To open from here we need to just find the first frame and set the sample rate, etc. to whatever is defined
for that frame.
*/
pInit->hasStreamInfoBlock = DRFLAC_FALSE;
pInit->hasMetadataBlocks = DRFLAC_FALSE;
if (!drflac__read_next_flac_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) {
return DRFLAC_FALSE; /* Couldn't find a frame. */
}
if (pInit->firstFrameHeader.bitsPerSample == 0) {
return DRFLAC_FALSE; /* Failed to initialize because the first frame depends on the STREAMINFO block, which does not exist. */
}
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
if (onRead(pUserData, pHeader->segmentTable, pHeader->segmentCount) != pHeader->segmentCount) {
return DRFLAC_AT_END;
}
*pBytesRead += pHeader->segmentCount;
for (i = 0; i < pHeader->segmentCount; ++i) {
*pCRC32 = drflac_crc32_byte(*pCRC32, pHeader->segmentTable[i]);
}
return DRFLAC_SUCCESS;
}
static drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, drflac_uint32* pBytesRead, drflac_uint32* pCRC32)
{
drflac_uint8 id[4];
*pBytesRead = 0;
if (onRead(pUserData, id, 4) != 4) {
return DRFLAC_AT_END;
}
*pBytesRead += 4;
/* We need to read byte-by-byte until we find the OggS capture pattern. */
for (;;) {
if (drflac_ogg__is_capture_pattern(id)) {
drflac_result result;
*pCRC32 = DRFLAC_OGG_CAPTURE_PATTERN_CRC32;
result = drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, pHeader, pBytesRead, pCRC32);
if (result == DRFLAC_SUCCESS) {
return DRFLAC_SUCCESS;
} else {
if (result == DRFLAC_CRC_MISMATCH) {
continue;
} else {
return result;
}
}
} else {
/* The first 4 bytes did not equal the capture pattern. Read the next byte and try again. */
id[0] = id[1];
id[1] = id[2];
id[2] = id[3];
if (onRead(pUserData, &id[3], 1) != 1) {
return DRFLAC_AT_END;
}
*pBytesRead += 1;
}
}
}
/*
The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works
in three general stages: Ogg Physical Bitstream -> Ogg/FLAC Logical Bitstream -> FLAC Native Bitstream. dr_flac is designed
in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type
dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from
the physical Ogg bitstream are converted and delivered in native FLAC format.
*/
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. */
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. */
drflac_uint32 serialNumber; /* The serial number of the FLAC audio pages. This is determined by the initial header page that was read during initialization. */
drflac_ogg_page_header bosPageHeader; /* Used for seeking. */
drflac_ogg_page_header currentPageHeader;
drflac_uint32 bytesRemainingInPage;
drflac_uint32 pageDataSize;
drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE];
} drflac_oggbs; /* oggbs = Ogg Bitstream */
static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, size_t bytesToRead)
{
size_t bytesActuallyRead = oggbs->onRead(oggbs->pUserData, bufferOut, bytesToRead);
oggbs->currentBytePos += bytesActuallyRead;
return bytesActuallyRead;
}
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
{
if (origin == drflac_seek_origin_start) {
if (offset <= 0x7FFFFFFF) {
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
return DRFLAC_FALSE;
}
oggbs->currentBytePos = offset;
return DRFLAC_TRUE;
} else {
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
return DRFLAC_FALSE;
}
oggbs->currentBytePos = offset;
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
}
} else {
while (offset > 0x7FFFFFFF) {
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
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. */
return DRFLAC_FALSE;
}
oggbs->currentBytePos += offset;
return DRFLAC_TRUE;
}
}
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
flags = header[1];
DRFLAC_COPY_MEMORY(&headerSize, header+2, 4);
headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize));
if (flags & 0x10) {
headerSize += 10;
}
if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
return DRFLAC_FALSE; /* Failed to seek past the tag. */
}
pInit->runningFilePos += headerSize;
} else {
break;
}
}
if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') {
return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#ifndef DR_FLAC_NO_OGG
if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') {
return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#endif
/* If we get here it means we likely don't have a header. Try opening in relaxed mode, if applicable. */
if (relaxed) {
if (container == drflac_container_native) {
return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#ifndef DR_FLAC_NO_OGG
if (container == drflac_container_ogg) {
return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#endif
}
/* Unsupported container. */
return DRFLAC_FALSE;
}
static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
{
DRFLAC_ASSERT(pFlac != NULL);
DRFLAC_ASSERT(pInit != NULL);
DRFLAC_ZERO_MEMORY(pFlac, sizeof(*pFlac));
pFlac->bs = pInit->bs;
pFlac->onMeta = pInit->onMeta;
pFlac->pUserDataMD = pInit->pUserDataMD;
pFlac->maxBlockSizeInPCMFrames = pInit->maxBlockSizeInPCMFrames;
pFlac->sampleRate = pInit->sampleRate;
pFlac->channels = (drflac_uint8)pInit->channels;
pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample;
pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
pFlac->container = pInit->container;
}
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)
{
drflac_init_info init;
drflac_uint32 allocationSize;
drflac_uint32 wholeSIMDVectorCountPerChannel;
drflac_uint32 decodedSamplesAllocationSize;
#ifndef DR_FLAC_NO_OGG
drflac_oggbs oggbs;
#endif
drflac_uint64 firstFramePos;
drflac_uint64 seektablePos;
drflac_uint32 seektableSize;
drflac_allocation_callbacks allocationCallbacks;
drflac* pFlac;
/* CPU support first. */
drflac__init_cpu_caps();
if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
return NULL;
}
if (pAllocationCallbacks != NULL) {
allocationCallbacks = *pAllocationCallbacks;
if (allocationCallbacks.onFree == NULL || (allocationCallbacks.onMalloc == NULL && allocationCallbacks.onRealloc == NULL)) {
return NULL; /* Invalid allocation callbacks. */
}
} else {
allocationCallbacks.pUserData = NULL;
allocationCallbacks.onMalloc = drflac__malloc_default;
allocationCallbacks.onRealloc = drflac__realloc_default;
allocationCallbacks.onFree = drflac__free_default;
}
/*
The size of the allocation for the drflac object needs to be large enough to fit the following:
1) The main members of the drflac structure
2) A block of memory large enough to store the decoded samples of the largest frame in the stream
3) If the container is Ogg, a drflac_oggbs object
The complicated part of the allocation is making sure there's enough room the decoded samples, taking into consideration
the different SIMD instruction sets.
*/
allocationSize = sizeof(drflac);
/*
The allocation size for decoded frames depends on the number of 32-bit integers that fit inside the largest SIMD vector
we are supporting.
*/
if ((init.maxBlockSizeInPCMFrames % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) {
wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32)));
} else {
wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1;
}
decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels;
allocationSize += decodedSamplesAllocationSize;
allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE; /* Allocate extra bytes to ensure we have enough for alignment. */
#ifndef DR_FLAC_NO_OGG
/* There's additional data required for Ogg streams. */
if (init.container == drflac_container_ogg) {
allocationSize += sizeof(drflac_oggbs);
}
DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
if (init.container == drflac_container_ogg) {
oggbs.onRead = onRead;
oggbs.onSeek = onSeek;
oggbs.pUserData = pUserData;
oggbs.currentBytePos = init.oggFirstBytePos;
oggbs.firstBytePos = init.oggFirstBytePos;
oggbs.serialNumber = init.oggSerial;
oggbs.bosPageHeader = init.oggBosHeader;
oggbs.bytesRemainingInPage = 0;
}
#endif
/*
This part is a bit awkward. We need to load the seektable so that it can be referenced in-memory, but I want the drflac object to
consist of only a single heap allocation. To this, the size of the seek table needs to be known, which we determine when reading
and decoding the metadata.
*/
firstFramePos = 42; /* <-- We know we are at byte 42 at this point. */
seektablePos = 0;
seektableSize = 0;
if (init.hasMetadataBlocks) {
drflac_read_proc onReadOverride = onRead;
drflac_seek_proc onSeekOverride = onSeek;
void* pUserDataOverride = pUserData;
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
onReadOverride = drflac__on_read_ogg;
onSeekOverride = drflac__on_seek_ogg;
pUserDataOverride = (void*)&oggbs;
}
#endif
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
return NULL;
}
allocationSize += seektableSize;
}
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
drflac__init_from_info(pFlac, &init);
pFlac->allocationCallbacks = allocationCallbacks;
pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE);
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
DRFLAC_COPY_MEMORY(pInternalOggbs, &oggbs, sizeof(oggbs));
/* 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.pUserData = (void*)pInternalOggbs;
pFlac->_oggbs = (void*)pInternalOggbs;
}
#endif
pFlac->firstFLACFramePosInBytes = firstFramePos;
/* NOTE: Seektables are not currently compatible with Ogg encapsulation (Ogg has its own accelerated seeking system). I may change this later, so I'm leaving this here for now. */
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg)
{
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
else
#endif
{
/* If we have a seektable we need to load it now, making sure we move back to where we were previously. */
if (seektablePos != 0) {
pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
/* Seek to the seektable, then just read directly into our seektable buffer. */
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
/* Endian swap. */
drflac_uint32 iSeekpoint;
for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
}
} else {
/* Failed to read the seektable. Pretend we don't have one. */
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
/* 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)) {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
} else {
/* Failed to seek to the seektable. Ominous sign, but for now we can just pretend we don't have one. */
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
}
}
/*
If we get here, but don't have a STREAMINFO block, it means we've opened the stream in relaxed mode and need to decode
the first frame.
*/
if (!init.hasStreamInfoBlock) {
pFlac->currentFLACFrame.header = init.firstFrameHeader;
for (;;) {
drflac_result result = drflac__decode_flac_frame(pFlac);
if (result == DRFLAC_SUCCESS) {
break;
} else {
if (result == DRFLAC_CRC_MISMATCH) {
if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
continue;
} else {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
}
}
}
return pFlac;
}
#ifndef DR_FLAC_NO_STDIO
#include <stdio.h>
#include <wchar.h> /* For wcslen(), wcsrtombs() */
/* drflac_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
#include <errno.h>
static drflac_result drflac_result_from_errno(int e)
{
switch (e)
{
case 0: return DRFLAC_SUCCESS;
#ifdef EPERM
case EPERM: return DRFLAC_INVALID_OPERATION;
#endif
#ifdef ENOENT
case ENOENT: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef ESRCH
case ESRCH: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef EINTR
case EINTR: return DRFLAC_INTERRUPT;
#endif
#ifdef EIO
case EIO: return DRFLAC_IO_ERROR;
#endif
#ifdef ENXIO
case ENXIO: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef E2BIG
case E2BIG: return DRFLAC_INVALID_ARGS;
#endif
#ifdef ENOEXEC
case ENOEXEC: return DRFLAC_INVALID_FILE;
#endif
#ifdef EBADF
case EBADF: return DRFLAC_INVALID_FILE;
#endif
#ifdef ECHILD
case ECHILD: return DRFLAC_ERROR;
#endif
#ifdef EAGAIN
case EAGAIN: return DRFLAC_UNAVAILABLE;
#endif
#ifdef ENOMEM
case ENOMEM: return DRFLAC_OUT_OF_MEMORY;
#endif
#ifdef EACCES
case EACCES: return DRFLAC_ACCESS_DENIED;
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
static drflac_result drflac_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err;
#endif
if (ppFile != NULL) {
*ppFile = NULL; /* Safety. */
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRFLAC_INVALID_ARGS;
}
#if defined(_MSC_VER) && _MSC_VER >= 1400
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drflac_result_from_errno(err);
}
#else
#if defined(_WIN32) || defined(__APPLE__)
*ppFile = fopen(pFilePath, pOpenMode);
#else
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
*ppFile = fopen64(pFilePath, pOpenMode);
#else
*ppFile = fopen(pFilePath, pOpenMode);
#endif
#endif
if (*ppFile == NULL) {
drflac_result result = drflac_result_from_errno(errno);
if (result == DRFLAC_SUCCESS) {
result = DRFLAC_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
}
return result;
}
#endif
return DRFLAC_SUCCESS;
}
/*
_wfopen() isn't always available in all compilation environments.
* Windows only.
* MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
* MinGW-64 (both 32- and 64-bit) seems to support it.
* MinGW wraps it in !defined(__STRICT_ANSI__).
* OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
*/
#if defined(_WIN32)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define DRFLAC_HAS_WFOPEN
#endif
#endif
static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
*ppFile = NULL; /* Safety. */
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRFLAC_INVALID_ARGS;
}
#if defined(DRFLAC_HAS_WFOPEN)
{
/* Use _wfopen() on Windows. */
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drflac_result_from_errno(err);
}
#else
*ppFile = _wfopen(pFilePath, pOpenMode);
if (*ppFile == NULL) {
return drflac_result_from_errno(errno);
}
#endif
(void)pAllocationCallbacks;
}
#else
/*
Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
*/
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
char pOpenModeMB[32] = {0};
/* Get the length first. */
DRFLAC_ZERO_OBJECT(&mbs);
lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
if (lenMB == (size_t)-1) {
return drflac_result_from_errno(errno);
}
pFilePathMB = (char*)drflac__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
if (pFilePathMB == NULL) {
return DRFLAC_OUT_OF_MEMORY;
}
pFilePathTemp = pFilePath;
DRFLAC_ZERO_OBJECT(&mbs);
wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
/* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
{
size_t i = 0;
for (;;) {
if (pOpenMode[i] == 0) {
pOpenModeMB[i] = '\0';
break;
}
pOpenModeMB[i] = (char)pOpenMode[i];
i += 1;
}
}
*ppFile = fopen(pFilePathMB, pOpenModeMB);
drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
if (*ppFile == NULL) {
return DRFLAC_ERROR;
}
#endif
return DRFLAC_SUCCESS;
}
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
{
return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
}
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
{
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
}
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
}
return pFlac;
}
#endif /* DR_FLAC_NO_STDIO */
static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
{
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
size_t bytesRemaining;
DRFLAC_ASSERT(memoryStream != NULL);
DRFLAC_ASSERT(memoryStream->dataSize >= memoryStream->currentReadPos);
bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos;
if (bytesToRead > bytesRemaining) {
bytesToRead = bytesRemaining;
}
if (bytesToRead > 0) {
DRFLAC_COPY_MEMORY(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead);
memoryStream->currentReadPos += bytesToRead;
}
return bytesToRead;
}
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
{
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
DRFLAC_ASSERT(memoryStream != NULL);
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
if (offset > (drflac_int64)memoryStream->dataSize) {
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. */
}
}
return DRFLAC_TRUE;
}
DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac__memory_stream memoryStream;
drflac* pFlac;
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);
if (pFlac == NULL) {
return NULL;
}
pFlac->memoryStream = memoryStream;
/* This is an awful hack... */
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg)
{
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
oggbs->pUserData = &pFlac->memoryStream;
}
else
#endif
{
pFlac->bs.pUserData = &pFlac->memoryStream;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac__memory_stream memoryStream;
drflac* pFlac;
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);
if (pFlac == NULL) {
return NULL;
}
pFlac->memoryStream = memoryStream;
/* This is an awful hack... */
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg)
{
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
oggbs->pUserData = &pFlac->memoryStream;
}
else
#endif
{
pFlac->bs.pUserData = &pFlac->memoryStream;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
return drflac_open_with_metadata_private(onRead, onSeek, 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)
{
return drflac_open_with_metadata_private(onRead, onSeek, 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)
{
return drflac_open_with_metadata_private(onRead, onSeek, 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)
{
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
}
DRFLAC_API void drflac_close(drflac* pFlac)
{
if (pFlac == NULL) {
return;
}
#ifndef DR_FLAC_NO_STDIO
/*
If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file()
was used by looking at the callbacks.
*/
if (pFlac->bs.onRead == drflac__on_read_stdio) {
fclose((FILE*)pFlac->bs.pUserData);
}
#ifndef DR_FLAC_NO_OGG
/* Need to clean up Ogg streams a bit differently due to the way the bit streaming is chained. */
if (pFlac->container == drflac_container_ogg) {
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
DRFLAC_ASSERT(pFlac->bs.onRead == drflac__on_read_ogg);
if (oggbs->onRead == drflac__on_read_stdio) {
fclose((FILE*)oggbs->pUserData);
}
}
#endif
#endif
drflac__free_from_callbacks(pFlac, &pFlac->allocationCallbacks);
}
#if 0
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutpu...
{
drflac_uint64 i;
for (i = 0; i < frameCount; ++i) {
drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
drflac_uint32 right = left - side;
pOutputSamples[i*2+0] = (drflac_int32)left;
pOutputSamples[i*2+1] = (drflac_int32)right;
}
}
#endif
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSa...
{
drflac_uint64 i;
drflac_uint64 frameCount4 = frameCount >> 2;
const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
for (i = 0; i < frameCount4; ++i) {
drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
drflac_uint32 right0 = left0 - side0;
drflac_uint32 right1 = left1 - side1;
drflac_uint32 right2 = left2 - side2;
drflac_uint32 right3 = left3 - side3;
pOutputSamples[i*8+0] = (drflac_int32)left0;
pOutputSamples[i*8+1] = (drflac_int32)right0;
pOutputSamples[i*8+2] = (drflac_int32)left1;
pOutputSamples[i*8+3] = (drflac_int32)right1;
pOutputSamples[i*8+4] = (drflac_int32)left2;
pOutputSamples[i*8+5] = (drflac_int32)right2;
pOutputSamples[i*8+6] = (drflac_int32)left3;
pOutputSamples[i*8+7] = (drflac_int32)right3;
}
for (i = (frameCount4 << 2); i < frameCount; ++i) {
drflac_uint32 left = pInputSamples0U32[i] << shift0;
drflac_uint32 side = pInputSamples1U32[i] << shift1;
drflac_uint32 right = left - side;
pOutputSamples[i*2+0] = (drflac_int32)left;
pOutputSamples[i*2+1] = (drflac_int32)right;
share/public_html/static/music_worklet_inprogress/decoder/deps/dr_libs/dr_flac.h view on Meta::CPAN
}
#if !defined(DR_FLAC_NO_CRC)
/* Fall back to binary search if seek table seeking fails. This requires the length of the stream to be known. */
if (!wasSuccessful && !pFlac->_noBinarySearchSeek && pFlac->totalPCMFrameCount > 0) {
wasSuccessful = drflac__seek_to_pcm_frame__binary_search(pFlac, pcmFrameIndex);
}
#endif
/* Fall back to brute force if all else fails. */
if (!wasSuccessful && !pFlac->_noBruteForceSeek) {
wasSuccessful = drflac__seek_to_pcm_frame__brute_force(pFlac, pcmFrameIndex);
}
}
if (wasSuccessful) {
pFlac->currentPCMFrame = pcmFrameIndex;
} else {
/* Seek failed. Try putting the decoder back to it's original state. */
if (drflac_seek_to_pcm_frame(pFlac, originalPCMFrame) == DRFLAC_FALSE) {
/* Failed to seek back to the original PCM frame. Fall back to 0. */
drflac_seek_to_pcm_frame(pFlac, 0);
}
}
return wasSuccessful;
}
}
/* High Level APIs */
#if defined(SIZE_MAX)
#define DRFLAC_SIZE_MAX SIZE_MAX
#else
#if defined(DRFLAC_64BIT)
#define DRFLAC_SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF)
#else
#define DRFLAC_SIZE_MAX 0xFFFFFFFF
#endif
#endif
/* Using a macro as the definition of the drflac__full_decode_and_close_*() API family. Sue me. */
#define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type) \
static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut)\
{ \
type* pSampleData = NULL; \
drflac_uint64 totalPCMFrameCount; \
\
DRFLAC_ASSERT(pFlac != NULL); \
\
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
\
if (totalPCMFrameCount == 0) { \
type buffer[4096]; \
drflac_uint64 pcmFramesRead; \
size_t sampleDataBufferSize = sizeof(buffer); \
\
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
if (pSampleData == NULL) { \
goto on_error; \
} \
\
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
type* pNewSampleData; \
size_t newSampleDataBufferSize; \
\
newSampleDataBufferSize = sampleDataBufferSize * 2; \
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
if (pNewSampleData == NULL) { \
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
goto on_error; \
} \
\
sampleDataBufferSize = newSampleDataBufferSize; \
pSampleData = pNewSampleData; \
} \
\
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
totalPCMFrameCount += pcmFramesRead; \
} \
\
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
protect those ears from random noise! */ \
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
} else { \
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
goto on_error; /* The decoded data is too big. */ \
} \
\
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \
if (pSampleData == NULL) { \
goto on_error; \
} \
\
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
} \
\
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
if (channelsOut) *channelsOut = pFlac->channels; \
if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
\
drflac_close(pFlac); \
return pSampleData; \
\
on_error: \
drflac_close(pFlac); \
return NULL; \
}
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_call...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
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_call...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
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* ...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
#ifndef DR_FLAC_NO_STDIO
DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
#endif
DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
drflac__free_from_callbacks(p, pAllocationCallbacks);
} else {
drflac__free_default(p, NULL);
}
}
DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments)
{
if (pIter == NULL) {
return;
}
pIter->countRemaining = commentCount;
pIter->pRunningData = (const char*)pComments;
}
DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut)
{
drflac_int32 length;
const char* pComment;
/* Safety. */
if (pCommentLengthOut) {
*pCommentLengthOut = 0;
}
if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
return NULL;
}
length = drflac__le2host_32_ptr_unaligned(pIter->pRunningData);
pIter->pRunningData += 4;
pComment = pIter->pRunningData;
pIter->pRunningData += length;
pIter->countRemaining -= 1;
if (pCommentLengthOut) {
*pCommentLengthOut = length;
}
return pComment;
}
DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData)
{
if (pIter == NULL) {
return;
}
pIter->countRemaining = trackCount;
pIter->pRunningData = (const char*)pTrackData;
}
DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack)