mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
Merge branch 'dev' of https://github.com/dr-soft/mini_al into dev
This commit is contained in:
+43
-16
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_flac - v0.12.19 - 2020-08-30
|
||||
dr_flac - v0.12.22 - 2020-11-01
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -232,7 +232,7 @@ extern "C" {
|
||||
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 12
|
||||
#define DRFLAC_VERSION_REVISION 19
|
||||
#define DRFLAC_VERSION_REVISION 22
|
||||
#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. */
|
||||
@@ -248,7 +248,7 @@ typedef unsigned int drflac_uint32;
|
||||
typedef signed __int64 drflac_int64;
|
||||
typedef unsigned __int64 drflac_uint64;
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
@@ -257,7 +257,7 @@ typedef unsigned int drflac_uint32;
|
||||
#endif
|
||||
typedef signed long long drflac_int64;
|
||||
typedef unsigned long long drflac_uint64;
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
@@ -1319,7 +1319,7 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
#define dr_flac_c
|
||||
|
||||
/* Disable some annoying warnings. */
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#if __GNUC__ >= 7
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
@@ -1367,7 +1367,15 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
#define DRFLAC_ARM
|
||||
#endif
|
||||
|
||||
/* Intrinsics Support */
|
||||
/*
|
||||
Intrinsics Support
|
||||
|
||||
There's a bug in GCC 4.2.x which results in an incorrect compilation error when using _mm_slli_epi32() where it complains with
|
||||
|
||||
"error: shift must be an immediate"
|
||||
|
||||
Unfortuantely dr_flac depends on this for a few things so we're just going to disable SSE on GCC 4.2 and below.
|
||||
*/
|
||||
#if !defined(DR_FLAC_NO_SIMD)
|
||||
#if defined(DRFLAC_X64) || defined(DRFLAC_X86)
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
@@ -1378,7 +1386,7 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
#if _MSC_VER >= 1600 && !defined(DRFLAC_NO_SSE41) /* 2010 */
|
||||
#define DRFLAC_SUPPORT_SSE41
|
||||
#endif
|
||||
#else
|
||||
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
|
||||
/* Assume GNUC-style. */
|
||||
#if defined(__SSE2__) && !defined(DRFLAC_NO_SSE2)
|
||||
#define DRFLAC_SUPPORT_SSE2
|
||||
@@ -1828,14 +1836,15 @@ static DRFLAC_INLINE drflac_uint64 drflac__swap_endian_uint64(drflac_uint64 n)
|
||||
#error "This compiler does not support the byte swap intrinsic."
|
||||
#endif
|
||||
#else
|
||||
return ((n & (drflac_uint64)0xFF00000000000000) >> 56) |
|
||||
((n & (drflac_uint64)0x00FF000000000000) >> 40) |
|
||||
((n & (drflac_uint64)0x0000FF0000000000) >> 24) |
|
||||
((n & (drflac_uint64)0x000000FF00000000) >> 8) |
|
||||
((n & (drflac_uint64)0x00000000FF000000) << 8) |
|
||||
((n & (drflac_uint64)0x0000000000FF0000) << 24) |
|
||||
((n & (drflac_uint64)0x000000000000FF00) << 40) |
|
||||
((n & (drflac_uint64)0x00000000000000FF) << 56);
|
||||
/* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
|
||||
return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
|
||||
((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
|
||||
((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
|
||||
((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
|
||||
((n & ((drflac_uint64)0xFF000000 )) << 8) |
|
||||
((n & ((drflac_uint64)0x00FF0000 )) << 24) |
|
||||
((n & ((drflac_uint64)0x0000FF00 )) << 40) |
|
||||
((n & ((drflac_uint64)0x000000FF )) << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5740,6 +5749,9 @@ static drflac_bool32 drflac__seek_to_approximate_flac_frame_to_byte(drflac* pFla
|
||||
*pLastSuccessfulSeekOffset = pFlac->firstFLACFramePosInBytes;
|
||||
|
||||
for (;;) {
|
||||
/* After rangeLo == rangeHi == targetByte fails, we need to break out. */
|
||||
drflac_uint64 lastTargetByte = targetByte;
|
||||
|
||||
/* When seeking to a byte, failure probably means we've attempted to seek beyond the end of the stream. To counter this we just halve it each attempt. */
|
||||
if (!drflac__seek_to_byte(&pFlac->bs, targetByte)) {
|
||||
/* If we couldn't even seek to the first byte in the stream we have a problem. Just abandon the whole thing. */
|
||||
@@ -5780,6 +5792,11 @@ static drflac_bool32 drflac__seek_to_approximate_flac_frame_to_byte(drflac* pFla
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We already tried this byte and there are no more to try, break out. */
|
||||
if(targetByte == lastTargetByte) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The current PCM frame needs to be updated based on the frame we just seeked to. */
|
||||
@@ -11762,7 +11779,7 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif /* dr_flac_c */
|
||||
@@ -11772,6 +11789,16 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.12.22 - 2020-11-01
|
||||
- Fix an error with the previous release.
|
||||
|
||||
v0.12.21 - 2020-11-01
|
||||
- Fix a possible deadlock when seeking.
|
||||
- Improve compiler support for older versions of GCC.
|
||||
|
||||
v0.12.20 - 2020-09-08
|
||||
- Fix a compilation error on older compilers.
|
||||
|
||||
v0.12.19 - 2020-08-30
|
||||
- Fix a bug due to an undefined 32-bit shift.
|
||||
|
||||
|
||||
+12
-4
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_mp3 - v0.6.16 - 2020-08-02
|
||||
dr_mp3 - v0.6.18 - 2020-11-01
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -95,7 +95,7 @@ extern "C" {
|
||||
|
||||
#define DRMP3_VERSION_MAJOR 0
|
||||
#define DRMP3_VERSION_MINOR 6
|
||||
#define DRMP3_VERSION_REVISION 16
|
||||
#define DRMP3_VERSION_REVISION 18
|
||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@@ -111,7 +111,7 @@ typedef unsigned int drmp3_uint32;
|
||||
typedef signed __int64 drmp3_int64;
|
||||
typedef unsigned __int64 drmp3_uint64;
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
@@ -120,7 +120,7 @@ typedef unsigned int drmp3_uint32;
|
||||
#endif
|
||||
typedef signed long long drmp3_int64;
|
||||
typedef unsigned long long drmp3_uint64;
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
@@ -713,6 +713,8 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
||||
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define DRMP3_HAVE_ARMV6 0
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4430,6 +4432,12 @@ counts rather than sample counts.
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.6.18 - 2020-11-01
|
||||
- Improve compiler support for older versions of GCC.
|
||||
|
||||
v0.6.17 - 2020-09-28
|
||||
- Bring up to date with minimp3.
|
||||
|
||||
v0.6.16 - 2020-08-02
|
||||
- Simplify sized types.
|
||||
|
||||
|
||||
+168
-59
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_wav - v0.12.10 - 2020-08-24
|
||||
dr_wav - v0.12.13 - 2020-11-01
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -18,7 +18,7 @@ Changes to Chunk Callback
|
||||
dr_wav supports the ability to fire a callback when a chunk is encounted (except for WAVE and FMT chunks). The callback has been updated to include both the
|
||||
container (RIFF or Wave64) and the FMT chunk which contains information about the format of the data in the wave file.
|
||||
|
||||
Previously, there was no direct way to determine the container, and therefore no way discriminate against the different IDs in the chunk header (RIFF and
|
||||
Previously, there was no direct way to determine the container, and therefore no way to discriminate against the different IDs in the chunk header (RIFF and
|
||||
Wave64 containers encode chunk ID's differently). The `container` parameter can be used to know which ID to use.
|
||||
|
||||
Sometimes it can be useful to know the data format at the time the chunk callback is fired. A pointer to a `drwav_fmt` object is now passed into the chunk
|
||||
@@ -144,7 +144,7 @@ extern "C" {
|
||||
|
||||
#define DRWAV_VERSION_MAJOR 0
|
||||
#define DRWAV_VERSION_MINOR 12
|
||||
#define DRWAV_VERSION_REVISION 10
|
||||
#define DRWAV_VERSION_REVISION 13
|
||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@@ -160,7 +160,7 @@ typedef unsigned int drwav_uint32;
|
||||
typedef signed __int64 drwav_int64;
|
||||
typedef unsigned __int64 drwav_uint64;
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
@@ -169,7 +169,7 @@ typedef unsigned int drwav_uint32;
|
||||
#endif
|
||||
typedef signed long long drwav_int64;
|
||||
typedef unsigned long long drwav_uint64;
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
@@ -298,7 +298,8 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
drwav_container_riff,
|
||||
drwav_container_w64
|
||||
drwav_container_w64,
|
||||
drwav_container_rf64
|
||||
} drwav_container;
|
||||
|
||||
typedef struct
|
||||
@@ -419,8 +420,8 @@ Returns the number of bytes read + seeked.
|
||||
To read data from the chunk, call onRead(), passing in pReadSeekUserData as the first parameter. Do the same for seeking with onSeek(). The return value must
|
||||
be the total number of bytes you have read _plus_ seeked.
|
||||
|
||||
Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` you should use `id.fourcc`,
|
||||
otherwise you should use `id.guid`.
|
||||
Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` or `drwav_container_rf64` you should
|
||||
use `id.fourcc`, otherwise you should use `id.guid`.
|
||||
|
||||
The `pFMT` parameter can be used to determine the data format of the wave file. Use `drwav_fmt_get_format()` to get the sample format, which will be one of the
|
||||
`DR_WAVE_FORMAT_*` identifiers.
|
||||
@@ -881,8 +882,8 @@ Helper for initializing a writer which outputs data to a memory buffer.
|
||||
|
||||
dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
|
||||
|
||||
The buffer will remain allocated even after drwav_uninit() is called. Indeed, the buffer should not be
|
||||
considered valid until after drwav_uninit() has been called anyway.
|
||||
The buffer will remain allocated even after drwav_uninit() is called. The buffer should not be considered valid
|
||||
until after drwav_uninit() has been called.
|
||||
*/
|
||||
DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||
DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||
@@ -1236,14 +1237,15 @@ static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
|
||||
#error "This compiler does not support the byte swap intrinsic."
|
||||
#endif
|
||||
#else
|
||||
return ((n & (drwav_uint64)0xFF00000000000000) >> 56) |
|
||||
((n & (drwav_uint64)0x00FF000000000000) >> 40) |
|
||||
((n & (drwav_uint64)0x0000FF0000000000) >> 24) |
|
||||
((n & (drwav_uint64)0x000000FF00000000) >> 8) |
|
||||
((n & (drwav_uint64)0x00000000FF000000) << 8) |
|
||||
((n & (drwav_uint64)0x0000000000FF0000) << 24) |
|
||||
((n & (drwav_uint64)0x000000000000FF00) << 40) |
|
||||
((n & (drwav_uint64)0x00000000000000FF) << 56);
|
||||
/* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
|
||||
return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
|
||||
((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
|
||||
((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
|
||||
((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
|
||||
((n & ((drwav_uint64)0xFF000000 )) << 8) |
|
||||
((n & ((drwav_uint64)0x00FF0000 )) << 24) |
|
||||
((n & ((drwav_uint64)0x0000FF00 )) << 40) |
|
||||
((n & ((drwav_uint64)0x000000FF )) << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1537,7 +1539,7 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
||||
|
||||
static drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
|
||||
{
|
||||
if (container == drwav_container_riff) {
|
||||
if (container == drwav_container_riff || container == drwav_container_rf64) {
|
||||
drwav_uint8 sizeInBytes[4];
|
||||
|
||||
if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
|
||||
@@ -1629,7 +1631,7 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
||||
|
||||
|
||||
/* Skip non-fmt chunks. */
|
||||
while ((container == drwav_container_riff && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||
while (((container == drwav_container_riff || container == drwav_container_rf64) && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||
if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -1643,7 +1645,7 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
||||
|
||||
|
||||
/* Validation. */
|
||||
if (container == drwav_container_riff) {
|
||||
if (container == drwav_container_riff || container == drwav_container_rf64) {
|
||||
if (!drwav__fourcc_equal(header.id.fourcc, "fmt ")) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -1817,9 +1819,9 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
drwav_uint8 riff[4];
|
||||
drwav_fmt fmt;
|
||||
unsigned short translatedFormatTag;
|
||||
drwav_uint64 sampleCountFromFactChunk;
|
||||
drwav_bool32 foundDataChunk;
|
||||
drwav_uint64 dataChunkSize;
|
||||
drwav_uint64 dataChunkSize = 0; /* <-- Important! Don't explicitly set this to 0 anywhere else. Calculation of the size of the data chunk is performed in different paths depending on the container. */
|
||||
drwav_uint64 sampleCountFromFactChunk = 0; /* Same as dataChunkSize - make sure this is the only place this is initialized to 0. */
|
||||
drwav_uint64 chunkSize;
|
||||
|
||||
cursor = 0;
|
||||
@@ -1852,12 +1854,14 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
} else if (drwav__fourcc_equal(riff, "RF64")) {
|
||||
pWav->container = drwav_container_rf64;
|
||||
} else {
|
||||
return DRWAV_FALSE; /* Unknown or unsupported container. */
|
||||
}
|
||||
|
||||
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
drwav_uint8 chunkSizeBytes[4];
|
||||
drwav_uint8 wave[4];
|
||||
|
||||
@@ -1866,9 +1870,15 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (drwav__bytes_to_u32(chunkSizeBytes) < 36) {
|
||||
return DRWAV_FALSE; /* Chunk size should always be at least 36 bytes. */
|
||||
}
|
||||
} else {
|
||||
if (drwav__bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
|
||||
return DRWAV_FALSE; /* Chunk size should always be set to -1/0xFFFFFFFF for RF64. The actual size is retrieved later. */
|
||||
}
|
||||
}
|
||||
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
|
||||
return DRWAV_FALSE;
|
||||
@@ -1900,6 +1910,54 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
}
|
||||
|
||||
|
||||
/* For RF64, the "ds64" chunk must come next, before the "fmt " chunk. */
|
||||
if (pWav->container == drwav_container_rf64) {
|
||||
drwav_uint8 sizeBytes[8];
|
||||
drwav_uint64 bytesRemainingInChunk;
|
||||
drwav_chunk_header header;
|
||||
drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
|
||||
if (result != DRWAV_SUCCESS) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
|
||||
if (!drwav__fourcc_equal(header.id.fourcc, "ds64")) {
|
||||
return DRWAV_FALSE; /* Expecting "ds64". */
|
||||
}
|
||||
|
||||
bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
|
||||
|
||||
/* We don't care about the size of the RIFF chunk - skip it. */
|
||||
if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
cursor += 8;
|
||||
|
||||
|
||||
/* Next 8 bytes is the size of the "data" chunk. */
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
dataChunkSize = drwav__bytes_to_u64(sizeBytes);
|
||||
|
||||
|
||||
/* Next 8 bytes is the same count which we would usually derived from the FACT chunk if it was available. */
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
sampleCountFromFactChunk = drwav__bytes_to_u64(sizeBytes);
|
||||
|
||||
|
||||
/* Skip over everything else. */
|
||||
if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
cursor += bytesRemainingInChunk;
|
||||
}
|
||||
|
||||
|
||||
/* The next bytes should be the "fmt " chunk. */
|
||||
if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
|
||||
return DRWAV_FALSE; /* Failed to read the "fmt " chunk. */
|
||||
@@ -1921,9 +1979,6 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
}
|
||||
|
||||
|
||||
|
||||
sampleCountFromFactChunk = 0;
|
||||
|
||||
/*
|
||||
We need to enumerate over each chunk for two reasons:
|
||||
1) The "data" chunk may not be the next one
|
||||
@@ -1932,7 +1987,6 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
In order to correctly report each chunk back to the client we will need to keep looping until the end of the file.
|
||||
*/
|
||||
foundDataChunk = DRWAV_FALSE;
|
||||
dataChunkSize = 0;
|
||||
|
||||
/* The next chunk we care about is the "data" chunk. This is not necessarily the next chunk so we'll need to loop. */
|
||||
for (;;)
|
||||
@@ -1968,11 +2022,13 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
}
|
||||
|
||||
chunkSize = header.sizeInBytes;
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
if (drwav__fourcc_equal(header.id.fourcc, "data")) {
|
||||
foundDataChunk = DRWAV_TRUE;
|
||||
if (pWav->container != drwav_container_rf64) { /* The data chunk size for RF64 will always be set to 0xFFFFFFFF here. It was set to it's true value earlier. */
|
||||
dataChunkSize = chunkSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
|
||||
foundDataChunk = DRWAV_TRUE;
|
||||
@@ -2011,7 +2067,7 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
sampleCountFromFactChunk = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (pWav->container == drwav_container_w64) {
|
||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
|
||||
return DRWAV_FALSE;
|
||||
@@ -2022,10 +2078,12 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
pWav->dataChunkDataPos = cursor;
|
||||
}
|
||||
}
|
||||
} else if (pWav->container == drwav_container_rf64) {
|
||||
/* We retrieved the sample count from the ds64 chunk earlier so no need to do that here. */
|
||||
}
|
||||
|
||||
/* "smpl" chunk. */
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
if (drwav__fourcc_equal(header.id.fourcc, "smpl")) {
|
||||
drwav_uint8 smplHeaderData[36]; /* 36 = size of the smpl header section, not including the loop data. */
|
||||
if (chunkSize >= sizeof(smplHeaderData)) {
|
||||
@@ -2193,13 +2251,12 @@ DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_
|
||||
|
||||
static drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
drwav_uint32 dataSubchunkPaddingSize = drwav__chunk_padding_size_riff(dataChunkSize);
|
||||
|
||||
if (dataChunkSize <= (0xFFFFFFFFUL - 36 - dataSubchunkPaddingSize)) {
|
||||
return 36 + (drwav_uint32)(dataChunkSize + dataSubchunkPaddingSize);
|
||||
} else {
|
||||
return 0xFFFFFFFF;
|
||||
drwav_uint64 chunkSize = 4 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 24 = "fmt " chunk. */
|
||||
if (chunkSize > 0xFFFFFFFFUL) {
|
||||
chunkSize = 0xFFFFFFFFUL;
|
||||
}
|
||||
|
||||
return (drwav_uint32)chunkSize; /* Safe cast due to the clamp above. */
|
||||
}
|
||||
|
||||
static drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
|
||||
@@ -2223,6 +2280,21 @@ static drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
|
||||
return 24 + dataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
|
||||
}
|
||||
|
||||
static drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
drwav_uint64 chunkSize = 4 + 36 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 36 = "ds64" chunk. 24 = "fmt " chunk. */
|
||||
if (chunkSize > 0xFFFFFFFFUL) {
|
||||
chunkSize = 0xFFFFFFFFUL;
|
||||
}
|
||||
|
||||
return chunkSize;
|
||||
}
|
||||
|
||||
static drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
return dataChunkSize;
|
||||
}
|
||||
|
||||
|
||||
static size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
|
||||
{
|
||||
@@ -2342,23 +2414,42 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
||||
|
||||
/* "RIFF" chunk. */
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
drwav_uint32 chunkSizeRIFF = 36 + (drwav_uint32)initialDataChunkSize; /* +36 = "RIFF"+[RIFF Chunk Size]+"WAVE" + [sizeof "fmt " chunk] */
|
||||
drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize; /* +28 = "WAVE" + [sizeof "fmt " chunk] */
|
||||
runningPos += drwav__write(pWav, "RIFF", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
runningPos += drwav__write(pWav, "RF64", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF); /* Always 0xFFFFFFFF for RF64. Set to a proper value in the "ds64" chunk. */
|
||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||
}
|
||||
|
||||
|
||||
/* "ds64" chunk (RF64 only). */
|
||||
if (pFormat->container == drwav_container_rf64) {
|
||||
drwav_uint32 initialds64ChunkSize = 28; /* 28 = [Size of RIFF (8 bytes)] + [Size of DATA (8 bytes)] + [Sample Count (8 bytes)] + [Table Length (4 bytes)]. Table length always set to 0. */
|
||||
drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize; /* +8 for the ds64 header. */
|
||||
|
||||
runningPos += drwav__write(pWav, "ds64", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize); /* Size of ds64. */
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize); /* Size of RIFF. Set to true value at the end. */
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize); /* Size of DATA. Set to true value at the end. */
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount); /* Sample count. */
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0); /* Table length. Always set to zero in our case since we're not doing any other chunks than "DATA". */
|
||||
}
|
||||
|
||||
|
||||
/* "fmt " chunk. */
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
|
||||
chunkSizeFMT = 16;
|
||||
runningPos += drwav__write(pWav, "fmt ", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
chunkSizeFMT = 40;
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
|
||||
@@ -2378,25 +2469,15 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
||||
drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, "data", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
runningPos += drwav__write(pWav, "data", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF); /* Always set to 0xFFFFFFFF for RF64. The true size of the data chunk is specified in the ds64 chunk. */
|
||||
}
|
||||
|
||||
|
||||
/* Simple validation. */
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
if (runningPos != 20 + chunkSizeFMT + 8) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (runningPos != 40 + chunkSizeFMT + 24) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set some properties for the client's convenience. */
|
||||
pWav->container = pFormat->container;
|
||||
pWav->channels = (drwav_uint16)pFormat->channels;
|
||||
@@ -2440,14 +2521,17 @@ DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pF
|
||||
/* Casting totalSampleCount to drwav_int64 for VC6 compatibility. No issues in practice because nobody is going to exhaust the whole 63 bits. */
|
||||
drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalSampleCount * pFormat->channels * pFormat->bitsPerSample/8.0);
|
||||
drwav_uint64 riffChunkSizeBytes;
|
||||
drwav_uint64 fileSizeBytes;
|
||||
drwav_uint64 fileSizeBytes = 0;
|
||||
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
|
||||
fileSizeBytes = (8 + riffChunkSizeBytes); /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
|
||||
fileSizeBytes = riffChunkSizeBytes;
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes);
|
||||
fileSizeBytes = (8 + riffChunkSizeBytes); /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
|
||||
}
|
||||
|
||||
return fileSizeBytes;
|
||||
@@ -3353,7 +3437,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
drwav_uint32 paddingSize = 0;
|
||||
|
||||
/* Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. */
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
|
||||
} else {
|
||||
paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
|
||||
@@ -3381,7 +3465,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
|
||||
drwav__write_u32ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
} else {
|
||||
} else if (pWav->container == drwav_container_w64) {
|
||||
/* The "RIFF" chunk size. */
|
||||
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
|
||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
||||
@@ -3393,6 +3477,21 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
} else if (pWav->container == drwav_container_rf64) {
|
||||
/* We only need to update the ds64 chunk. The "RIFF" and "data" chunks always have their sizes set to 0xFFFFFFFF for RF64. */
|
||||
int ds64BodyPos = 12 + 8;
|
||||
|
||||
/* The "RIFF" chunk size. */
|
||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
|
||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
||||
}
|
||||
|
||||
/* The "data" chunk size. */
|
||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
|
||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5934,6 +6033,16 @@ two different ways to initialize a drwav object.
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.12.13 - 2020-11-01
|
||||
- Improve compiler support for older versions of GCC.
|
||||
|
||||
v0.12.12 - 2020-09-28
|
||||
- Add support for RF64.
|
||||
- Fix a bug in writing mode where the size of the RIFF chunk incorrectly includes the header section.
|
||||
|
||||
v0.12.11 - 2020-09-08
|
||||
- Fix a compilation error on older compilers.
|
||||
|
||||
v0.12.10 - 2020-08-24
|
||||
- Fix a bug when seeking with ADPCM formats.
|
||||
|
||||
|
||||
+339
-136
@@ -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.
|
||||
miniaudio - v0.10.20 - 2020-10-06
|
||||
miniaudio - v0.10.21 - 2020-10-30
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -3662,6 +3662,137 @@ MA_API const char* ma_get_backend_name(ma_backend backend)
|
||||
}
|
||||
}
|
||||
|
||||
MA_API ma_bool32 ma_is_backend_enabled(ma_backend backend)
|
||||
{
|
||||
/*
|
||||
This looks a little bit gross, but we want all backends to be included in the switch to avoid warnings on some compilers
|
||||
about some enums not being handled by the switch statement.
|
||||
*/
|
||||
switch (backend)
|
||||
{
|
||||
case ma_backend_wasapi:
|
||||
#if defined(MA_HAS_WASAPI)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_dsound:
|
||||
#if defined(MA_HAS_DSOUND)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_winmm:
|
||||
#if defined(MA_HAS_WINMM)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_coreaudio:
|
||||
#if defined(MA_HAS_COREAUDIO)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_sndio:
|
||||
#if defined(MA_HAS_SNDIO)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_audio4:
|
||||
#if defined(MA_HAS_AUDIO4)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_oss:
|
||||
#if defined(MA_HAS_OSS)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_pulseaudio:
|
||||
#if defined(MA_HAS_PULSEAUDIO)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_alsa:
|
||||
#if defined(MA_HAS_ALSA)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_jack:
|
||||
#if defined(MA_HAS_JACK)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_aaudio:
|
||||
#if defined(MA_HAS_AAUDIO)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_opensl:
|
||||
#if defined(MA_HAS_OPENSL)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_webaudio:
|
||||
#if defined(MA_HAS_WEBAUDIO)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
case ma_backend_null:
|
||||
#if defined(MA_HAS_NULL)
|
||||
return MA_TRUE;
|
||||
#else
|
||||
return MA_FALSE;
|
||||
#endif
|
||||
|
||||
default: return MA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
MA_API ma_result ma_get_enabled_backends(ma_backend* pBackends, size_t backendCap, size_t* pBackendCount)
|
||||
{
|
||||
size_t backendCount;
|
||||
size_t iBackend;
|
||||
ma_result result = MA_SUCCESS;
|
||||
|
||||
if (pBackendCount == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
backendCount = 0;
|
||||
|
||||
for (iBackend = 0; iBackend <= ma_backend_null; iBackend += 1) {
|
||||
ma_backend backend = (ma_backend)iBackend;
|
||||
|
||||
if (ma_is_backend_enabled(backend)) {
|
||||
/* The backend is enabled. Try adding it to the list. If there's no room, MA_NO_SPACE needs to be returned. */
|
||||
if (backendCount == backendCap) {
|
||||
result = MA_NO_SPACE;
|
||||
break;
|
||||
} else {
|
||||
pBackends[backendCount] = backend;
|
||||
backendCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pBackendCount != NULL) {
|
||||
*pBackendCount = backendCount;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MA_API ma_bool32 ma_is_loopback_supported(ma_backend backend)
|
||||
{
|
||||
switch (backend)
|
||||
@@ -5107,6 +5238,10 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
||||
{
|
||||
ma_result result = MA_SUCCESS;
|
||||
ma_bool32 exitLoop = MA_FALSE;
|
||||
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
@@ -5128,10 +5263,6 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
||||
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
|
||||
|
||||
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
|
||||
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
ma_uint32 capturedDeviceFramesRemaining;
|
||||
ma_uint32 capturedDeviceFramesProcessed;
|
||||
ma_uint32 capturedDeviceFramesToProcess;
|
||||
@@ -5212,26 +5343,23 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
||||
|
||||
case ma_device_type_capture:
|
||||
{
|
||||
/* We read in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint8 intermediaryBuffer[8192];
|
||||
ma_uint32 intermediaryBufferSizeInFrames = sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesReadThisPeriod = 0;
|
||||
while (framesReadThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
||||
if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
|
||||
framesToReadThisIteration = intermediaryBufferSizeInFrames;
|
||||
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
|
||||
framesToReadThisIteration = capturedDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
result = ma_device_read__null(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
|
||||
result = ma_device_read__null(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
|
||||
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
|
||||
|
||||
framesReadThisPeriod += framesProcessed;
|
||||
}
|
||||
@@ -5240,21 +5368,19 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
||||
case ma_device_type_playback:
|
||||
{
|
||||
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint8 intermediaryBuffer[8192];
|
||||
ma_uint32 intermediaryBufferSizeInFrames = sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesWrittenThisPeriod = 0;
|
||||
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
||||
if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
|
||||
framesToWriteThisIteration = intermediaryBufferSizeInFrames;
|
||||
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
|
||||
framesToWriteThisIteration = playbackDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
|
||||
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
|
||||
|
||||
result = ma_device_write__null(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
|
||||
result = ma_device_write__null(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
@@ -7866,7 +7992,7 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice)
|
||||
In loopback mode it's possible for WaitForSingleObject() to get stuck in a deadlock when nothing is being played. When nothing
|
||||
is being played, the event is never signalled internally by WASAPI which means we will deadlock when stopping the device.
|
||||
*/
|
||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_duplex) {
|
||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
|
||||
SetEvent((HANDLE)pDevice->wasapi.hEventCapture);
|
||||
}
|
||||
|
||||
@@ -11264,6 +11390,10 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
||||
{
|
||||
ma_result result = MA_SUCCESS;
|
||||
ma_bool32 exitLoop = MA_FALSE;
|
||||
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
@@ -11307,10 +11437,6 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
||||
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
|
||||
|
||||
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
|
||||
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
ma_uint32 capturedDeviceFramesRemaining;
|
||||
ma_uint32 capturedDeviceFramesProcessed;
|
||||
ma_uint32 capturedDeviceFramesToProcess;
|
||||
@@ -11391,25 +11517,23 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
||||
case ma_device_type_capture:
|
||||
{
|
||||
/* We read in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint8 intermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 intermediaryBufferSizeInFrames = sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesReadThisPeriod = 0;
|
||||
while (framesReadThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
||||
if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
|
||||
framesToReadThisIteration = intermediaryBufferSizeInFrames;
|
||||
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
|
||||
framesToReadThisIteration = capturedDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
result = ma_device_read__winmm(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
|
||||
result = ma_device_read__winmm(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
|
||||
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
|
||||
|
||||
framesReadThisPeriod += framesProcessed;
|
||||
}
|
||||
@@ -11418,21 +11542,19 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
||||
case ma_device_type_playback:
|
||||
{
|
||||
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint8 intermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 intermediaryBufferSizeInFrames = sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesWrittenThisPeriod = 0;
|
||||
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
||||
if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
|
||||
framesToWriteThisIteration = intermediaryBufferSizeInFrames;
|
||||
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
|
||||
framesToWriteThisIteration = playbackDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
|
||||
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
|
||||
|
||||
result = ma_device_write__winmm(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
|
||||
result = ma_device_write__winmm(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
@@ -17136,7 +17258,14 @@ static ma_result ma_get_channel_map_from_AudioChannelLayout(AudioChannelLayout*
|
||||
Need to use the tag to determine the channel map. For now I'm just assuming a default channel map, but later on this should
|
||||
be updated to determine the mapping based on the tag.
|
||||
*/
|
||||
UInt32 channelCount = ma_min(AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag), channelMapCap);
|
||||
UInt32 channelCount;
|
||||
|
||||
/* Our channel map retrieval APIs below take 32-bit integers, so we'll want to clamp the channel map capacity. */
|
||||
if (channelMapCap > 0xFFFFFFFF) {
|
||||
channelMapCap = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
channelCount = ma_min(AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag), (UInt32)channelMapCap);
|
||||
|
||||
switch (pChannelLayout->mChannelLayoutTag)
|
||||
{
|
||||
@@ -17742,7 +17871,7 @@ static ma_result ma_find_AudioObjectID(ma_context* pContext, ma_device_type devi
|
||||
}
|
||||
|
||||
|
||||
static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_bool32 usingDefaultFormat, ma_bool32 usingDefaultChannels, ma_bool32 usingDefaultSampleRate, AudioStreamBasicDescription* pFormat)
|
||||
static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_bool32 usingDefaultFormat, ma_bool32 usingDefaultChannels, ma_bool32 usingDefaultSampleRate, const AudioStreamBasicDescription* pOrigFormat, AudioStreamBasicDescription* pFormat)
|
||||
{
|
||||
UInt32 deviceFormatDescriptionCount;
|
||||
AudioStreamRangedDescription* pDeviceFormatDescriptions;
|
||||
@@ -17761,41 +17890,21 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec
|
||||
|
||||
desiredSampleRate = sampleRate;
|
||||
if (usingDefaultSampleRate) {
|
||||
/*
|
||||
When using the device's default sample rate, we get the highest priority standard rate supported by the device. Otherwise
|
||||
we just use the pre-set rate.
|
||||
*/
|
||||
ma_uint32 iStandardRate;
|
||||
for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
|
||||
ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
|
||||
ma_bool32 foundRate = MA_FALSE;
|
||||
UInt32 iDeviceRate;
|
||||
|
||||
for (iDeviceRate = 0; iDeviceRate < deviceFormatDescriptionCount; ++iDeviceRate) {
|
||||
ma_uint32 deviceRate = (ma_uint32)pDeviceFormatDescriptions[iDeviceRate].mFormat.mSampleRate;
|
||||
|
||||
if (deviceRate == standardRate) {
|
||||
desiredSampleRate = standardRate;
|
||||
foundRate = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundRate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
desiredSampleRate = pOrigFormat->mSampleRate;
|
||||
}
|
||||
|
||||
desiredChannelCount = channels;
|
||||
if (usingDefaultChannels) {
|
||||
ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &desiredChannelCount); /* <-- Not critical if this fails. */
|
||||
desiredChannelCount = pOrigFormat->mChannelsPerFrame;
|
||||
}
|
||||
|
||||
desiredFormat = format;
|
||||
if (usingDefaultFormat) {
|
||||
result = ma_format_from_AudioStreamBasicDescription(pOrigFormat, &desiredFormat);
|
||||
if (result != MA_SUCCESS || desiredFormat == ma_format_unknown) {
|
||||
desiredFormat = g_maFormatPriorities[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If we get here it means we don't have an exact match to what the client is asking for. We'll need to find the closest one. The next
|
||||
@@ -18652,6 +18761,8 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex
|
||||
|
||||
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||
{
|
||||
/* Don't do anything if we've already initializd device tracking. */
|
||||
if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
@@ -18663,6 +18774,9 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex
|
||||
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
|
||||
g_DeviceTrackingInitCounter_CoreAudio += 1;
|
||||
}
|
||||
}
|
||||
ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||
|
||||
@@ -18675,6 +18789,9 @@ static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pCont
|
||||
|
||||
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||
{
|
||||
g_DeviceTrackingInitCounter_CoreAudio -= 1;
|
||||
|
||||
if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
@@ -18685,12 +18802,14 @@ static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pCont
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
|
||||
/* At this point there should be no tracked devices. If so there's an error somewhere. */
|
||||
MA_ASSERT(g_ppTrackedDevices_CoreAudio == NULL);
|
||||
MA_ASSERT(g_TrackedDeviceCount_CoreAudio == 0);
|
||||
/* At this point there should be no tracked devices. If not there's an error somewhere. */
|
||||
if (g_ppTrackedDevices_CoreAudio != NULL) {
|
||||
ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "You have uninitialized all contexts while an associated device is still active.", MA_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio);
|
||||
}
|
||||
}
|
||||
ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||
|
||||
return MA_SUCCESS;
|
||||
@@ -19057,26 +19176,30 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
||||
AudioStreamBasicDescription origFormat;
|
||||
UInt32 origFormatSize;
|
||||
|
||||
result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, pData->usingDefaultFormat, pData->usingDefaultChannels, pData->usingDefaultSampleRate, &bestFormat);
|
||||
if (result != MA_SUCCESS) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* From what I can see, Apple's documentation implies that we should keep the sample rate consistent. */
|
||||
origFormatSize = sizeof(origFormat);
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &origFormat, &origFormatSize);
|
||||
} else {
|
||||
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &origFormat, &origFormatSize);
|
||||
}
|
||||
|
||||
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &origFormat, &origFormatSize);
|
||||
if (status != noErr) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, pData->usingDefaultFormat, pData->usingDefaultChannels, pData->usingDefaultSampleRate, &origFormat, &bestFormat);
|
||||
if (result != MA_SUCCESS) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
Update 2020-10-10:
|
||||
|
||||
I cannot remember where I read this in the documentation and I cannot find it again. For now I'm going to remove this
|
||||
and see what the feedback from the community is like. If this results in issues we can add it back in again. The idea
|
||||
is that the closest sample rate natively supported by the backend to the requested sample rate should be used if possible.
|
||||
*/
|
||||
#if 0
|
||||
/* From what I can see, Apple's documentation implies that we should keep the sample rate consistent. */
|
||||
bestFormat.mSampleRate = origFormat.mSampleRate;
|
||||
#endif
|
||||
|
||||
status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
|
||||
if (status != noErr) {
|
||||
@@ -31827,7 +31950,7 @@ static ma_result ma_resampler_process_pcm_frames__seek__linear(ma_resampler* pRe
|
||||
static ma_result ma_resampler_process_pcm_frames__seek__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
|
||||
{
|
||||
/* The generic seek method is implemented in on top of ma_resampler_process_pcm_frames__read() by just processing into a dummy buffer. */
|
||||
float devnull[8192];
|
||||
float devnull[4096];
|
||||
ma_uint64 totalOutputFramesToProcess;
|
||||
ma_uint64 totalOutputFramesProcessed;
|
||||
ma_uint64 totalInputFramesProcessed;
|
||||
@@ -36162,7 +36285,7 @@ MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc,
|
||||
{
|
||||
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
|
||||
|
||||
if (pBytesWritten == NULL) {
|
||||
if (pBytesWritten != NULL) {
|
||||
*pBytesWritten = 0;
|
||||
}
|
||||
|
||||
@@ -36399,9 +36522,13 @@ static ma_result ma_default_vfs_read__win32(ma_vfs* pVFS, ma_vfs_file file, void
|
||||
}
|
||||
|
||||
readResult = ReadFile((HANDLE)file, ma_offset_ptr(pDst, totalBytesRead), bytesToRead, &bytesRead, NULL);
|
||||
if (readResult == 1 && bytesRead == 0) {
|
||||
break; /* EOF */
|
||||
}
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
|
||||
if (bytesRead < bytesToRead || (readResult == 1 && bytesRead == 0)) {
|
||||
if (bytesRead < bytesToRead) {
|
||||
break; /* EOF */
|
||||
}
|
||||
|
||||
@@ -36448,7 +36575,7 @@ static ma_result ma_default_vfs_write__win32(ma_vfs* pVFS, ma_vfs_file file, con
|
||||
}
|
||||
}
|
||||
|
||||
if (pBytesWritten == NULL) {
|
||||
if (pBytesWritten != NULL) {
|
||||
*pBytesWritten = totalBytesWritten;
|
||||
}
|
||||
|
||||
@@ -36910,7 +37037,7 @@ extern "C" {
|
||||
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
|
||||
#define DRWAV_VERSION_MAJOR 0
|
||||
#define DRWAV_VERSION_MINOR 12
|
||||
#define DRWAV_VERSION_REVISION 10
|
||||
#define DRWAV_VERSION_REVISION 12
|
||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||
#include <stddef.h>
|
||||
typedef signed char drwav_int8;
|
||||
@@ -37049,7 +37176,8 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
drwav_container_riff,
|
||||
drwav_container_w64
|
||||
drwav_container_w64,
|
||||
drwav_container_rf64
|
||||
} drwav_container;
|
||||
typedef struct
|
||||
{
|
||||
@@ -37282,7 +37410,7 @@ extern "C" {
|
||||
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 12
|
||||
#define DRFLAC_VERSION_REVISION 19
|
||||
#define DRFLAC_VERSION_REVISION 20
|
||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||
#include <stddef.h>
|
||||
typedef signed char drflac_int8;
|
||||
@@ -37643,7 +37771,7 @@ extern "C" {
|
||||
#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
|
||||
#define DRMP3_VERSION_MAJOR 0
|
||||
#define DRMP3_VERSION_MINOR 6
|
||||
#define DRMP3_VERSION_REVISION 16
|
||||
#define DRMP3_VERSION_REVISION 17
|
||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||
#include <stddef.h>
|
||||
typedef signed char drmp3_int8;
|
||||
@@ -41684,14 +41812,14 @@ static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
|
||||
#error "This compiler does not support the byte swap intrinsic."
|
||||
#endif
|
||||
#else
|
||||
return ((n & (drwav_uint64)0xFF00000000000000) >> 56) |
|
||||
((n & (drwav_uint64)0x00FF000000000000) >> 40) |
|
||||
((n & (drwav_uint64)0x0000FF0000000000) >> 24) |
|
||||
((n & (drwav_uint64)0x000000FF00000000) >> 8) |
|
||||
((n & (drwav_uint64)0x00000000FF000000) << 8) |
|
||||
((n & (drwav_uint64)0x0000000000FF0000) << 24) |
|
||||
((n & (drwav_uint64)0x000000000000FF00) << 40) |
|
||||
((n & (drwav_uint64)0x00000000000000FF) << 56);
|
||||
return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
|
||||
((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
|
||||
((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
|
||||
((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
|
||||
((n & ((drwav_uint64)0xFF000000 )) << 8) |
|
||||
((n & ((drwav_uint64)0x00FF0000 )) << 24) |
|
||||
((n & ((drwav_uint64)0x0000FF00 )) << 40) |
|
||||
((n & ((drwav_uint64)0x000000FF )) << 56);
|
||||
#endif
|
||||
}
|
||||
static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
|
||||
@@ -41927,7 +42055,7 @@ static drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 sam
|
||||
static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
|
||||
static drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
|
||||
{
|
||||
if (container == drwav_container_riff) {
|
||||
if (container == drwav_container_riff || container == drwav_container_rf64) {
|
||||
drwav_uint8 sizeInBytes[4];
|
||||
if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
|
||||
return DRWAV_AT_END;
|
||||
@@ -41996,7 +42124,7 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
||||
if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
while ((container == drwav_container_riff && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||
while (((container == drwav_container_riff || container == drwav_container_rf64) && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||
if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -42005,7 +42133,7 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
if (container == drwav_container_riff) {
|
||||
if (container == drwav_container_riff || container == drwav_container_rf64) {
|
||||
if (!drwav__fourcc_equal(header.id.fourcc, "fmt ")) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -42138,9 +42266,9 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
drwav_uint8 riff[4];
|
||||
drwav_fmt fmt;
|
||||
unsigned short translatedFormatTag;
|
||||
drwav_uint64 sampleCountFromFactChunk;
|
||||
drwav_bool32 foundDataChunk;
|
||||
drwav_uint64 dataChunkSize;
|
||||
drwav_uint64 dataChunkSize = 0;
|
||||
drwav_uint64 sampleCountFromFactChunk = 0;
|
||||
drwav_uint64 chunkSize;
|
||||
cursor = 0;
|
||||
sequential = (flags & DRWAV_SEQUENTIAL) != 0;
|
||||
@@ -42161,18 +42289,26 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
} else if (drwav__fourcc_equal(riff, "RF64")) {
|
||||
pWav->container = drwav_container_rf64;
|
||||
} else {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
drwav_uint8 chunkSizeBytes[4];
|
||||
drwav_uint8 wave[4];
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (drwav__bytes_to_u32(chunkSizeBytes) < 36) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (drwav__bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -42195,6 +42331,38 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
}
|
||||
if (pWav->container == drwav_container_rf64) {
|
||||
drwav_uint8 sizeBytes[8];
|
||||
drwav_uint64 bytesRemainingInChunk;
|
||||
drwav_chunk_header header;
|
||||
drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
|
||||
if (result != DRWAV_SUCCESS) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
if (!drwav__fourcc_equal(header.id.fourcc, "ds64")) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
|
||||
if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
cursor += 8;
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
dataChunkSize = drwav__bytes_to_u64(sizeBytes);
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
bytesRemainingInChunk -= 8;
|
||||
sampleCountFromFactChunk = drwav__bytes_to_u64(sizeBytes);
|
||||
if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
cursor += bytesRemainingInChunk;
|
||||
}
|
||||
if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
@@ -42208,9 +42376,7 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
|
||||
translatedFormatTag = drwav__bytes_to_u16(fmt.subFormat + 0);
|
||||
}
|
||||
sampleCountFromFactChunk = 0;
|
||||
foundDataChunk = DRWAV_FALSE;
|
||||
dataChunkSize = 0;
|
||||
for (;;)
|
||||
{
|
||||
drwav_chunk_header header;
|
||||
@@ -42234,11 +42400,13 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
pWav->dataChunkDataPos = cursor;
|
||||
}
|
||||
chunkSize = header.sizeInBytes;
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
if (drwav__fourcc_equal(header.id.fourcc, "data")) {
|
||||
foundDataChunk = DRWAV_TRUE;
|
||||
if (pWav->container != drwav_container_rf64) {
|
||||
dataChunkSize = chunkSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
|
||||
foundDataChunk = DRWAV_TRUE;
|
||||
@@ -42264,7 +42432,7 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
sampleCountFromFactChunk = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (pWav->container == drwav_container_w64) {
|
||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
|
||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
|
||||
return DRWAV_FALSE;
|
||||
@@ -42274,8 +42442,9 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
||||
pWav->dataChunkDataPos = cursor;
|
||||
}
|
||||
}
|
||||
} else if (pWav->container == drwav_container_rf64) {
|
||||
}
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
if (drwav__fourcc_equal(header.id.fourcc, "smpl")) {
|
||||
drwav_uint8 smplHeaderData[36];
|
||||
if (chunkSize >= sizeof(smplHeaderData)) {
|
||||
@@ -42394,12 +42563,11 @@ DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_
|
||||
}
|
||||
static drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
drwav_uint32 dataSubchunkPaddingSize = drwav__chunk_padding_size_riff(dataChunkSize);
|
||||
if (dataChunkSize <= (0xFFFFFFFFUL - 36 - dataSubchunkPaddingSize)) {
|
||||
return 36 + (drwav_uint32)(dataChunkSize + dataSubchunkPaddingSize);
|
||||
} else {
|
||||
return 0xFFFFFFFF;
|
||||
drwav_uint64 chunkSize = 4 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
|
||||
if (chunkSize > 0xFFFFFFFFUL) {
|
||||
chunkSize = 0xFFFFFFFFUL;
|
||||
}
|
||||
return (drwav_uint32)chunkSize;
|
||||
}
|
||||
static drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
@@ -42418,6 +42586,18 @@ static drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
return 24 + dataChunkSize;
|
||||
}
|
||||
static drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
drwav_uint64 chunkSize = 4 + 36 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
|
||||
if (chunkSize > 0xFFFFFFFFUL) {
|
||||
chunkSize = 0xFFFFFFFFUL;
|
||||
}
|
||||
return chunkSize;
|
||||
}
|
||||
static drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
|
||||
{
|
||||
return dataChunkSize;
|
||||
}
|
||||
static size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
|
||||
{
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
@@ -42498,21 +42678,35 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
||||
}
|
||||
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
drwav_uint32 chunkSizeRIFF = 36 + (drwav_uint32)initialDataChunkSize;
|
||||
drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, "RIFF", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
runningPos += drwav__write(pWav, "RF64", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
|
||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||
}
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
if (pFormat->container == drwav_container_rf64) {
|
||||
drwav_uint32 initialds64ChunkSize = 28;
|
||||
drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, "ds64", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0);
|
||||
}
|
||||
if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
|
||||
chunkSizeFMT = 16;
|
||||
runningPos += drwav__write(pWav, "fmt ", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
chunkSizeFMT = 40;
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
|
||||
@@ -42528,19 +42722,13 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
||||
drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, "data", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
|
||||
runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
|
||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
|
||||
}
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
if (runningPos != 20 + chunkSizeFMT + 8) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (runningPos != 40 + chunkSizeFMT + 24) {
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
runningPos += drwav__write(pWav, "data", 4);
|
||||
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
|
||||
}
|
||||
pWav->container = pFormat->container;
|
||||
pWav->channels = (drwav_uint16)pFormat->channels;
|
||||
@@ -42574,13 +42762,16 @@ DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pF
|
||||
{
|
||||
drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalSampleCount * pFormat->channels * pFormat->bitsPerSample/8.0);
|
||||
drwav_uint64 riffChunkSizeBytes;
|
||||
drwav_uint64 fileSizeBytes;
|
||||
drwav_uint64 fileSizeBytes = 0;
|
||||
if (pFormat->container == drwav_container_riff) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
|
||||
fileSizeBytes = (8 + riffChunkSizeBytes);
|
||||
} else {
|
||||
} else if (pFormat->container == drwav_container_w64) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
|
||||
fileSizeBytes = riffChunkSizeBytes;
|
||||
} else if (pFormat->container == drwav_container_rf64) {
|
||||
riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes);
|
||||
fileSizeBytes = (8 + riffChunkSizeBytes);
|
||||
}
|
||||
return fileSizeBytes;
|
||||
}
|
||||
@@ -43352,7 +43543,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
}
|
||||
if (pWav->onWrite != NULL) {
|
||||
drwav_uint32 paddingSize = 0;
|
||||
if (pWav->container == drwav_container_riff) {
|
||||
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
|
||||
paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
|
||||
} else {
|
||||
paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
|
||||
@@ -43371,7 +43562,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
|
||||
drwav__write_u32ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
} else {
|
||||
} else if (pWav->container == drwav_container_w64) {
|
||||
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
|
||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
||||
@@ -43380,6 +43571,16 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
} else if (pWav->container == drwav_container_rf64) {
|
||||
int ds64BodyPos = 12 + 8;
|
||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
|
||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
||||
}
|
||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
|
||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
|
||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pWav->isSequentialWrite) {
|
||||
@@ -45592,14 +45793,14 @@ static DRFLAC_INLINE drflac_uint64 drflac__swap_endian_uint64(drflac_uint64 n)
|
||||
#error "This compiler does not support the byte swap intrinsic."
|
||||
#endif
|
||||
#else
|
||||
return ((n & (drflac_uint64)0xFF00000000000000) >> 56) |
|
||||
((n & (drflac_uint64)0x00FF000000000000) >> 40) |
|
||||
((n & (drflac_uint64)0x0000FF0000000000) >> 24) |
|
||||
((n & (drflac_uint64)0x000000FF00000000) >> 8) |
|
||||
((n & (drflac_uint64)0x00000000FF000000) << 8) |
|
||||
((n & (drflac_uint64)0x0000000000FF0000) << 24) |
|
||||
((n & (drflac_uint64)0x000000000000FF00) << 40) |
|
||||
((n & (drflac_uint64)0x00000000000000FF) << 56);
|
||||
return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
|
||||
((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
|
||||
((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
|
||||
((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
|
||||
((n & ((drflac_uint64)0xFF000000 )) << 8) |
|
||||
((n & ((drflac_uint64)0x00FF0000 )) << 24) |
|
||||
((n & ((drflac_uint64)0x0000FF00 )) << 40) |
|
||||
((n & ((drflac_uint64)0x000000FF )) << 56);
|
||||
#endif
|
||||
}
|
||||
static DRFLAC_INLINE drflac_uint16 drflac__be2host_16(drflac_uint16 n)
|
||||
@@ -53483,6 +53684,8 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
||||
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define DRMP3_HAVE_ARMV6 0
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
miniaudio - v0.10.20 - 2020-10-06
|
||||
miniaudio - v0.10.21 - 2020-10-30
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -20,7 +20,7 @@ extern "C" {
|
||||
|
||||
#define MA_VERSION_MAJOR 0
|
||||
#define MA_VERSION_MINOR 10
|
||||
#define MA_VERSION_REVISION 20
|
||||
#define MA_VERSION_REVISION 21
|
||||
#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__)
|
||||
@@ -1525,6 +1525,8 @@ typedef enum
|
||||
ma_backend_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
|
||||
} ma_backend;
|
||||
|
||||
#define MA_BACKEND_COUNT (ma_backend_null+1)
|
||||
|
||||
|
||||
/*
|
||||
The callback for processing audio data from the device.
|
||||
@@ -2474,7 +2476,7 @@ struct ma_device
|
||||
ma_uint32 currentPeriodFramesRemainingPlayback;
|
||||
ma_uint32 currentPeriodFramesRemainingCapture;
|
||||
ma_uint64 lastProcessedFramePlayback;
|
||||
ma_uint32 lastProcessedFrameCapture;
|
||||
ma_uint64 lastProcessedFrameCapture;
|
||||
ma_bool32 isStarted;
|
||||
} null_device;
|
||||
#endif
|
||||
@@ -3674,6 +3676,84 @@ Retrieves a friendly name for a backend.
|
||||
*/
|
||||
MA_API const char* ma_get_backend_name(ma_backend backend);
|
||||
|
||||
/*
|
||||
Determines whether or not the given backend is available by the compilation environment.
|
||||
*/
|
||||
MA_API ma_bool32 ma_is_backend_enabled(ma_backend backend);
|
||||
|
||||
/*
|
||||
Retrieves compile-time enabled backends.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pBackends(out, optional)
|
||||
A pointer to the buffer that will receive the enabled backends. Set to NULL to retrieve the backend count. Setting
|
||||
the capacity of the buffer to `MA_BUFFER_COUNT` will guarantee it's large enough for all backends.
|
||||
|
||||
backendCap(in)
|
||||
The capacity of the `pBackends` buffer.
|
||||
|
||||
pBackendCount(out)
|
||||
A pointer to the variable that will receive the enabled backend count.
|
||||
|
||||
|
||||
Return Value
|
||||
------------
|
||||
MA_SUCCESS if successful.
|
||||
MA_INVALID_ARGS if `pBackendCount` is NULL.
|
||||
MA_NO_SPACE if the capacity of `pBackends` is not large enough.
|
||||
|
||||
If `MA_NO_SPACE` is returned, the `pBackends` buffer will be filled with `*pBackendCount` values.
|
||||
|
||||
|
||||
Thread Safety
|
||||
-------------
|
||||
Safe.
|
||||
|
||||
|
||||
Callback Safety
|
||||
---------------
|
||||
Safe.
|
||||
|
||||
|
||||
Remarks
|
||||
-------
|
||||
If you want to retrieve the number of backends so you can determine the capacity of `pBackends` buffer, you can call
|
||||
this function with `pBackends` set to NULL.
|
||||
|
||||
This will also enumerate the null backend. If you don't want to include this you need to check for `ma_backend_null`
|
||||
when you enumerate over the returned backends and handle it appropriately. Alternatively, you can disable it at
|
||||
compile time with `MA_NO_NULL`.
|
||||
|
||||
The returned backends are determined based on compile time settings, not the platform it's currently running on. For
|
||||
example, PulseAudio will be returned if it was enabled at compile time, even when the user doesn't actually have
|
||||
PulseAudio installed.
|
||||
|
||||
|
||||
Example 1
|
||||
---------
|
||||
The example below retrieves the enabled backend count using a fixed sized buffer allocated on the stack. The buffer is
|
||||
given a capacity of `MA_BACKEND_COUNT` which will guarantee it'll be large enough to store all available backends.
|
||||
Since `MA_BACKEND_COUNT` is always a relatively small value, this should be suitable for most scenarios.
|
||||
|
||||
```
|
||||
ma_backend enabledBackends[MA_BACKEND_COUNT];
|
||||
size_t enabledBackendCount;
|
||||
|
||||
result = ma_get_enabled_backends(enabledBackends, MA_BACKEND_COUNT, &enabledBackendCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
// Failed to retrieve enabled backends. Should never happen in this example since all inputs are valid.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
ma_is_backend_enabled()
|
||||
*/
|
||||
MA_API ma_result ma_get_enabled_backends(ma_backend* pBackends, size_t backendCap, size_t* pBackendCount);
|
||||
|
||||
/*
|
||||
Determines whether or not loopback mode is support by a backend.
|
||||
*/
|
||||
|
||||
@@ -6,21 +6,20 @@
|
||||
#define RANDOM_PREFIX ma_speex
|
||||
#include "thirdparty/speex_resampler.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(__clang__)
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned __int64 spx_uint64_t;
|
||||
#else
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wc++11-long-long"
|
||||
#endif
|
||||
typedef unsigned __int64 spx_uint64_t;
|
||||
#if defined(__clang__)
|
||||
#endif
|
||||
typedef unsigned long long spx_uint64_t;
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#else
|
||||
#define MA_HAS_STDINT
|
||||
#include <stdint.h>
|
||||
typedef uint64_t spx_uint64_t;
|
||||
#endif
|
||||
|
||||
int ma_speex_resampler_get_required_input_frame_count(SpeexResamplerState* st, spx_uint64_t out_len, spx_uint64_t* in_len);
|
||||
@@ -50,14 +49,14 @@ int ma_speex_resampler_get_expected_output_frame_count(SpeexResamplerState* st,
|
||||
#pragma warning(disable:4244) /* conversion from 'x' to 'y', possible loss of data */
|
||||
#pragma warning(disable:4018) /* signed/unsigned mismatch */
|
||||
#pragma warning(disable:4706) /* assignment within conditional expression */
|
||||
#else
|
||||
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare" /* comparison between signed and unsigned integer expressions */
|
||||
#endif
|
||||
#include "thirdparty/resample.c"
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
+1243
-1141
File diff suppressed because it is too large
Load Diff
@@ -240,10 +240,14 @@ ma_result print_device_info(ma_context* pContext, ma_device_type deviceType, con
|
||||
|
||||
MA_ASSERT(pDeviceInfo != NULL);
|
||||
|
||||
#if 1
|
||||
result = ma_context_get_device_info(pContext, deviceType, &pDeviceInfo->id, ma_share_mode_shared, &detailedDeviceInfo);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
detailedDeviceInfo = *pDeviceInfo;
|
||||
#endif
|
||||
|
||||
printf("%s\n", pDeviceInfo->name);
|
||||
printf(" Default: %s\n", (detailedDeviceInfo._private.isDefault) ? "Yes" : "No");
|
||||
@@ -579,5 +583,10 @@ done:
|
||||
ma_encoder_uninit(&g_State.encoder);
|
||||
}
|
||||
|
||||
|
||||
printf("Press Enter to quit...");
|
||||
getchar();
|
||||
getchar();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user