mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 01:04:02 +02:00
ALSA: Try fixing a crackling bug.
This commit is contained in:
@@ -8868,6 +8868,7 @@ mal_result mal_context_init__winmm(mal_context* pContext)
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#ifdef MAL_HAS_ALSA
|
#ifdef MAL_HAS_ALSA
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
#ifdef MAL_NO_RUNTIME_LINKING
|
#ifdef MAL_NO_RUNTIME_LINKING
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
typedef snd_pcm_uframes_t mal_snd_pcm_uframes_t;
|
typedef snd_pcm_uframes_t mal_snd_pcm_uframes_t;
|
||||||
@@ -9131,8 +9132,8 @@ static struct
|
|||||||
const char* name;
|
const char* name;
|
||||||
float scale;
|
float scale;
|
||||||
} g_malDefaultBufferSizeScalesALSA[] = {
|
} g_malDefaultBufferSizeScalesALSA[] = {
|
||||||
{"bcm2835 IEC958/HDMI", 40.0f},
|
{"bcm2835 IEC958/HDMI", 2.0f},
|
||||||
{"bcm2835 ALSA", 40.0f}
|
{"bcm2835 ALSA", 2.0f}
|
||||||
};
|
};
|
||||||
|
|
||||||
float mal_find_default_buffer_size_scale__alsa(const char* deviceName)
|
float mal_find_default_buffer_size_scale__alsa(const char* deviceName)
|
||||||
@@ -9812,6 +9813,47 @@ mal_uint32 mal_device__wait_for_frames__alsa(mal_device* pDevice, mal_bool32* pR
|
|||||||
|
|
||||||
if (pRequiresRestart) *pRequiresRestart = MAL_FALSE;
|
if (pRequiresRestart) *pRequiresRestart = MAL_FALSE;
|
||||||
|
|
||||||
|
// I want it so that this function returns the period size in frames. We just wait until that number of frames are available and then return.
|
||||||
|
mal_uint32 periodSizeInFrames = pDevice->bufferSizeInFrames / pDevice->periods;
|
||||||
|
while (!pDevice->alsa.breakFromMainLoop) {
|
||||||
|
mal_snd_pcm_sframes_t framesAvailable = ((mal_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((mal_snd_pcm_t*)pDevice->alsa.pPCM);
|
||||||
|
if (framesAvailable < 0) {
|
||||||
|
if (framesAvailable == -EPIPE) {
|
||||||
|
if (((mal_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((mal_snd_pcm_t*)pDevice->alsa.pPCM, framesAvailable, MAL_TRUE) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pRequiresRestart) *pRequiresRestart = MAL_TRUE; // A device recovery means a restart for mmap mode.
|
||||||
|
|
||||||
|
// Try again, but if it fails this time just return an error.
|
||||||
|
framesAvailable = ((mal_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((mal_snd_pcm_t*)pDevice->alsa.pPCM);
|
||||||
|
if (framesAvailable < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framesAvailable >= periodSizeInFrames) {
|
||||||
|
return periodSizeInFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framesAvailable < periodSizeInFrames) {
|
||||||
|
// Less than a whole period is available so keep waiting.
|
||||||
|
int waitResult = ((mal_snd_pcm_wait_proc)pDevice->pContext->alsa.snd_pcm_wait)((mal_snd_pcm_t*)pDevice->alsa.pPCM, -1);
|
||||||
|
if (waitResult < 0) {
|
||||||
|
if (waitResult == -EPIPE) {
|
||||||
|
if (((mal_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((mal_snd_pcm_t*)pDevice->alsa.pPCM, waitResult, MAL_TRUE) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pRequiresRestart) *pRequiresRestart = MAL_TRUE; // A device recovery means a restart for mmap mode.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
while (!pDevice->alsa.breakFromMainLoop) {
|
while (!pDevice->alsa.breakFromMainLoop) {
|
||||||
int waitResult = ((mal_snd_pcm_wait_proc)pDevice->pContext->alsa.snd_pcm_wait)((mal_snd_pcm_t*)pDevice->alsa.pPCM, -1);
|
int waitResult = ((mal_snd_pcm_wait_proc)pDevice->pContext->alsa.snd_pcm_wait)((mal_snd_pcm_t*)pDevice->alsa.pPCM, -1);
|
||||||
if (waitResult < 0) {
|
if (waitResult < 0) {
|
||||||
@@ -9861,6 +9903,7 @@ mal_uint32 mal_device__wait_for_frames__alsa(mal_device* pDevice, mal_bool32* pR
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We'll get here if the loop was terminated. Just return whatever's available.
|
// We'll get here if the loop was terminated. Just return whatever's available.
|
||||||
mal_snd_pcm_sframes_t framesAvailable = ((mal_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((mal_snd_pcm_t*)pDevice->alsa.pPCM);
|
mal_snd_pcm_sframes_t framesAvailable = ((mal_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((mal_snd_pcm_t*)pDevice->alsa.pPCM);
|
||||||
@@ -10150,8 +10193,6 @@ mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type type, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Hardware parameters.
|
// Hardware parameters.
|
||||||
mal_snd_pcm_hw_params_t* pHWParams = (mal_snd_pcm_hw_params_t*)alloca(((mal_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
|
mal_snd_pcm_hw_params_t* pHWParams = (mal_snd_pcm_hw_params_t*)alloca(((mal_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
|
||||||
mal_zero_memory(pHWParams, ((mal_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
|
mal_zero_memory(pHWParams, ((mal_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
|
||||||
@@ -10271,21 +10312,12 @@ mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type type, co
|
|||||||
pDevice->internalSampleRate = (mal_uint32)sampleRate;
|
pDevice->internalSampleRate = (mal_uint32)sampleRate;
|
||||||
|
|
||||||
|
|
||||||
// Periods.
|
// At this point we know the internal sample rate which means we can calculate the buffer size in frames.
|
||||||
mal_uint32 periods = pConfig->periods;
|
|
||||||
int dir = 0;
|
|
||||||
if (((mal_snd_pcm_hw_params_set_periods_near_proc)pContext->alsa.snd_pcm_hw_params_set_periods_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &periods, &dir) < 0) {
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
|
||||||
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[ALSA] Failed to set period count. snd_pcm_hw_params_set_periods_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
|
||||||
}
|
|
||||||
pDevice->periods = periods;
|
|
||||||
|
|
||||||
|
|
||||||
// Buffer Size
|
|
||||||
if (pDevice->bufferSizeInFrames == 0) {
|
if (pDevice->bufferSizeInFrames == 0) {
|
||||||
pDevice->bufferSizeInFrames = mal_scale_buffer_size(mal_calculate_buffer_size_in_frames_from_milliseconds(pDevice->bufferSizeInMilliseconds, pDevice->internalSampleRate), bufferSizeScaleFactor);
|
pDevice->bufferSizeInFrames = mal_scale_buffer_size(mal_calculate_buffer_size_in_frames_from_milliseconds(pDevice->bufferSizeInMilliseconds, pDevice->internalSampleRate), bufferSizeScaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buffer Size
|
||||||
mal_snd_pcm_uframes_t actualBufferSize = pDevice->bufferSizeInFrames;
|
mal_snd_pcm_uframes_t actualBufferSize = pDevice->bufferSizeInFrames;
|
||||||
if (((mal_snd_pcm_hw_params_set_buffer_size_near_proc)pContext->alsa.snd_pcm_hw_params_set_buffer_size_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &actualBufferSize) < 0) {
|
if (((mal_snd_pcm_hw_params_set_buffer_size_near_proc)pContext->alsa.snd_pcm_hw_params_set_buffer_size_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &actualBufferSize) < 0) {
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
@@ -10293,6 +10325,14 @@ mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type type, co
|
|||||||
}
|
}
|
||||||
pDevice->bufferSizeInFrames = actualBufferSize;
|
pDevice->bufferSizeInFrames = actualBufferSize;
|
||||||
|
|
||||||
|
// Periods.
|
||||||
|
mal_uint32 periods = pConfig->periods;
|
||||||
|
if (((mal_snd_pcm_hw_params_set_periods_near_proc)pContext->alsa.snd_pcm_hw_params_set_periods_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &periods, NULL) < 0) {
|
||||||
|
mal_device_uninit__alsa(pDevice);
|
||||||
|
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[ALSA] Failed to set period count. snd_pcm_hw_params_set_periods_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
pDevice->periods = periods;
|
||||||
|
|
||||||
|
|
||||||
// Apply hardware parameters.
|
// Apply hardware parameters.
|
||||||
if (((mal_snd_pcm_hw_params_proc)pContext->alsa.snd_pcm_hw_params)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
if (((mal_snd_pcm_hw_params_proc)pContext->alsa.snd_pcm_hw_params)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user