dependencies/SDL_sound/dr_flac.h in gosu-1.4.5.pre1 vs dependencies/SDL_sound/dr_flac.h in gosu-1.4.5
- old
+ new
@@ -1,8 +1,8 @@
/*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_flac - v0.12.37 - 2022-02-12
+dr_flac - v0.12.39 - 2022-09-17
David Reid - mackron@gmail.com
GitHub: https://github.com/mackron/dr_libs
*/
@@ -208,12 +208,15 @@
be used if available. Otherwise the seek will be performed using brute force.
#define DR_FLAC_NO_SIMD
Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.
+#define DR_FLAC_NO_WCHAR
+ Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_FLAC_NO_STDIO is also defined.
+
Notes
=====
- dr_flac does not support changing the sample rate nor channel count mid stream.
- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
- When using Ogg encapsulation, a corrupted metadata block will result in `drflac_open_with_metadata()` and `drflac_open()` returning inconsistent samples due
@@ -230,11 +233,11 @@
#define DRFLAC_STRINGIFY(x) #x
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
#define DRFLAC_VERSION_MAJOR 0
#define DRFLAC_VERSION_MINOR 12
-#define DRFLAC_VERSION_REVISION 37
+#define DRFLAC_VERSION_REVISION 39
#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. */
/* Sized types. */
@@ -381,19 +384,17 @@
{
drflac_seek_origin_start,
drflac_seek_origin_current
} drflac_seek_origin;
-/* Packing is important on this structure because we map this directly to the raw data within the SEEKTABLE metadata block. */
-#pragma pack(2)
+/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
typedef struct
{
drflac_uint64 firstPCMFrame;
drflac_uint64 flacFrameOffset; /* The offset from the first byte of the header of the first frame. */
drflac_uint16 pcmFrameCount;
} drflac_seekpoint;
-#pragma pack()
typedef struct
{
drflac_uint16 minBlockSizeInPCMFrames;
drflac_uint16 maxBlockSizeInPCMFrames;
@@ -1278,19 +1279,17 @@
{
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)
+/* The order of members here is important because we map this directly to the raw data within the CUESHEET metadata block. */
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;
@@ -1361,14 +1360,20 @@
case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
I am using "__inline__" only when we're compiling in strict ANSI mode.
*/
#if defined(__STRICT_ANSI__)
- #define DRFLAC_INLINE __inline__ __attribute__((always_inline))
+ #define DRFLAC_GNUC_INLINE_HINT __inline__
#else
- #define DRFLAC_INLINE inline __attribute__((always_inline))
+ #define DRFLAC_GNUC_INLINE_HINT inline
#endif
+
+ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+ #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT __attribute__((always_inline))
+ #else
+ #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT
+ #endif
#elif defined(__WATCOMC__)
#define DRFLAC_INLINE __inline
#else
#define DRFLAC_INLINE
#endif
@@ -1507,13 +1512,11 @@
static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
{
#if defined(DRFLAC_SUPPORT_SSE41)
#if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
- #if defined(DRFLAC_X64)
- return DRFLAC_TRUE; /* 64-bit targets always support SSE4.1. */
- #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE4_1__)
+ #if defined(__SSE4_1__) || defined(__AVX__)
return DRFLAC_TRUE; /* If the compiler is allowed to freely generate SSE41 code we can assume support. */
#else
#if defined(DRFLAC_NO_CPUID)
return DRFLAC_FALSE;
#else
@@ -1574,22 +1577,25 @@
extern __inline drflac_uint16 _watcom_bswap16(drflac_uint16);
extern __inline drflac_uint32 _watcom_bswap32(drflac_uint32);
extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
#pragma aux _watcom_bswap16 = \
"xchg al, ah" \
- parm [ax] \
- modify [ax];
+ parm [ax] \
+ value [ax] \
+ modify nomemory;
#pragma aux _watcom_bswap32 = \
- "bswap eax" \
- parm [eax] \
- modify [eax];
+ "bswap eax" \
+ parm [eax] \
+ value [eax] \
+ modify nomemory;
#pragma aux _watcom_bswap64 = \
"bswap eax" \
"bswap edx" \
"xchg eax,edx" \
parm [eax edx] \
- modify [eax edx];
+ value [eax edx] \
+ modify nomemory;
#endif
/* Standard library stuff. */
#ifndef DRFLAC_ASSERT
@@ -1686,10 +1692,14 @@
#define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0
#define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8
#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9
#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10
+#define DRFLAC_SEEKPOINT_SIZE_IN_BYTES 18
+#define DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES 36
+#define DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES 12
+
#define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision)
{
@@ -2688,10 +2698,14 @@
#define DRFLAC_IMPLEMENT_CLZ_MSVC
#endif
#if defined(__WATCOMC__) && defined(__386__)
#define DRFLAC_IMPLEMENT_CLZ_WATCOM
#endif
+#ifdef __MRC__
+#include <intrinsics.h>
+#define DRFLAC_IMPLEMENT_CLZ_MRC
+#endif
static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x)
{
drflac_uint32 n;
static drflac_uint32 clz_table_4[] = {
@@ -2728,10 +2742,12 @@
static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported(void)
{
/* Fast compile time check for ARM. */
#if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
return DRFLAC_TRUE;
+#elif defined(__MRC__)
+ return DRFLAC_TRUE;
#else
/* If the compiler itself does not support the intrinsic then we'll need to return false. */
#ifdef DRFLAC_HAS_LZCNT_INTRINSIC
return drflac__gIsLZCNTSupported;
#else
@@ -2837,17 +2853,27 @@
}
#endif
#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
+#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT
+/* Use the LZCNT instruction (only available on some processors since the 2010s). */
+#pragma aux drflac__clz_watcom_lzcnt = \
+ "db 0F3h, 0Fh, 0BDh, 0C0h" /* lzcnt eax, eax */ \
+ parm [eax] \
+ value [eax] \
+ modify nomemory;
+#else
+/* Use the 386+-compatible implementation. */
#pragma aux drflac__clz_watcom = \
"bsr eax, eax" \
"xor eax, 31" \
parm [eax] nomemory \
value [eax] \
modify exact [eax] nomemory;
#endif
+#endif
static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
{
#ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
if (drflac__is_lzcnt_supported()) {
@@ -2855,12 +2881,16 @@
} else
#endif
{
#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
return drflac__clz_msvc(x);
+#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT)
+ return drflac__clz_watcom_lzcnt(x);
#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
+#elif defined(__MRC__)
+ return __cntlzw(x);
#else
return drflac__clz_software(x);
#endif
}
}
@@ -4418,11 +4448,11 @@
int32x2_t shift64;
uint32x4_t one128;
const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
- riceParamMask = ~((~0UL) << riceParam);
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
riceParamMask128 = vdupq_n_u32(riceParamMask);
riceParam128 = vdupq_n_s32(riceParam);
shift64 = vdup_n_s32(-shift); /* Negate the shift because we'll be doing a variable shift using vshlq_s32(). */
one128 = vdupq_n_u32(1);
@@ -4604,14 +4634,17 @@
int32x4_t samples128_8;
uint32x4_t riceParamMask128;
int32x4_t riceParam128;
int64x1_t shift64;
uint32x4_t one128;
+ int64x2_t prediction128 = { 0 };
+ uint32x4_t zeroCountPart128;
+ uint32x4_t riceParamPart128;
const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
- riceParamMask = ~((~0UL) << riceParam);
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
riceParamMask128 = vdupq_n_u32(riceParamMask);
riceParam128 = vdupq_n_s32(riceParam);
shift64 = vdup_n_s64(-shift); /* Negate the shift because we'll be doing a variable shift using vshlq_s32(). */
one128 = vdupq_n_u32(1);
@@ -4684,14 +4717,10 @@
coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
}
/* For this version we are doing one sample at a time. */
while (pDecodedSamples < pDecodedSamplesEnd) {
- int64x2_t prediction128;
- uint32x4_t zeroCountPart128;
- uint32x4_t riceParamPart128;
-
if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
return DRFLAC_FALSE;
@@ -6435,11 +6464,11 @@
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* pSeektableSize, drflac_allocation_callbacks* pAllocationCallbacks)
+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)
{
/*
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.
*/
@@ -6495,36 +6524,41 @@
{
seektablePos = runningFilePos;
seektableSize = blockSize;
if (onMeta) {
+ drflac_uint32 seekpointCount;
drflac_uint32 iSeekpoint;
void* pRawData;
- pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ seekpointCount = blockSize/DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+
+ pRawData = drflac__malloc_from_callbacks(seekpointCount * sizeof(drflac_seekpoint), pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
- if (onRead(pUserData, pRawData, blockSize) != blockSize) {
- drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
- return DRFLAC_FALSE;
- }
+ /* We need to read seekpoint by seekpoint and do some processing. */
+ for (iSeekpoint = 0; iSeekpoint < seekpointCount; ++iSeekpoint) {
+ drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
- metadata.pRawData = pRawData;
- metadata.rawDataSize = blockSize;
- metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
- metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
+ if (onRead(pUserData, pSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) != DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
- /* Endian swap. */
- for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
- drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
+ /* Endian swap. */
pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
}
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+ metadata.data.seektable.seekpointCount = seekpointCount;
+ metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
+
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
@@ -6605,13 +6639,19 @@
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
+ size_t bufferSize;
drflac_uint8 iTrack;
drflac_uint8 iIndex;
+ void* pTrackData;
+ /*
+ This needs to be loaded in two passes. The first pass is used to calculate the size of the memory allocation
+ we need for storing the necessary data. The second pass will fill that buffer with usable data.
+ */
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
@@ -6628,42 +6668,95 @@
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;
+ metadata.data.cuesheet.pTrackData = NULL; /* Will be filled later. */
- /* 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;
+ /* Pass 1: Calculate the size of the buffer for the track data. */
+ {
+ const char* pRunningDataSaved = pRunningData; /* Will be restored at the end in preparation for the second pass. */
- if (pRunningDataEnd - pRunningData < 36) {
- drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
- return DRFLAC_FALSE;
+ bufferSize = metadata.data.cuesheet.trackCount * DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES;
+
+ for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+ drflac_uint8 indexCount;
+ drflac_uint32 indexPointSize;
+
+ if (pRunningDataEnd - pRunningData < DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ /* Skip to the index point count */
+ pRunningData += 35;
+
+ indexCount = pRunningData[0];
+ pRunningData += 1;
+
+ bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
+
+ /* Quick validation check. */
+ indexPointSize = indexCount * DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+ if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ pRunningData += indexPointSize;
}
- /* 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) {
+ pRunningData = pRunningDataSaved;
+ }
+
+ /* Pass 2: Allocate a buffer and fill the data. Validation was done in the step above so can be skipped. */
+ {
+ char* pRunningTrackData;
+
+ pTrackData = drflac__malloc_from_callbacks(bufferSize, pAllocationCallbacks);
+ if (pTrackData == NULL) {
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);
+ pRunningTrackData = (char*)pTrackData;
+
+ for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+ drflac_uint8 indexCount;
+
+ DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES);
+ pRunningData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1; /* Skip forward, but not beyond the last byte in the CUESHEET_TRACK block which is the index count. */
+ pRunningTrackData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1;
+
+ /* Grab the index count for the next part. */
+ indexCount = pRunningData[0];
+ pRunningData += 1;
+ pRunningTrackData += 1;
+
+ /* Extract each track index. */
+ for (iIndex = 0; iIndex < indexCount; ++iIndex) {
+ drflac_cuesheet_track_index* pTrackIndex = (drflac_cuesheet_track_index*)pRunningTrackData;
+
+ DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES);
+ pRunningData += DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+ pRunningTrackData += sizeof(drflac_cuesheet_track_index);
+
+ pTrackIndex->offset = drflac__be2host_64(pTrackIndex->offset);
+ }
}
+
+ metadata.data.cuesheet.pTrackData = pTrackData;
}
+ /* The original data is no longer needed. */
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ pRawData = NULL;
+
onMeta(pUserDataMD, &metadata);
- drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ drflac__free_from_callbacks(pTrackData, pAllocationCallbacks);
+ pTrackData = NULL;
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
{
@@ -6698,19 +6791,19 @@
/* 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.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.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;
@@ -6789,13 +6882,13 @@
if (isLastBlock) {
break;
}
}
- *pSeektablePos = seektablePos;
- *pSeektableSize = seektableSize;
- *pFirstFramePos = runningFilePos;
+ *pSeektablePos = seektablePos;
+ *pSeekpointCount = seektableSize / DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+ *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)
@@ -7821,15 +7914,15 @@
drflac_init_info init;
drflac_uint32 allocationSize;
drflac_uint32 wholeSIMDVectorCountPerChannel;
drflac_uint32 decodedSamplesAllocationSize;
#ifndef DR_FLAC_NO_OGG
- drflac_oggbs oggbs;
+ drflac_oggbs* pOggbs = NULL;
#endif
drflac_uint64 firstFramePos;
drflac_uint64 seektablePos;
- drflac_uint32 seektableSize;
+ drflac_uint32 seekpointCount;
drflac_allocation_callbacks allocationCallbacks;
drflac* pFlac;
/* CPU support first. */
drflac__init_cpu_caps();
@@ -7879,68 +7972,81 @@
#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;
+ pOggbs = (drflac_oggbs*)drflac__malloc_from_callbacks(sizeof(*pOggbs), &allocationCallbacks);
+ if (pOggbs == NULL) {
+ return NULL; /*DRFLAC_OUT_OF_MEMORY;*/
+ }
+
+ DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
+ pOggbs->onRead = onRead;
+ pOggbs->onSeek = onSeek;
+ pOggbs->pUserData = pUserData;
+ pOggbs->currentBytePos = init.oggFirstBytePos;
+ pOggbs->firstBytePos = init.oggFirstBytePos;
+ pOggbs->serialNumber = init.oggSerial;
+ pOggbs->bosPageHeader = init.oggBosHeader;
+ pOggbs->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;
+ firstFramePos = 42; /* <-- We know we are at byte 42 at this point. */
+ seektablePos = 0;
+ seekpointCount = 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;
+ pUserDataOverride = (void*)pOggbs;
}
#endif
- if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
+ if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
+ #ifndef DR_FLAC_NO_OGG
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ #endif
return NULL;
}
- allocationSize += seektableSize;
+ allocationSize += seekpointCount * sizeof(drflac_seekpoint);
}
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) {
+ #ifndef DR_FLAC_NO_OGG
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ #endif
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);
- *pInternalOggbs = oggbs;
+ drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + (seekpointCount * sizeof(drflac_seekpoint)));
+ DRFLAC_COPY_MEMORY(pInternalOggbs, pOggbs, sizeof(*pOggbs));
+ /* At this point the pOggbs object has been handed over to pInternalOggbs and can be freed. */
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ pOggbs = NULL;
+
/* 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;
@@ -7959,30 +8065,32 @@
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->seekpointCount = seekpointCount;
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) {
+ drflac_uint32 iSeekpoint;
+
+ for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
+ if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) == DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+ /* Endian swap. */
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;
+ break;
}
- } 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);
@@ -8027,11 +8135,13 @@
#ifndef DR_FLAC_NO_STDIO
#include <stdio.h>
+#ifndef DR_FLAC_NO_WCHAR
#include <wchar.h> /* For wcslen(), wcsrtombs() */
+#endif
/* 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)
{
@@ -8493,10 +8603,11 @@
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define DRFLAC_HAS_WFOPEN
#endif
#endif
+#ifndef DR_FLAC_NO_WCHAR
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. */
}
@@ -8521,14 +8632,27 @@
#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.
+ 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.
*/
+
+ /*
+ Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+ need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+ and submit a bug report and it'll be added to the library upstream.
+ */
+ #if defined(__DJGPP__)
+ {
+ /* Nothing to do here. This will fall through to the error check below. */
+ }
+ #else
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
@@ -8566,18 +8690,20 @@
*ppFile = fopen(pFilePathMB, pOpenModeMB);
drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
+ #endif
if (*ppFile == NULL) {
return DRFLAC_ERROR;
}
#endif
return DRFLAC_SUCCESS;
}
+#endif
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
{
return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
}
@@ -8606,10 +8732,11 @@
}
return pFlac;
}
+#ifndef DR_FLAC_NO_WCHAR
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
@@ -8623,10 +8750,11 @@
return NULL;
}
return pFlac;
}
+#endif
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;
@@ -8642,10 +8770,11 @@
}
return pFlac;
}
+#ifndef DR_FLAC_NO_WCHAR
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;
@@ -8659,10 +8788,11 @@
return pFlac;
}
return pFlac;
}
+#endif
#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;
@@ -11926,9 +12056,21 @@
/*
REVISION HISTORY
================
+v0.12.39 - 2022-09-17
+ - Fix compilation with DJGPP.
+ - Fix compilation error with Visual Studio 2019 and the ARM build.
+ - Fix an error with SSE 4.1 detection.
+ - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
+ - Improve compatibility with compilers which lack support for explicit struct packing.
+ - Improve compatibility with low-end and embedded hardware by reducing the amount of stack
+ allocation when loading an Ogg encapsulated file.
+
+v0.12.38 - 2022-04-10
+ - Fix compilation error on older versions of GCC.
+
v0.12.37 - 2022-02-12
- Improve ARM detection.
v0.12.36 - 2022-02-07
- Fix a compilation error with the ARM build.