Merge branch 'dev' into dev-0.12

This commit is contained in:
David Reid
2025-02-24 16:35:53 +10:00
12 changed files with 1424 additions and 558 deletions
+42 -31
View File
@@ -1,6 +1,6 @@
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.22 - TBD
miniaudio - v0.11.22 - 2025-02-24
David Reid - mackron@gmail.com
@@ -28520,7 +28520,21 @@ static ma_result ma_device_start__alsa(ma_device* pDevice)
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
/* Don't need to do anything for playback because it'll be started automatically when enough data has been written. */
/*
When data is written to the device we wait for the device to get ready to receive data with poll(). In my testing
I have observed that poll() can sometimes block forever unless the device is started explicitly with snd_pcm_start()
or some data is written with snd_pcm_writei().
To resolve this I've decided to do an explicit start with snd_pcm_start(). The problem with this is that the device
is started without any data in the internal buffer which will result in an immediate underrun. If instead we were
to call into snd_pcm_writei() in an attempt to prevent the underrun, we would run the risk of a weird deadlock
issue as documented inside ma_device_write__alsa().
*/
resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
if (resultALSA < 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start playback device.");
return ma_result_from_errno(-resultALSA);
}
}
return MA_SUCCESS;
@@ -28581,7 +28595,6 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from playback wakeupfd. read() = %d\n", resultRead);
}
}
}
return MA_SUCCESS;
@@ -28607,7 +28620,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
/*
Before checking the ALSA poll descriptor flag we need to check if the wakeup descriptor
has had it's POLLIN flag set. If so, we need to actually read the data and then exit
has had it's POLLIN flag set. If so, we need to actually read the data and then exit the
function. The wakeup descriptor will be the first item in the descriptors buffer.
*/
if ((pPollDescriptors[0].revents & POLLIN) != 0) {
@@ -28636,7 +28649,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
ma_snd_pcm_state_t state = ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM);
if (state == MA_SND_PCM_STATE_XRUN) {
/* The PCM is in a xrun state. This will be recovered from at a higher level. We can disregard this. */
} else {
} else {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[ALSA] POLLERR detected. status = %d\n", ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM));
}
}
@@ -38163,20 +38176,12 @@ static ma_result ma_create_and_configure_AAudioStreamBuilder__aaudio(ma_context*
((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pDescriptor->sampleRate);
}
if (deviceType == ma_device_type_capture) {
if (pDescriptor->channels != 0) {
((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
}
if (pDescriptor->format != ma_format_unknown) {
((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
}
} else {
if (pDescriptor->channels != 0) {
((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
}
if (pDescriptor->format != ma_format_unknown) {
((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
}
if (pDescriptor->channels != 0) {
((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
}
if (pDescriptor->format != ma_format_unknown) {
((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
}
@@ -53118,12 +53123,7 @@ static ma_channel_conversion_path ma_channel_map_get_conversion_path(const ma_ch
ma_uint32 iChannelIn;
ma_bool32 areAllChannelPositionsPresent = MA_TRUE;
for (iChannelIn = 0; iChannelIn < channelsIn; ++iChannelIn) {
ma_bool32 isInputChannelPositionInOutput = MA_FALSE;
if (ma_channel_map_contains_channel_position(channelsOut, pChannelMapOut, ma_channel_map_get_channel(pChannelMapIn, channelsIn, iChannelIn))) {
isInputChannelPositionInOutput = MA_TRUE;
break;
}
ma_bool32 isInputChannelPositionInOutput = ma_channel_map_contains_channel_position(channelsOut, pChannelMapOut, ma_channel_map_get_channel(pChannelMapIn, channelsIn, iChannelIn));
if (!isInputChannelPositionInOutput) {
areAllChannelPositionsPresent = MA_FALSE;
break;
@@ -60513,7 +60513,7 @@ extern "C" {
#define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x)
#define MA_DR_WAV_VERSION_MAJOR 0
#define MA_DR_WAV_VERSION_MINOR 13
#define MA_DR_WAV_VERSION_REVISION 17
#define MA_DR_WAV_VERSION_REVISION 18
#define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION)
#include <stddef.h>
#define MA_DR_WAVE_FORMAT_PCM 0x1
@@ -65417,6 +65417,14 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
if (requiredInputFrameCount > 0) {
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn);
/*
Note here that even if we've reached the end, we don't want to abort because there might be more output frames needing to be
generated from cached input data, which might happen if resampling is being performed.
*/
if (result != MA_SUCCESS && result != MA_AT_END) {
break;
}
} else {
framesReadThisIterationIn = 0;
pIntermediaryBuffer[0] = 0; /* <-- This is just to silence a static analysis warning. */
@@ -68540,7 +68548,7 @@ static ma_result ma_resource_manager_data_buffer_node_decode_next_page(ma_resour
}
result = ma_decoder_read_pcm_frames(pDecoder, pPage->pAudioData, framesToTryReading, &framesRead);
if (framesRead > 0) {
if (result == MA_SUCCESS && framesRead > 0) {
pPage->sizeInFrames = framesRead;
result = ma_paged_audio_buffer_data_append_page(&pDataBufferNode->data.backend.decodedPaged.data, pPage);
@@ -70999,6 +71007,7 @@ static ma_result ma_job_process__resource_manager__load_data_buffer(ma_job* pJob
goto done; /* <-- This will ensure the execution pointer is incremented. */
} else {
result = MA_SUCCESS; /* <-- Make sure this is reset. */
(void)result; /* <-- This is to suppress a static analysis diagnostic about "result" not being used. But for safety when I do future maintenance I don't want to delete that assignment. */
}
/* Try initializing the connector if we haven't already. */
@@ -77731,7 +77740,7 @@ code below please report the bug to the respective repository for the relevant p
***************************************************************************************************************************************************************
**************************************************************************************************************************************************************/
#if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING))
#if !defined(MA_DR_WAV_IMPLEMENTATION) && !defined(MA_DR_WAV_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
#if !defined(MA_DR_WAV_IMPLEMENTATION)
/* dr_wav_c begin */
#ifndef ma_dr_wav_c
#define ma_dr_wav_c
@@ -79321,7 +79330,9 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
compressionFormat = MA_DR_WAVE_FORMAT_MULAW;
} else if (ma_dr_wav_fourcc_equal(type, "ima4")) {
compressionFormat = MA_DR_WAVE_FORMAT_DVI_ADPCM;
sampleSizeInBits = 4;
sampleSizeInBits = 4;
(void)compressionFormat;
(void)sampleSizeInBits;
return MA_FALSE;
} else {
return MA_FALSE;
@@ -82562,7 +82573,7 @@ MA_API ma_bool32 ma_dr_wav_fourcc_equal(const ma_uint8* a, const char* b)
#endif /* MA_NO_WAV */
#if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
#if !defined(MA_DR_FLAC_IMPLEMENTATION) && !defined(MA_DR_FLAC_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
#if !defined(MA_DR_FLAC_IMPLEMENTATION)
/* dr_flac_c begin */
#ifndef ma_dr_flac_c
#define ma_dr_flac_c
@@ -90311,7 +90322,7 @@ MA_API ma_bool32 ma_dr_flac_next_cuesheet_track(ma_dr_flac_cuesheet_track_iterat
#endif /* MA_NO_FLAC */
#if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
#if !defined(MA_DR_MP3_IMPLEMENTATION) && !defined(MA_DR_MP3_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
#if !defined(MA_DR_MP3_IMPLEMENTATION)
/* dr_mp3_c begin */
#ifndef ma_dr_mp3_c
#define ma_dr_mp3_c