14 Commits

Author SHA1 Message Date
David Reid 09615e6bc1 Update c89atomic. 2026-04-26 18:56:05 +10:00
David Reid 12a83fcf54 Update dr_wav. 2026-04-26 11:55:12 +10:00
David Reid 2986173662 Emscripten: Fix an error with ALLOW_MEMORY_GROWTH.
Public issue https://github.com/mackron/miniaudio/issues/1114
2026-04-26 08:32:28 +10:00
Echo J dcfc24c100 Emscripten: Cast pointer arguments to pointer-sized integers
For some reason, 64-bit pointer arguments are casted to Numbers
in Emscripten's type handling (which causes conversion errors when
passing them back to native code)
2026-04-26 08:11:16 +10:00
David Reid 7533c9d341 Update build instructions for Emscripten test. 2026-04-26 08:10:43 +10:00
Yuri Khrustalev 56ffd77769 Make ma_android_sdk_version static to fix -Wmissing-prototypes. 2026-04-26 07:22:41 +10:00
amaldika 55f16e62f6 Support to build for arm64EC configuration on MSVC. 2026-04-26 07:21:35 +10:00
David Reid 1df46ae9a0 Update dr_libs. 2026-04-26 07:08:13 +10:00
David Reid 12bacf1186 Revert "Enforce a read callback to be specified for decoders."
This reverts commit 52d09d3688.
2026-03-13 11:22:40 +10:00
David Reid 117366df9a Fix an incorrect check for the decoding seek callback. 2026-03-12 06:24:04 +10:00
David Reid 0041150de0 Update change history. 2026-03-12 06:16:57 +10:00
David Reid 52d09d3688 Enforce a read callback to be specified for decoders. 2026-03-12 06:15:27 +10:00
David Reid 6922366bb1 Don't crash when a decoding seek callback is unavailable. 2026-03-12 06:14:00 +10:00
David Reid 4c082afe71 Clarify usage of the decoder read callback. 2026-03-12 06:08:27 +10:00
3 changed files with 252 additions and 57 deletions
+5
View File
@@ -1,3 +1,8 @@
v0.11.26 - TBD
=====================
* Fixed a crash when passing in null for the read or seek callbacks for a decoder.
v0.11.25 - 2026-03-04 v0.11.25 - 2026-03-04
===================== =====================
* Bug fixes to the WAV decoder. * Bug fixes to the WAV decoder.
+245 -55
View File
@@ -1,6 +1,6 @@
/* /*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.25 - 2026-03-04 miniaudio - v0.11.26 - TBD
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@@ -3747,7 +3747,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0 #define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11 #define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 25 #define MA_VERSION_REVISION 26
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
@@ -3764,7 +3764,7 @@ extern "C" {
#endif #endif
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__) || defined(__ppc64__) #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__powerpc64__) || defined(__ppc64__)
#define MA_SIZEOF_PTR 8 #define MA_SIZEOF_PTR 8
#else #else
#define MA_SIZEOF_PTR 4 #define MA_SIZEOF_PTR 4
@@ -9974,7 +9974,19 @@ typedef struct
} ma_decoding_backend_vtable; } ma_decoding_backend_vtable;
typedef ma_result (* ma_decoder_read_proc)(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead); /* Returns the number of bytes read. */ /*
The read callback should return MA_SUCCESS if more than zero bytes were successfully read. If zero
bytes can be read because it reached the end of the file, return MA_AT_END. If any other error
occurs just return any other error code (it's fine to just generically return MA_ERROR).
Return the actual number of bytes read in `pBytesRead`. Important note: if the number of bytes
actually read is less than the number of bytes requested (bytesToRead), miniaudio will treat it as
if the end of the file has been reached and it will stop decoding. This becomes relevant for things
like streaming data sources, such as internet streams. If you haven't yet received `bytesToRead`
from the network, you need to have your callback wait for it and then only return when the full
number of bytes can be output, or when you've reached the genuine end of the stream.
*/
typedef ma_result (* ma_decoder_read_proc)(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead);
typedef ma_result (* ma_decoder_seek_proc)(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin); typedef ma_result (* ma_decoder_seek_proc)(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin);
typedef ma_result (* ma_decoder_tell_proc)(ma_decoder* pDecoder, ma_int64* pCursor); typedef ma_result (* ma_decoder_tell_proc)(ma_decoder* pDecoder, ma_int64* pCursor);
@@ -11644,11 +11656,11 @@ IMPLEMENTATION
#if defined(__arm__) || defined(_M_ARM) #if defined(__arm__) || defined(_M_ARM)
#define MA_ARM32 #define MA_ARM32
#endif #endif
#if defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) #if defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define MA_ARM64 #define MA_ARM64
#endif #endif
#if defined(__x86_64__) || defined(_M_X64) #if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
#define MA_X64 #define MA_X64
#elif defined(__i386) || defined(_M_IX86) #elif defined(__i386) || defined(_M_IX86)
#define MA_X86 #define MA_X86
@@ -11703,7 +11715,7 @@ IMPLEMENTATION
#endif #endif
#if defined(MA_ARM) #if defined(MA_ARM)
#if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)) #if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
#define MA_SUPPORT_NEON #define MA_SUPPORT_NEON
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
@@ -12157,7 +12169,7 @@ static MA_INLINE void ma_restore_denormals(unsigned int prevState)
#ifdef MA_ANDROID #ifdef MA_ANDROID
#include <sys/system_properties.h> #include <sys/system_properties.h>
int ma_android_sdk_version() static int ma_android_sdk_version(void)
{ {
char sdkVersion[PROP_VALUE_MAX + 1] = {0, }; char sdkVersion[PROP_VALUE_MAX + 1] = {0, };
if (__system_property_get("ro.build.version.sdk", sdkVersion)) { if (__system_property_get("ro.build.version.sdk", sdkVersion)) {
@@ -14226,7 +14238,8 @@ typedef int ma_atomic_memory_order;
!defined(MA_ATOMIC_LEGACY_MSVC_ASM) && \ !defined(MA_ATOMIC_LEGACY_MSVC_ASM) && \
!defined(MA_ATOMIC_MODERN_GCC) && \ !defined(MA_ATOMIC_MODERN_GCC) && \
!defined(MA_ATOMIC_LEGACY_GCC) && \ !defined(MA_ATOMIC_LEGACY_GCC) && \
!defined(MA_ATOMIC_LEGACY_GCC_ASM) !defined(MA_ATOMIC_LEGACY_GCC_ASM) && \
!defined(MA_ATOMIC_CHIBICC)
#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__) || defined(__BORLANDC__)
#if (defined(_MSC_VER) && _MSC_VER > 1600) #if (defined(_MSC_VER) && _MSC_VER > 1600)
#define MA_ATOMIC_MODERN_MSVC #define MA_ATOMIC_MODERN_MSVC
@@ -14239,12 +14252,12 @@ typedef int ma_atomic_memory_order;
#endif #endif
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || defined(__clang__) #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || defined(__clang__)
#define MA_ATOMIC_MODERN_GCC #define MA_ATOMIC_MODERN_GCC
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)))
#define MA_ATOMIC_LEGACY_GCC
#elif defined(__chibicc__)
#define MA_ATOMIC_CHIBICC
#else #else
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) #define MA_ATOMIC_LEGACY_GCC_ASM
#define MA_ATOMIC_LEGACY_GCC
#else
#define MA_ATOMIC_LEGACY_GCC_ASM
#endif
#endif #endif
#endif #endif
#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC) #if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC)
@@ -14556,6 +14569,24 @@ typedef int ma_atomic_memory_order;
#endif #endif
} }
#endif #endif
#if defined(MA_ATOMIC_CHIBICC)
#define ma_atomic_memory_order_relaxed 0
#define ma_atomic_memory_order_consume 1
#define ma_atomic_memory_order_acquire 2
#define ma_atomic_memory_order_release 3
#define ma_atomic_memory_order_acq_rel 4
#define ma_atomic_memory_order_seq_cst 5
typedef ma_uint32 ma_atomic_flag;
#define ma_atomic_flag_test_and_set_explicit(dst, order) __builtin_atomic_exchange(dst, 1)
#define ma_atomic_flag_clear_explicit(dst, order) __builtin_atomic_exchange(dst, 0)
static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order)
{
ma_atomic_flag expected;
expected = 0;
__builtin_compare_and_swap(dst, &expected, 0);
return expected;
}
#endif
#define ma_atomic_flag_test_and_set(dst) ma_atomic_flag_test_and_set_explicit(dst, ma_atomic_memory_order_acquire) #define ma_atomic_flag_test_and_set(dst) ma_atomic_flag_test_and_set_explicit(dst, ma_atomic_memory_order_acquire)
#define ma_atomic_flag_clear(dst) ma_atomic_flag_clear_explicit(dst, ma_atomic_memory_order_release) #define ma_atomic_flag_clear(dst) ma_atomic_flag_clear_explicit(dst, ma_atomic_memory_order_release)
typedef ma_atomic_flag ma_atomic_spinlock; typedef ma_atomic_flag ma_atomic_spinlock;
@@ -16930,6 +16961,88 @@ ma_atomic_spinlock ma_atomic_global_lock;
#error Unsupported compiler. #error Unsupported compiler.
#endif #endif
#endif #endif
#if defined(MA_ATOMIC_CHIBICC)
#define MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE
static void ma_atomic_thread_fence(ma_atomic_memory_order order)
{
static ma_uint32 dummy;
__builtin_atomic_exchange(&dummy, 0);
(void)dummy;
}
#define ma_atomic_signal_fence(order) ma_atomic_thread_fence(order)
#define ma_atomic_is_lock_free_8(ptr) 1
#define ma_atomic_is_lock_free_16(ptr) 1
#define ma_atomic_is_lock_free_32(ptr) 1
#define ma_atomic_is_lock_free_64(ptr) 1
#define ma_atomic_store_explicit_8( dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_store_explicit_16(dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_store_explicit_32(dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_store_explicit_64(dst, src, order) __builtin_atomic_exchange(dst, src)
#define MA_ATOMIC_CHIBICC_LOAD(sizeInBits) \
static MA_INLINE ma_uint##sizeInBits ma_atomic_load_explicit_##sizeInBits(volatile ma_uint##sizeInBits* dst, ma_atomic_memory_order order) \
{ \
ma_uint##sizeInBits expected = 0; \
__builtin_compare_and_swap(dst, &expected, 0); \
return expected; \
}
MA_ATOMIC_CHIBICC_LOAD(8)
MA_ATOMIC_CHIBICC_LOAD(16)
MA_ATOMIC_CHIBICC_LOAD(32)
MA_ATOMIC_CHIBICC_LOAD(64)
#define ma_atomic_exchange_explicit_8( dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_exchange_explicit_16(dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_exchange_explicit_32(dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_exchange_explicit_64(dst, src, order) __builtin_atomic_exchange(dst, src)
#define ma_atomic_compare_exchange_strong_explicit_8( dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
#define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, successOrder, failureOrder) __builtin_compare_and_swap(dst, expected, replacement)
static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8 (volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) { __builtin_compare_and_swap(dst, &expected, replacement); return expected; }
static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) { __builtin_compare_and_swap(dst, &expected, replacement); return expected; }
static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) { __builtin_compare_and_swap(dst, &expected, replacement); return expected; }
static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) { __builtin_compare_and_swap(dst, &expected, replacement); return expected; }
#define MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, opName, opInst) \
static MA_INLINE ma_uint##sizeInBits ma_atomic_fetch_##opName##_explicit_##sizeInBits(volatile ma_uint##sizeInBits* dst, ma_uint##sizeInBits src, ma_atomic_memory_order order) \
{ \
ma_uint##sizeInBits oldValue; \
ma_uint##sizeInBits newValue; \
do { \
oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
newValue = oldValue opInst src; \
} while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \
(void)order; \
return oldValue; \
}
#define MA_ATOMIC_CHIBICC_FETCH_ADD(sizeInBits) MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, add, +)
MA_ATOMIC_CHIBICC_FETCH_ADD(8)
MA_ATOMIC_CHIBICC_FETCH_ADD(16)
MA_ATOMIC_CHIBICC_FETCH_ADD(32)
MA_ATOMIC_CHIBICC_FETCH_ADD(64)
#define MA_ATOMIC_CHIBICC_FETCH_SUB(sizeInBits) MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, sub, -)
MA_ATOMIC_CHIBICC_FETCH_SUB(8)
MA_ATOMIC_CHIBICC_FETCH_SUB(16)
MA_ATOMIC_CHIBICC_FETCH_SUB(32)
MA_ATOMIC_CHIBICC_FETCH_SUB(64)
#define MA_ATOMIC_CHIBICC_FETCH_OR(sizeInBits) MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, or, |)
MA_ATOMIC_CHIBICC_FETCH_OR(8)
MA_ATOMIC_CHIBICC_FETCH_OR(16)
MA_ATOMIC_CHIBICC_FETCH_OR(32)
MA_ATOMIC_CHIBICC_FETCH_OR(64)
#define MA_ATOMIC_CHIBICC_FETCH_XOR(sizeInBits) MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, xor, ^)
MA_ATOMIC_CHIBICC_FETCH_XOR(8)
MA_ATOMIC_CHIBICC_FETCH_XOR(16)
MA_ATOMIC_CHIBICC_FETCH_XOR(32)
MA_ATOMIC_CHIBICC_FETCH_XOR(64)
#define MA_ATOMIC_CHIBICC_FETCH_AND(sizeInBits) MA_ATOMIC_CHIBICC_FETCH_OP(sizeInBits, and, &)
MA_ATOMIC_CHIBICC_FETCH_AND(8)
MA_ATOMIC_CHIBICC_FETCH_AND(16)
MA_ATOMIC_CHIBICC_FETCH_AND(32)
MA_ATOMIC_CHIBICC_FETCH_AND(64)
#endif
#if !defined(MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE) #if !defined(MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE)
static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{ {
@@ -42089,7 +42202,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
state: 1, /* 1 = ma_device_state_stopped */ state: 1, /* 1 = ma_device_state_stopped */
pDevice: $1 pDevice: $1
}); });
}, pDevice->webaudio.audioContext, pDevice); }, pDevice->webaudio.audioContext, (ma_uintptr)pDevice);
return MA_SUCCESS; return MA_SUCCESS;
} }
@@ -42169,8 +42282,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* The node processing callback. */ /* The node processing callback. */
device.scriptNode.onaudioprocess = function(e) { device.scriptNode.onaudioprocess = function(e) {
if (device.intermediaryBufferView == null || device.intermediaryBufferView.length == 0) { if (device.intermediaryBufferView == null || device.intermediaryBufferView.length == 0 || device.intermediaryBufferView.buffer !== HEAPF32.buffer) {
device.intermediaryBufferView = new Float32Array(HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels); device.intermediaryBufferView = new Float32Array(HEAPF32.buffer, Number(pIntermediaryBuffer), bufferSize * channels);
} }
/* Do the capture side first. */ /* Do the capture side first. */
@@ -42227,7 +42340,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
device.pDevice = pDevice; device.pDevice = pDevice;
return window.miniaudio.track_device(device); return window.miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, (ma_uintptr)pDevice->webaudio.pIntermediaryBuffer, (ma_uintptr)pDevice);
if (deviceIndex < 0) { if (deviceIndex < 0) {
return MA_FAILED_TO_OPEN_BACKEND_DEVICE; return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
@@ -61944,7 +62057,7 @@ extern "C" {
#define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x) #define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x)
#define MA_DR_WAV_VERSION_MAJOR 0 #define MA_DR_WAV_VERSION_MAJOR 0
#define MA_DR_WAV_VERSION_MINOR 14 #define MA_DR_WAV_VERSION_MINOR 14
#define MA_DR_WAV_VERSION_REVISION 5 #define MA_DR_WAV_VERSION_REVISION 6
#define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION) #define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION)
#include <stddef.h> #include <stddef.h>
#define MA_DR_WAVE_FORMAT_PCM 0x1 #define MA_DR_WAVE_FORMAT_PCM 0x1
@@ -62379,7 +62492,7 @@ extern "C" {
#define MA_DR_FLAC_XSTRINGIFY(x) MA_DR_FLAC_STRINGIFY(x) #define MA_DR_FLAC_XSTRINGIFY(x) MA_DR_FLAC_STRINGIFY(x)
#define MA_DR_FLAC_VERSION_MAJOR 0 #define MA_DR_FLAC_VERSION_MAJOR 0
#define MA_DR_FLAC_VERSION_MINOR 13 #define MA_DR_FLAC_VERSION_MINOR 13
#define MA_DR_FLAC_VERSION_REVISION 3 #define MA_DR_FLAC_VERSION_REVISION 4
#define MA_DR_FLAC_VERSION_STRING MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MAJOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MINOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_REVISION) #define MA_DR_FLAC_VERSION_STRING MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MAJOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MINOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_REVISION)
#include <stddef.h> #include <stddef.h>
#if defined(_MSC_VER) && _MSC_VER >= 1700 #if defined(_MSC_VER) && _MSC_VER >= 1700
@@ -62679,7 +62792,7 @@ extern "C" {
#define MA_DR_MP3_XSTRINGIFY(x) MA_DR_MP3_STRINGIFY(x) #define MA_DR_MP3_XSTRINGIFY(x) MA_DR_MP3_STRINGIFY(x)
#define MA_DR_MP3_VERSION_MAJOR 0 #define MA_DR_MP3_VERSION_MAJOR 0
#define MA_DR_MP3_VERSION_MINOR 7 #define MA_DR_MP3_VERSION_MINOR 7
#define MA_DR_MP3_VERSION_REVISION 3 #define MA_DR_MP3_VERSION_REVISION 4
#define MA_DR_MP3_VERSION_STRING MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MAJOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MINOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_REVISION) #define MA_DR_MP3_VERSION_STRING MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MAJOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MINOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_REVISION)
#include <stddef.h> #include <stddef.h>
#define MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152 #define MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
@@ -62853,6 +62966,10 @@ static ma_result ma_decoder_seek_bytes(ma_decoder* pDecoder, ma_int64 byteOffset
{ {
MA_ASSERT(pDecoder != NULL); MA_ASSERT(pDecoder != NULL);
if (pDecoder->onSeek == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pDecoder->onSeek(pDecoder, byteOffset, origin); return pDecoder->onSeek(pDecoder, byteOffset, origin);
} }
@@ -80361,7 +80478,12 @@ MA_PRIVATE ma_result ma_dr_wav__read_chunk_header(ma_dr_wav_read_proc onRead, vo
if (onRead(pUserData, sizeInBytes, 8) != 8) { if (onRead(pUserData, sizeInBytes, 8) != 8) {
return MA_INVALID_FILE; return MA_INVALID_FILE;
} }
pHeaderOut->sizeInBytes = ma_dr_wav_bytes_to_u64(sizeInBytes) - 24; pHeaderOut->sizeInBytes = ma_dr_wav_bytes_to_u64(sizeInBytes);
if (pHeaderOut->sizeInBytes >= 24) {
pHeaderOut->sizeInBytes -= 24;
} else {
return MA_INVALID_FILE;
}
pHeaderOut->paddingSize = ma_dr_wav__chunk_padding_size_w64(pHeaderOut->sizeInBytes); pHeaderOut->paddingSize = ma_dr_wav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
*pRunningBytesReadOut += 24; *pRunningBytesReadOut += 24;
} else { } else {
@@ -80529,7 +80651,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa
ma_uint32 loopCount; ma_uint32 loopCount;
ma_uint32 calculatedLoopCount; ma_uint32 calculatedLoopCount;
loopCount = ma_dr_wav_bytes_to_u32(smplHeaderData + 28); loopCount = ma_dr_wav_bytes_to_u32(smplHeaderData + 28);
calculatedLoopCount = (pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES; calculatedLoopCount = (ma_uint32)((pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES);
if (loopCount != calculatedLoopCount) { if (loopCount != calculatedLoopCount) {
return totalBytesRead; return totalBytesRead;
} }
@@ -80804,8 +80926,9 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_bext_to_metadata_obj(ma_dr_wav__metadata_pa
if (extraBytes > 0) { if (extraBytes > 0) {
pMetadata->data.bext.pCodingHistory = (char*)ma_dr_wav__metadata_get_memory(pParser, extraBytes + 1, 1); pMetadata->data.bext.pCodingHistory = (char*)ma_dr_wav__metadata_get_memory(pParser, extraBytes + 1, 1);
MA_DR_WAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL); MA_DR_WAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
bytesRead += ma_dr_wav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL); pMetadata->data.bext.codingHistorySize = (ma_uint32)ma_dr_wav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
pMetadata->data.bext.codingHistorySize = (ma_uint32)ma_dr_wav__strlen(pMetadata->data.bext.pCodingHistory); pMetadata->data.bext.pCodingHistory[pMetadata->data.bext.codingHistorySize] = '\0';
bytesRead += pMetadata->data.bext.codingHistorySize;
} else { } else {
pMetadata->data.bext.pCodingHistory = NULL; pMetadata->data.bext.pCodingHistory = NULL;
pMetadata->data.bext.codingHistorySize = 0; pMetadata->data.bext.codingHistorySize = 0;
@@ -80947,8 +81070,8 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse
bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
ma_uint32 loopCount = ma_dr_wav_bytes_to_u32(buffer); ma_uint32 loopCount = ma_dr_wav_bytes_to_u32(buffer);
ma_uint64 calculatedLoopCount; ma_uint32 calculatedLoopCount;
calculatedLoopCount = (pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES; calculatedLoopCount = (ma_uint32)((pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES);
if (calculatedLoopCount == loopCount) { if (calculatedLoopCount == loopCount) {
bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
@@ -81362,6 +81485,9 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
if (((pWav->container == ma_dr_wav_container_riff || pWav->container == ma_dr_wav_container_rifx || pWav->container == ma_dr_wav_container_rf64) && ma_dr_wav_fourcc_equal(header.id.fourcc, "fmt ")) || if (((pWav->container == ma_dr_wav_container_riff || pWav->container == ma_dr_wav_container_rifx || pWav->container == ma_dr_wav_container_rf64) && ma_dr_wav_fourcc_equal(header.id.fourcc, "fmt ")) ||
((pWav->container == ma_dr_wav_container_w64) && ma_dr_wav_guid_equal(header.id.guid, ma_dr_wavGUID_W64_FMT))) { ((pWav->container == ma_dr_wav_container_w64) && ma_dr_wav_guid_equal(header.id.guid, ma_dr_wavGUID_W64_FMT))) {
ma_uint8 fmtData[16]; ma_uint8 fmtData[16];
if (header.sizeInBytes < sizeof(fmtData)) {
return MA_FALSE;
}
foundChunk_fmt = MA_TRUE; foundChunk_fmt = MA_TRUE;
if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) { if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
return MA_FALSE; return MA_FALSE;
@@ -81699,6 +81825,10 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
blockCount += 1; blockCount += 1;
} }
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) {
ma_dr_wav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return MA_FALSE;
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
} }
if (pWav->translatedFormatTag == MA_DR_WAVE_FORMAT_DVI_ADPCM) { if (pWav->translatedFormatTag == MA_DR_WAVE_FORMAT_DVI_ADPCM) {
@@ -81708,6 +81838,10 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
blockCount += 1; blockCount += 1;
} }
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) {
ma_dr_wav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return MA_FALSE;
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
pWav->totalPCMFrameCount += blockCount; pWav->totalPCMFrameCount += blockCount;
} }
@@ -83422,6 +83556,9 @@ MA_PRIVATE void ma_dr_wav__pcm_to_s16(ma_int16* pOut, const ma_uint8* pIn, size_
sample |= (ma_uint64)(pIn[j]) << shift; sample |= (ma_uint64)(pIn[j]) << shift;
shift += 8; shift += 8;
} }
if (!ma_dr_wav__is_little_endian()) {
sample = ma_dr_wav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (ma_int16)((ma_int64)sample >> 48); *pOut++ = (ma_int16)((ma_int64)sample >> 48);
} }
@@ -83763,6 +83900,9 @@ MA_PRIVATE void ma_dr_wav__pcm_to_f32(float* pOut, const ma_uint8* pIn, size_t s
sample |= (ma_uint64)(pIn[j]) << shift; sample |= (ma_uint64)(pIn[j]) << shift;
shift += 8; shift += 8;
} }
if (!ma_dr_wav__is_little_endian()) {
sample = ma_dr_wav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (float)((ma_int64)sample / 9223372036854775807.0); *pOut++ = (float)((ma_int64)sample / 9223372036854775807.0);
} }
@@ -84127,6 +84267,9 @@ MA_PRIVATE void ma_dr_wav__pcm_to_s32(ma_int32* pOut, const ma_uint8* pIn, size_
sample |= (ma_uint64)(pIn[j]) << shift; sample |= (ma_uint64)(pIn[j]) << shift;
shift += 8; shift += 8;
} }
if (!ma_dr_wav__is_little_endian()) {
sample = ma_dr_wav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (ma_int32)((ma_int64)sample >> 32); *pOut++ = (ma_int32)((ma_int64)sample >> 32);
} }
@@ -85061,6 +85204,7 @@ static MA_INLINE ma_bool32 ma_dr_flac_has_sse41(void)
#ifndef MA_DR_FLAC_ZERO_OBJECT #ifndef MA_DR_FLAC_ZERO_OBJECT
#define MA_DR_FLAC_ZERO_OBJECT(p) MA_DR_FLAC_ZERO_MEMORY((p), sizeof(*(p))) #define MA_DR_FLAC_ZERO_OBJECT(p) MA_DR_FLAC_ZERO_MEMORY((p), sizeof(*(p)))
#endif #endif
#define MA_DR_FLAC_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MA_DR_FLAC_MAX_SIMD_VECTOR_SIZE 64 #define MA_DR_FLAC_MAX_SIMD_VECTOR_SIZE 64
#define MA_DR_FLAC_SUBFRAME_CONSTANT 0 #define MA_DR_FLAC_SUBFRAME_CONSTANT 0
#define MA_DR_FLAC_SUBFRAME_VERBATIM 1 #define MA_DR_FLAC_SUBFRAME_VERBATIM 1
@@ -88342,7 +88486,6 @@ static ma_bool32 ma_dr_flac__seek_to_pcm_frame__binary_search_internal(ma_dr_fla
break; break;
} }
} else { } else {
const float approxCompressionRatio = (ma_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((ma_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
if (pcmRangeLo > pcmFrameIndex) { if (pcmRangeLo > pcmFrameIndex) {
byteRangeHi = lastSuccessfulSeekOffset; byteRangeHi = lastSuccessfulSeekOffset;
if (byteRangeLo > byteRangeHi) { if (byteRangeLo > byteRangeHi) {
@@ -88360,11 +88503,12 @@ static ma_bool32 ma_dr_flac__seek_to_pcm_frame__binary_search_internal(ma_dr_fla
break; break;
} }
} else { } else {
const double approxCompressionRatio = (ma_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((ma_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0);
byteRangeLo = lastSuccessfulSeekOffset; byteRangeLo = lastSuccessfulSeekOffset;
if (byteRangeHi < byteRangeLo) { if (byteRangeHi < byteRangeLo) {
byteRangeHi = byteRangeLo; byteRangeHi = byteRangeLo;
} }
targetByte = lastSuccessfulSeekOffset + (ma_uint64)(((ma_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio); targetByte = lastSuccessfulSeekOffset + (ma_uint64)(((ma_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0) * approxCompressionRatio);
if (targetByte > byteRangeHi) { if (targetByte > byteRangeHi) {
targetByte = byteRangeHi; targetByte = byteRangeHi;
} }
@@ -88645,7 +88789,7 @@ static void* ma_dr_flac__realloc_from_callbacks(void* p, size_t szNew, size_t sz
return NULL; return NULL;
} }
if (p != NULL) { if (p != NULL) {
MA_DR_FLAC_COPY_MEMORY(p2, p, szOld); MA_DR_FLAC_COPY_MEMORY(p2, p, MA_DR_FLAC_MIN(szNew, szOld));
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
} }
return p2; return p2;
@@ -88663,10 +88807,19 @@ static void ma_dr_flac__free_from_callbacks(void* p, const ma_allocation_callbac
} }
static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks) static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks)
{ {
ma_uint64 runningFilePos = 42; ma_uint64 runningFilePos = 42;
ma_uint64 seektablePos = 0; ma_uint64 seektablePos = 0;
ma_uint32 seektableSize = 0; ma_uint32 seektableSize = 0;
(void)onTell; ma_int64 fileSize = 0;
ma_bool32 hasKnownFileSize = MA_FALSE;
if (onTell != NULL && onSeek != NULL) {
if (onSeek(pUserData, 0, MA_DR_FLAC_SEEK_END)) {
if (onTell(pUserData, &fileSize)) {
hasKnownFileSize = MA_TRUE;
}
onSeek(pUserData, runningFilePos, MA_DR_FLAC_SEEK_SET);
}
}
for (;;) { for (;;) {
ma_dr_flac_metadata metadata; ma_dr_flac_metadata metadata;
ma_uint8 isLastBlock = 0; ma_uint8 isLastBlock = 0;
@@ -88675,6 +88828,9 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
if (ma_dr_flac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == MA_FALSE) { if (ma_dr_flac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == MA_FALSE) {
return MA_FALSE; return MA_FALSE;
} }
if (hasKnownFileSize && (blockSize > ((ma_uint64)fileSize - runningFilePos))) {
return MA_FALSE;
}
runningFilePos += 4; runningFilePos += 4;
metadata.type = blockType; metadata.type = blockType;
metadata.rawDataSize = 0; metadata.rawDataSize = 0;
@@ -88763,7 +88919,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks);
return MA_FALSE; return MA_FALSE;
} }
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength; metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
metadata.data.vorbis_comment.commentCount = ma_dr_flac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4; metadata.data.vorbis_comment.commentCount = ma_dr_flac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if ((pRunningDataEnd - pRunningData) / sizeof(ma_uint32) < metadata.data.vorbis_comment.commentCount) { if ((pRunningDataEnd - pRunningData) / sizeof(ma_uint32) < metadata.data.vorbis_comment.commentCount) {
ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks);
@@ -88896,12 +89052,16 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
} }
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.mimeLength = ma_dr_flac__be2host_32(metadata.data.picture.mimeLength); metadata.data.picture.mimeLength = ma_dr_flac__be2host_32(metadata.data.picture.mimeLength);
if (blockSizeRemaining < metadata.data.picture.mimeLength) {
result = MA_FALSE;
goto done_flac;
}
pMime = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); pMime = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks);
if (pMime == NULL) { if (pMime == NULL) {
result = MA_FALSE; result = MA_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { if (onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
result = MA_FALSE; result = MA_FALSE;
goto done_flac; goto done_flac;
} }
@@ -88914,12 +89074,16 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
} }
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.descriptionLength = ma_dr_flac__be2host_32(metadata.data.picture.descriptionLength); metadata.data.picture.descriptionLength = ma_dr_flac__be2host_32(metadata.data.picture.descriptionLength);
if (blockSizeRemaining < metadata.data.picture.descriptionLength) {
result = MA_FALSE;
goto done_flac;
}
pDescription = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); pDescription = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks);
if (pDescription == NULL) { if (pDescription == NULL) {
result = MA_FALSE; result = MA_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { if (onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
result = MA_FALSE; result = MA_FALSE;
goto done_flac; goto done_flac;
} }
@@ -89878,9 +90042,15 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
#endif #endif
return NULL; return NULL;
} }
if ((0xFFFFFFFF - (seekpointCount * sizeof(ma_dr_flac_seekpoint))) < allocationSize) {
#ifndef MA_DR_FLAC_NO_OGG
ma_dr_flac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
return NULL;
}
allocationSize += seekpointCount * sizeof(ma_dr_flac_seekpoint); allocationSize += seekpointCount * sizeof(ma_dr_flac_seekpoint);
} }
pFlac = (ma_dr_flac*)ma_dr_flac__malloc_from_callbacks(allocationSize, &allocationCallbacks); pFlac = (ma_dr_flac*)ma_dr_flac__malloc_from_callbacks((size_t)allocationSize, &allocationCallbacks);
if (pFlac == NULL) { if (pFlac == NULL) {
#ifndef MA_DR_FLAC_NO_OGG #ifndef MA_DR_FLAC_NO_OGG
ma_dr_flac__free_from_callbacks(pOggbs, &allocationCallbacks); ma_dr_flac__free_from_callbacks(pOggbs, &allocationCallbacks);
@@ -92753,7 +92923,10 @@ MA_API const char* ma_dr_mp3_version_string(void)
#define MA_DR_MP3_MIN(a, b) ((a) > (b) ? (b) : (a)) #define MA_DR_MP3_MIN(a, b) ((a) > (b) ? (b) : (a))
#define MA_DR_MP3_MAX(a, b) ((a) < (b) ? (b) : (a)) #define MA_DR_MP3_MAX(a, b) ((a) < (b) ? (b) : (a))
#if !defined(MA_DR_MP3_NO_SIMD) #if !defined(MA_DR_MP3_NO_SIMD)
#if !defined(MA_DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) #if !defined(MA_DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
#define MA_DR_MP3_ONLY_SIMD
#endif
#if !defined(MA_DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
#define MA_DR_MP3_ONLY_SIMD #define MA_DR_MP3_ONLY_SIMD
#endif #endif
#if ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__))) #if ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
@@ -94910,6 +95083,9 @@ static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc on
const ma_uint8* pTagDataBeg; const ma_uint8* pTagDataBeg;
pTagDataBeg = pFirstFrameData + MA_DR_MP3_HDR_SIZE + (bs.pos/8); pTagDataBeg = pFirstFrameData + MA_DR_MP3_HDR_SIZE + (bs.pos/8);
pTagData = pTagDataBeg; pTagData = pTagDataBeg;
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) {
goto done_xing_info;
}
isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g'); isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o'); isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
if (isXing || isInfo) { if (isXing || isInfo) {
@@ -94917,33 +95093,46 @@ static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc on
ma_uint32 flags = pTagData[7]; ma_uint32 flags = pTagData[7];
pTagData += 8; pTagData += 8;
if (flags & 0x01) { if (flags & 0x01) {
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info;
}
detectedMP3FrameCount = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3]; detectedMP3FrameCount = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3];
pTagData += 4; pTagData += 4;
} }
if (flags & 0x02) { if (flags & 0x02) {
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info;
}
bytes = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3]; bytes = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3];
(void)bytes; (void)bytes;
pTagData += 4; pTagData += 4;
} }
if (flags & 0x04) { if (flags & 0x04) {
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) {
goto done_xing_info;
}
pTagData += 100; pTagData += 100;
} }
if (flags & 0x08) { if (flags & 0x08) {
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info;
}
pTagData += 4; pTagData += 4;
} }
if (pTagData[0]) { if (pTagData[0]) {
pTagData += 21; int delayInPCMFrames;
if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) { int paddingInPCMFrames;
int delayInPCMFrames; if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) {
int paddingInPCMFrames; goto done_xing_info;
delayInPCMFrames = (( (ma_uint32)pTagData[0] << 4) | ((ma_uint32)pTagData[1] >> 4)) + (528 + 1);
paddingInPCMFrames = ((((ma_uint32)pTagData[1] & 0xF) << 8) | ((ma_uint32)pTagData[2] )) - (528 + 1);
if (paddingInPCMFrames < 0) {
paddingInPCMFrames = 0;
}
pMP3->delayInPCMFrames = (ma_uint32)delayInPCMFrames;
pMP3->paddingInPCMFrames = (ma_uint32)paddingInPCMFrames;
} }
pTagData += 21;
delayInPCMFrames = (( (ma_uint32)pTagData[0] << 4) | ((ma_uint32)pTagData[1] >> 4)) + (528 + 1);
paddingInPCMFrames = ((((ma_uint32)pTagData[1] & 0xF) << 8) | ((ma_uint32)pTagData[2] )) - (528 + 1);
if (paddingInPCMFrames < 0) {
paddingInPCMFrames = 0;
}
pMP3->delayInPCMFrames = (ma_uint32)delayInPCMFrames;
pMP3->paddingInPCMFrames = (ma_uint32)paddingInPCMFrames;
} }
if (isXing) { if (isXing) {
pMP3->isVBR = MA_TRUE; pMP3->isVBR = MA_TRUE;
@@ -94962,6 +95151,7 @@ static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc on
pMP3->streamCursor = pMP3->streamStartOffset; pMP3->streamCursor = pMP3->streamStartOffset;
ma_dr_mp3dec_init(&pMP3->decoder); ma_dr_mp3dec_init(&pMP3->decoder);
} }
done_xing_info:;
} else { } else {
} }
} }
@@ -94971,7 +95161,7 @@ static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc on
return MA_FALSE; return MA_FALSE;
} }
if (detectedMP3FrameCount != 0xFFFFFFFF) { if (detectedMP3FrameCount != 0xFFFFFFFF) {
pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount; pMP3->totalPCMFrameCount = (ma_uint64)detectedMP3FrameCount * firstFramePCMFrameCount;
} }
pMP3->channels = pMP3->mp3FrameChannels; pMP3->channels = pMP3->mp3FrameChannels;
pMP3->sampleRate = pMP3->mp3FrameSampleRate; pMP3->sampleRate = pMP3->mp3FrameSampleRate;
@@ -95271,7 +95461,7 @@ MA_API ma_uint64 ma_dr_mp3_read_pcm_frames_f32(ma_dr_mp3* pMP3, ma_uint64 frames
return ma_dr_mp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut); return ma_dr_mp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
#else #else
{ {
ma_int16 pTempS16[8192]; ma_int16 pTempS16[1152*2];
ma_uint64 totalPCMFramesRead = 0; ma_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
ma_uint64 framesJustRead; ma_uint64 framesJustRead;
@@ -95300,7 +95490,7 @@ MA_API ma_uint64 ma_dr_mp3_read_pcm_frames_s16(ma_dr_mp3* pMP3, ma_uint64 frames
return ma_dr_mp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut); return ma_dr_mp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
#else #else
{ {
float pTempF32[4096]; float pTempF32[1152*2];
ma_uint64 totalPCMFramesRead = 0; ma_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
ma_uint64 framesJustRead; ma_uint64 framesJustRead;
@@ -95631,7 +95821,7 @@ static float* ma_dr_mp3__full_read_and_close_f32(ma_dr_mp3* pMP3, ma_dr_mp3_conf
ma_uint64 totalFramesRead = 0; ma_uint64 totalFramesRead = 0;
ma_uint64 framesCapacity = 0; ma_uint64 framesCapacity = 0;
float* pFrames = NULL; float* pFrames = NULL;
float temp[4096]; float temp[1152*2];
MA_DR_MP3_ASSERT(pMP3 != NULL); MA_DR_MP3_ASSERT(pMP3 != NULL);
for (;;) { for (;;) {
ma_uint64 framesToReadRightNow = MA_DR_MP3_COUNTOF(temp) / pMP3->channels; ma_uint64 framesToReadRightNow = MA_DR_MP3_COUNTOF(temp) / pMP3->channels;
@@ -95684,7 +95874,7 @@ static ma_int16* ma_dr_mp3__full_read_and_close_s16(ma_dr_mp3* pMP3, ma_dr_mp3_c
ma_uint64 totalFramesRead = 0; ma_uint64 totalFramesRead = 0;
ma_uint64 framesCapacity = 0; ma_uint64 framesCapacity = 0;
ma_int16* pFrames = NULL; ma_int16* pFrames = NULL;
ma_int16 temp[4096]; ma_int16 temp[1152*2];
MA_DR_MP3_ASSERT(pMP3 != NULL); MA_DR_MP3_ASSERT(pMP3 != NULL);
for (;;) { for (;;) {
ma_uint64 framesToReadRightNow = MA_DR_MP3_COUNTOF(temp) / pMP3->channels; ma_uint64 framesToReadRightNow = MA_DR_MP3_COUNTOF(temp) / pMP3->channels;
+2 -2
View File
@@ -15,11 +15,11 @@ On Linux, do `source ~/emsdk/emsdk_env.sh` before compiling.
On Windows, you need to move into the build and run emsdk_env.bat from a command prompt using an absolute On Windows, you need to move into the build and run emsdk_env.bat from a command prompt using an absolute
path like "C:\emsdk\emsdk_env.bat". Note that PowerShell doesn't work for me for some reason. Example: path like "C:\emsdk\emsdk_env.bat". Note that PowerShell doesn't work for me for some reason. Example:
emcc ../test_emscripten/ma_test_emscripten.c -o bin/test_emscripten.html -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY -DMA_ENABLE_AUDIO_WORKLETS -Wall -Wextra emcc ../emscripten/emscripten.c -o bin/emscripten.html -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY -DMA_ENABLE_AUDIO_WORKLETS -Wall -Wextra
If you output WASM it may not work when running the web page locally. To test you can run with something If you output WASM it may not work when running the web page locally. To test you can run with something
like this: like this:
emrun ./bin/test_emscripten.html emrun ./bin/emscripten.html
If you want to see stdout on the command line when running from emrun, add `--emrun` to your emcc command. If you want to see stdout on the command line when running from emrun, add `--emrun` to your emcc command.