mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
Version 0.10.21
This commit is contained in:
+359
-156
@@ -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.10.20 - 2020-10-06
|
miniaudio - v0.10.21 - 2020-10-30
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
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)
|
MA_API ma_bool32 ma_is_loopback_supported(ma_backend backend)
|
||||||
{
|
{
|
||||||
switch (backend)
|
switch (backend)
|
||||||
@@ -5107,6 +5238,10 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
|||||||
{
|
{
|
||||||
ma_result result = MA_SUCCESS;
|
ma_result result = MA_SUCCESS;
|
||||||
ma_bool32 exitLoop = MA_FALSE;
|
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);
|
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);
|
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
|
||||||
|
|
||||||
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
|
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 capturedDeviceFramesRemaining;
|
||||||
ma_uint32 capturedDeviceFramesProcessed;
|
ma_uint32 capturedDeviceFramesProcessed;
|
||||||
ma_uint32 capturedDeviceFramesToProcess;
|
ma_uint32 capturedDeviceFramesToProcess;
|
||||||
@@ -5212,26 +5343,23 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
|||||||
|
|
||||||
case ma_device_type_capture:
|
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 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||||
ma_uint32 framesReadThisPeriod = 0;
|
ma_uint32 framesReadThisPeriod = 0;
|
||||||
while (framesReadThisPeriod < periodSizeInFrames) {
|
while (framesReadThisPeriod < periodSizeInFrames) {
|
||||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
||||||
ma_uint32 framesProcessed;
|
ma_uint32 framesProcessed;
|
||||||
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
||||||
if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
|
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
|
||||||
framesToReadThisIteration = intermediaryBufferSizeInFrames;
|
framesToReadThisIteration = capturedDeviceDataCapInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ma_device_read__null(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
|
result = ma_device_read__null(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
|
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
|
||||||
|
|
||||||
framesReadThisPeriod += framesProcessed;
|
framesReadThisPeriod += framesProcessed;
|
||||||
}
|
}
|
||||||
@@ -5240,21 +5368,19 @@ static ma_result ma_device_main_loop__null(ma_device* pDevice)
|
|||||||
case ma_device_type_playback:
|
case ma_device_type_playback:
|
||||||
{
|
{
|
||||||
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
/* 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 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||||
ma_uint32 framesWrittenThisPeriod = 0;
|
ma_uint32 framesWrittenThisPeriod = 0;
|
||||||
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
||||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
||||||
ma_uint32 framesProcessed;
|
ma_uint32 framesProcessed;
|
||||||
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
||||||
if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
|
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
|
||||||
framesToWriteThisIteration = intermediaryBufferSizeInFrames;
|
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) {
|
if (result != MA_SUCCESS) {
|
||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break;
|
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
|
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.
|
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);
|
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_result result = MA_SUCCESS;
|
||||||
ma_bool32 exitLoop = MA_FALSE;
|
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);
|
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);
|
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
|
||||||
|
|
||||||
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
|
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 capturedDeviceFramesRemaining;
|
||||||
ma_uint32 capturedDeviceFramesProcessed;
|
ma_uint32 capturedDeviceFramesProcessed;
|
||||||
ma_uint32 capturedDeviceFramesToProcess;
|
ma_uint32 capturedDeviceFramesToProcess;
|
||||||
@@ -11391,25 +11517,23 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
|||||||
case ma_device_type_capture:
|
case ma_device_type_capture:
|
||||||
{
|
{
|
||||||
/* We read in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
/* 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 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||||
ma_uint32 framesReadThisPeriod = 0;
|
ma_uint32 framesReadThisPeriod = 0;
|
||||||
while (framesReadThisPeriod < periodSizeInFrames) {
|
while (framesReadThisPeriod < periodSizeInFrames) {
|
||||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
||||||
ma_uint32 framesProcessed;
|
ma_uint32 framesProcessed;
|
||||||
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
||||||
if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
|
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
|
||||||
framesToReadThisIteration = intermediaryBufferSizeInFrames;
|
framesToReadThisIteration = capturedDeviceDataCapInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ma_device_read__winmm(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
|
result = ma_device_read__winmm(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
|
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
|
||||||
|
|
||||||
framesReadThisPeriod += framesProcessed;
|
framesReadThisPeriod += framesProcessed;
|
||||||
}
|
}
|
||||||
@@ -11418,21 +11542,19 @@ static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
|||||||
case ma_device_type_playback:
|
case ma_device_type_playback:
|
||||||
{
|
{
|
||||||
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
/* 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 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||||
ma_uint32 framesWrittenThisPeriod = 0;
|
ma_uint32 framesWrittenThisPeriod = 0;
|
||||||
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
||||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
||||||
ma_uint32 framesProcessed;
|
ma_uint32 framesProcessed;
|
||||||
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
||||||
if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
|
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
|
||||||
framesToWriteThisIteration = intermediaryBufferSizeInFrames;
|
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) {
|
if (result != MA_SUCCESS) {
|
||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break;
|
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
|
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.
|
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)
|
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;
|
UInt32 deviceFormatDescriptionCount;
|
||||||
AudioStreamRangedDescription* pDeviceFormatDescriptions;
|
AudioStreamRangedDescription* pDeviceFormatDescriptions;
|
||||||
@@ -17761,40 +17890,20 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec
|
|||||||
|
|
||||||
desiredSampleRate = sampleRate;
|
desiredSampleRate = sampleRate;
|
||||||
if (usingDefaultSampleRate) {
|
if (usingDefaultSampleRate) {
|
||||||
/*
|
desiredSampleRate = pOrigFormat->mSampleRate;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
desiredChannelCount = channels;
|
desiredChannelCount = channels;
|
||||||
if (usingDefaultChannels) {
|
if (usingDefaultChannels) {
|
||||||
ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &desiredChannelCount); /* <-- Not critical if this fails. */
|
desiredChannelCount = pOrigFormat->mChannelsPerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
desiredFormat = format;
|
desiredFormat = format;
|
||||||
if (usingDefaultFormat) {
|
if (usingDefaultFormat) {
|
||||||
desiredFormat = g_maFormatPriorities[0];
|
result = ma_format_from_AudioStreamBasicDescription(pOrigFormat, &desiredFormat);
|
||||||
|
if (result != MA_SUCCESS || desiredFormat == ma_format_unknown) {
|
||||||
|
desiredFormat = g_maFormatPriorities[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -18652,17 +18761,22 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex
|
|||||||
|
|
||||||
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||||
{
|
{
|
||||||
AudioObjectPropertyAddress propAddress;
|
/* Don't do anything if we've already initializd device tracking. */
|
||||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
|
||||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
AudioObjectPropertyAddress propAddress;
|
||||||
|
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
|
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||||
|
|
||||||
ma_mutex_init(&g_DeviceTrackingMutex_CoreAudio);
|
ma_mutex_init(&g_DeviceTrackingMutex_CoreAudio);
|
||||||
|
|
||||||
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||||
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||||
|
|
||||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||||
|
|
||||||
|
g_DeviceTrackingInitCounter_CoreAudio += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
|
ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||||
|
|
||||||
@@ -18675,21 +18789,26 @@ static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pCont
|
|||||||
|
|
||||||
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||||
{
|
{
|
||||||
AudioObjectPropertyAddress propAddress;
|
g_DeviceTrackingInitCounter_CoreAudio -= 1;
|
||||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
|
||||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
|
||||||
|
|
||||||
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
|
||||||
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
AudioObjectPropertyAddress propAddress;
|
||||||
|
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
|
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||||
|
|
||||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||||
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
((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. */
|
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
MA_ASSERT(g_ppTrackedDevices_CoreAudio == NULL);
|
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||||
MA_ASSERT(g_TrackedDeviceCount_CoreAudio == 0);
|
|
||||||
|
|
||||||
ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio);
|
/* 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);
|
ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
|
||||||
|
|
||||||
@@ -19057,26 +19176,30 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
AudioStreamBasicDescription origFormat;
|
AudioStreamBasicDescription origFormat;
|
||||||
UInt32 origFormatSize;
|
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);
|
origFormatSize = sizeof(origFormat);
|
||||||
if (deviceType == ma_device_type_playback) {
|
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &origFormat, &origFormatSize);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != noErr) {
|
if (status != noErr) {
|
||||||
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||||
return result;
|
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;
|
bestFormat.mSampleRate = origFormat.mSampleRate;
|
||||||
|
#endif
|
||||||
|
|
||||||
status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
|
status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
|
||||||
if (status != noErr) {
|
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)
|
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. */
|
/* 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 totalOutputFramesToProcess;
|
||||||
ma_uint64 totalOutputFramesProcessed;
|
ma_uint64 totalOutputFramesProcessed;
|
||||||
ma_uint64 totalInputFramesProcessed;
|
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;
|
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
|
||||||
|
|
||||||
if (pBytesWritten == NULL) {
|
if (pBytesWritten != NULL) {
|
||||||
*pBytesWritten = 0;
|
*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);
|
readResult = ReadFile((HANDLE)file, ma_offset_ptr(pDst, totalBytesRead), bytesToRead, &bytesRead, NULL);
|
||||||
|
if (readResult == 1 && bytesRead == 0) {
|
||||||
|
break; /* EOF */
|
||||||
|
}
|
||||||
|
|
||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
|
|
||||||
if (bytesRead < bytesToRead || (readResult == 1 && bytesRead == 0)) {
|
if (bytesRead < bytesToRead) {
|
||||||
break; /* EOF */
|
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;
|
*pBytesWritten = totalBytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36910,7 +37037,7 @@ extern "C" {
|
|||||||
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
|
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
|
||||||
#define DRWAV_VERSION_MAJOR 0
|
#define DRWAV_VERSION_MAJOR 0
|
||||||
#define DRWAV_VERSION_MINOR 12
|
#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)
|
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
typedef signed char drwav_int8;
|
typedef signed char drwav_int8;
|
||||||
@@ -37049,7 +37176,8 @@ typedef enum
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
drwav_container_riff,
|
drwav_container_riff,
|
||||||
drwav_container_w64
|
drwav_container_w64,
|
||||||
|
drwav_container_rf64
|
||||||
} drwav_container;
|
} drwav_container;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -37282,7 +37410,7 @@ extern "C" {
|
|||||||
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
||||||
#define DRFLAC_VERSION_MAJOR 0
|
#define DRFLAC_VERSION_MAJOR 0
|
||||||
#define DRFLAC_VERSION_MINOR 12
|
#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)
|
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
typedef signed char drflac_int8;
|
typedef signed char drflac_int8;
|
||||||
@@ -37643,7 +37771,7 @@ extern "C" {
|
|||||||
#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
|
#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
|
||||||
#define DRMP3_VERSION_MAJOR 0
|
#define DRMP3_VERSION_MAJOR 0
|
||||||
#define DRMP3_VERSION_MINOR 6
|
#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)
|
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
typedef signed char drmp3_int8;
|
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."
|
#error "This compiler does not support the byte swap intrinsic."
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
return ((n & (drwav_uint64)0xFF00000000000000) >> 56) |
|
return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
|
||||||
((n & (drwav_uint64)0x00FF000000000000) >> 40) |
|
((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
|
||||||
((n & (drwav_uint64)0x0000FF0000000000) >> 24) |
|
((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
|
||||||
((n & (drwav_uint64)0x000000FF00000000) >> 8) |
|
((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
|
||||||
((n & (drwav_uint64)0x00000000FF000000) << 8) |
|
((n & ((drwav_uint64)0xFF000000 )) << 8) |
|
||||||
((n & (drwav_uint64)0x0000000000FF0000) << 24) |
|
((n & ((drwav_uint64)0x00FF0000 )) << 24) |
|
||||||
((n & (drwav_uint64)0x000000000000FF00) << 40) |
|
((n & ((drwav_uint64)0x0000FF00 )) << 40) |
|
||||||
((n & (drwav_uint64)0x00000000000000FF) << 56);
|
((n & ((drwav_uint64)0x000000FF )) << 56);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
|
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_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)
|
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];
|
drwav_uint8 sizeInBytes[4];
|
||||||
if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
|
if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
|
||||||
return DRWAV_AT_END;
|
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) {
|
if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
|
||||||
return DRWAV_FALSE;
|
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)) {
|
if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
@@ -42005,7 +42133,7 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
|
|||||||
return DRWAV_FALSE;
|
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 ")) {
|
if (!drwav__fourcc_equal(header.id.fourcc, "fmt ")) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
@@ -42138,9 +42266,9 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
drwav_uint8 riff[4];
|
drwav_uint8 riff[4];
|
||||||
drwav_fmt fmt;
|
drwav_fmt fmt;
|
||||||
unsigned short translatedFormatTag;
|
unsigned short translatedFormatTag;
|
||||||
drwav_uint64 sampleCountFromFactChunk;
|
|
||||||
drwav_bool32 foundDataChunk;
|
drwav_bool32 foundDataChunk;
|
||||||
drwav_uint64 dataChunkSize;
|
drwav_uint64 dataChunkSize = 0;
|
||||||
|
drwav_uint64 sampleCountFromFactChunk = 0;
|
||||||
drwav_uint64 chunkSize;
|
drwav_uint64 chunkSize;
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
sequential = (flags & DRWAV_SEQUENTIAL) != 0;
|
sequential = (flags & DRWAV_SEQUENTIAL) != 0;
|
||||||
@@ -42161,17 +42289,25 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (drwav__fourcc_equal(riff, "RF64")) {
|
||||||
|
pWav->container = drwav_container_rf64;
|
||||||
} else {
|
} else {
|
||||||
return DRWAV_FALSE;
|
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 chunkSizeBytes[4];
|
||||||
drwav_uint8 wave[4];
|
drwav_uint8 wave[4];
|
||||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
|
if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
if (drwav__bytes_to_u32(chunkSizeBytes) < 36) {
|
if (pWav->container == drwav_container_riff) {
|
||||||
return DRWAV_FALSE;
|
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)) {
|
if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
@@ -42195,6 +42331,38 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
return DRWAV_FALSE;
|
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)) {
|
if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
|
||||||
return DRWAV_FALSE;
|
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) {
|
if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
|
||||||
translatedFormatTag = drwav__bytes_to_u16(fmt.subFormat + 0);
|
translatedFormatTag = drwav__bytes_to_u16(fmt.subFormat + 0);
|
||||||
}
|
}
|
||||||
sampleCountFromFactChunk = 0;
|
|
||||||
foundDataChunk = DRWAV_FALSE;
|
foundDataChunk = DRWAV_FALSE;
|
||||||
dataChunkSize = 0;
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
drwav_chunk_header header;
|
drwav_chunk_header header;
|
||||||
@@ -42234,10 +42400,12 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
pWav->dataChunkDataPos = cursor;
|
pWav->dataChunkDataPos = cursor;
|
||||||
}
|
}
|
||||||
chunkSize = header.sizeInBytes;
|
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")) {
|
if (drwav__fourcc_equal(header.id.fourcc, "data")) {
|
||||||
foundDataChunk = DRWAV_TRUE;
|
foundDataChunk = DRWAV_TRUE;
|
||||||
dataChunkSize = chunkSize;
|
if (pWav->container != drwav_container_rf64) {
|
||||||
|
dataChunkSize = chunkSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
|
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
|
||||||
@@ -42264,7 +42432,7 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
sampleCountFromFactChunk = 0;
|
sampleCountFromFactChunk = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (pWav->container == drwav_container_w64) {
|
||||||
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
|
if (drwav__guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
|
||||||
if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
|
if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
@@ -42274,8 +42442,9 @@ static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk,
|
|||||||
pWav->dataChunkDataPos = cursor;
|
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")) {
|
if (drwav__fourcc_equal(header.id.fourcc, "smpl")) {
|
||||||
drwav_uint8 smplHeaderData[36];
|
drwav_uint8 smplHeaderData[36];
|
||||||
if (chunkSize >= sizeof(smplHeaderData)) {
|
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)
|
static drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize)
|
||||||
{
|
{
|
||||||
drwav_uint32 dataSubchunkPaddingSize = drwav__chunk_padding_size_riff(dataChunkSize);
|
drwav_uint64 chunkSize = 4 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
|
||||||
if (dataChunkSize <= (0xFFFFFFFFUL - 36 - dataSubchunkPaddingSize)) {
|
if (chunkSize > 0xFFFFFFFFUL) {
|
||||||
return 36 + (drwav_uint32)(dataChunkSize + dataSubchunkPaddingSize);
|
chunkSize = 0xFFFFFFFFUL;
|
||||||
} else {
|
|
||||||
return 0xFFFFFFFF;
|
|
||||||
}
|
}
|
||||||
|
return (drwav_uint32)chunkSize;
|
||||||
}
|
}
|
||||||
static drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
|
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;
|
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)
|
static size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
|
||||||
{
|
{
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
@@ -42498,21 +42678,35 @@ static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_for
|
|||||||
}
|
}
|
||||||
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
|
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
|
||||||
if (pFormat->container == drwav_container_riff) {
|
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(pWav, "RIFF", 4);
|
||||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
||||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||||
} else {
|
} else if (pFormat->container == drwav_container_w64) {
|
||||||
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
|
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
|
||||||
runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
|
runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
|
||||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
|
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
|
||||||
runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
|
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;
|
chunkSizeFMT = 16;
|
||||||
runningPos += drwav__write(pWav, "fmt ", 4);
|
runningPos += drwav__write(pWav, "fmt ", 4);
|
||||||
runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
|
runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
|
||||||
} else {
|
} else if (pFormat->container == drwav_container_w64) {
|
||||||
chunkSizeFMT = 40;
|
chunkSizeFMT = 40;
|
||||||
runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
|
runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
|
||||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
|
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;
|
drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
|
||||||
runningPos += drwav__write(pWav, "data", 4);
|
runningPos += drwav__write(pWav, "data", 4);
|
||||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
|
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
|
||||||
} else {
|
} else if (pFormat->container == drwav_container_w64) {
|
||||||
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
|
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
|
||||||
runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
|
runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
|
||||||
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
|
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
|
||||||
}
|
} else if (pFormat->container == drwav_container_rf64) {
|
||||||
if (pFormat->container == drwav_container_riff) {
|
runningPos += drwav__write(pWav, "data", 4);
|
||||||
if (runningPos != 20 + chunkSizeFMT + 8) {
|
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
|
||||||
return DRWAV_FALSE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (runningPos != 40 + chunkSizeFMT + 24) {
|
|
||||||
return DRWAV_FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pWav->container = pFormat->container;
|
pWav->container = pFormat->container;
|
||||||
pWav->channels = (drwav_uint16)pFormat->channels;
|
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 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalSampleCount * pFormat->channels * pFormat->bitsPerSample/8.0);
|
||||||
drwav_uint64 riffChunkSizeBytes;
|
drwav_uint64 riffChunkSizeBytes;
|
||||||
drwav_uint64 fileSizeBytes;
|
drwav_uint64 fileSizeBytes = 0;
|
||||||
if (pFormat->container == drwav_container_riff) {
|
if (pFormat->container == drwav_container_riff) {
|
||||||
riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
|
riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
|
||||||
fileSizeBytes = (8 + riffChunkSizeBytes);
|
fileSizeBytes = (8 + riffChunkSizeBytes);
|
||||||
} else {
|
} else if (pFormat->container == drwav_container_w64) {
|
||||||
riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
|
riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
|
||||||
fileSizeBytes = riffChunkSizeBytes;
|
fileSizeBytes = riffChunkSizeBytes;
|
||||||
|
} else if (pFormat->container == drwav_container_rf64) {
|
||||||
|
riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes);
|
||||||
|
fileSizeBytes = (8 + riffChunkSizeBytes);
|
||||||
}
|
}
|
||||||
return fileSizeBytes;
|
return fileSizeBytes;
|
||||||
}
|
}
|
||||||
@@ -43352,7 +43543,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
|||||||
}
|
}
|
||||||
if (pWav->onWrite != NULL) {
|
if (pWav->onWrite != NULL) {
|
||||||
drwav_uint32 paddingSize = 0;
|
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);
|
paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
|
||||||
} else {
|
} else {
|
||||||
paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
|
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_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
|
||||||
drwav__write_u32ne_to_le(pWav, dataChunkSize);
|
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)) {
|
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
|
||||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
||||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
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_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
|
||||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
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) {
|
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."
|
#error "This compiler does not support the byte swap intrinsic."
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
return ((n & (drflac_uint64)0xFF00000000000000) >> 56) |
|
return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
|
||||||
((n & (drflac_uint64)0x00FF000000000000) >> 40) |
|
((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
|
||||||
((n & (drflac_uint64)0x0000FF0000000000) >> 24) |
|
((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
|
||||||
((n & (drflac_uint64)0x000000FF00000000) >> 8) |
|
((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
|
||||||
((n & (drflac_uint64)0x00000000FF000000) << 8) |
|
((n & ((drflac_uint64)0xFF000000 )) << 8) |
|
||||||
((n & (drflac_uint64)0x0000000000FF0000) << 24) |
|
((n & ((drflac_uint64)0x00FF0000 )) << 24) |
|
||||||
((n & (drflac_uint64)0x000000000000FF00) << 40) |
|
((n & ((drflac_uint64)0x0000FF00 )) << 40) |
|
||||||
((n & (drflac_uint64)0x00000000000000FF) << 56);
|
((n & ((drflac_uint64)0x000000FF )) << 56);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static DRFLAC_INLINE drflac_uint16 drflac__be2host_16(drflac_uint16 n)
|
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));
|
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define DRMP3_HAVE_ARMV6 0
|
||||||
#endif
|
#endif
|
||||||
typedef struct
|
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.
|
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
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define MA_VERSION_MAJOR 0
|
#define MA_VERSION_MAJOR 0
|
||||||
#define MA_VERSION_MINOR 10
|
#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)
|
#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__)
|
||||||
@@ -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_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
|
||||||
} ma_backend;
|
} ma_backend;
|
||||||
|
|
||||||
|
#define MA_BACKEND_COUNT (ma_backend_null+1)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The callback for processing audio data from the device.
|
The callback for processing audio data from the device.
|
||||||
@@ -2474,7 +2476,7 @@ struct ma_device
|
|||||||
ma_uint32 currentPeriodFramesRemainingPlayback;
|
ma_uint32 currentPeriodFramesRemainingPlayback;
|
||||||
ma_uint32 currentPeriodFramesRemainingCapture;
|
ma_uint32 currentPeriodFramesRemainingCapture;
|
||||||
ma_uint64 lastProcessedFramePlayback;
|
ma_uint64 lastProcessedFramePlayback;
|
||||||
ma_uint32 lastProcessedFrameCapture;
|
ma_uint64 lastProcessedFrameCapture;
|
||||||
ma_bool32 isStarted;
|
ma_bool32 isStarted;
|
||||||
} null_device;
|
} null_device;
|
||||||
#endif
|
#endif
|
||||||
@@ -3674,6 +3676,84 @@ Retrieves a friendly name for a backend.
|
|||||||
*/
|
*/
|
||||||
MA_API const char* ma_get_backend_name(ma_backend 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.
|
Determines whether or not loopback mode is support by a backend.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-2
@@ -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.10.21 - TBD
|
miniaudio - v0.10.21 - 2020-10-30
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@@ -62859,7 +62859,7 @@ The following miscellaneous changes have also been made.
|
|||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.10.21 - TBD
|
v0.10.21 - 2020-10-30
|
||||||
- Add ma_is_backend_enabled() and ma_get_enabled_backends() for retrieving enabled backends at run-time.
|
- Add ma_is_backend_enabled() and ma_get_enabled_backends() for retrieving enabled backends at run-time.
|
||||||
- WASAPI: Fix a copy and paste bug relating to loopback mode.
|
- WASAPI: Fix a copy and paste bug relating to loopback mode.
|
||||||
- Core Audio: Fix a bug when using multiple contexts.
|
- Core Audio: Fix a bug when using multiple contexts.
|
||||||
|
|||||||
Reference in New Issue
Block a user