mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Experimental work on MMAP mode for ALSA.
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
//
|
//
|
||||||
// NOTES
|
// NOTES
|
||||||
// =====
|
// =====
|
||||||
// - This library uses an asynchronous API delivering and requesting audio data. Each device will have
|
// - This library uses an asynchronous API for delivering and requesting audio data. Each device will have
|
||||||
// it's own worker thread which is managed by the library.
|
// it's own worker thread which is managed by the library.
|
||||||
// - If mal_device_init() is called with a device that's not aligned to the platform's natural alignment
|
// - If mal_device_init() is called with a device that's not aligned to the platform's natural alignment
|
||||||
// boundary (4 bytes on 32-bit, 8 bytes on 64-bit), it will _not_ be thread-safe. The reason for this
|
// boundary (4 bytes on 32-bit, 8 bytes on 64-bit), it will _not_ be thread-safe. The reason for this
|
||||||
@@ -1623,7 +1623,7 @@ mal_uint32 mal_device__wait_for_frames__alsa(mal_device* pDevice)
|
|||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
while (!pDevice->alsa.breakFromMainLoop) {
|
while (!pDevice->alsa.breakFromMainLoop) {
|
||||||
snd_pcm_sframes_t framesAvailable = snd_pcm_avail_update(pDevice->alsa.pPCM);
|
snd_pcm_sframes_t framesAvailable = snd_pcm_avail(pDevice->alsa.pPCM);
|
||||||
if (framesAvailable >= pDevice->fragmentSizeInFrames) {
|
if (framesAvailable >= pDevice->fragmentSizeInFrames) {
|
||||||
return pDevice->fragmentSizeInFrames;
|
return pDevice->fragmentSizeInFrames;
|
||||||
}
|
}
|
||||||
@@ -1631,12 +1631,12 @@ mal_uint32 mal_device__wait_for_frames__alsa(mal_device* pDevice)
|
|||||||
if (framesAvailable < 0) {
|
if (framesAvailable < 0) {
|
||||||
if (framesAvailable == -EPIPE) {
|
if (framesAvailable == -EPIPE) {
|
||||||
if (snd_pcm_recover(pDevice->alsa.pPCM, framesAvailable, MAL_TRUE) < 0) {
|
if (snd_pcm_recover(pDevice->alsa.pPCM, framesAvailable, MAL_TRUE) < 0) {
|
||||||
return MAL_FALSE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
framesAvailable = snd_pcm_avail_update(pDevice->alsa.pPCM);
|
framesAvailable = snd_pcm_avail(pDevice->alsa.pPCM);
|
||||||
if (framesAvailable < 0) {
|
if (framesAvailable < 0) {
|
||||||
return MAL_FALSE;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1648,13 +1648,16 @@ mal_uint32 mal_device__wait_for_frames__alsa(mal_device* pDevice)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, making sure it's never
|
||||||
|
// more than the size of a fragment.
|
||||||
snd_pcm_sframes_t framesAvailable = snd_pcm_avail(pDevice->alsa.pPCM);
|
snd_pcm_sframes_t framesAvailable = snd_pcm_avail(pDevice->alsa.pPCM);
|
||||||
if (framesAvailable < 0) {
|
if (framesAvailable < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return framesAvailable;
|
// There's a small chance we'll have more frames available than the size of a fragment. These frames
|
||||||
|
// will be lost to cyberspace :(
|
||||||
|
return (framesAvailable < pDevice->fragmentSizeInFrames) ? framesAvailable : pDevice->fragmentSizeInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_bool32 mal_device_write__alsa(mal_device* pDevice)
|
mal_bool32 mal_device_write__alsa(mal_device* pDevice)
|
||||||
@@ -1667,17 +1670,39 @@ mal_bool32 mal_device_write__alsa(mal_device* pDevice)
|
|||||||
return MAL_FALSE;
|
return MAL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pBuffer = NULL;
|
|
||||||
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
|
||||||
// mmap.
|
|
||||||
return MAL_FALSE;
|
|
||||||
} else {
|
|
||||||
// readi/writei.
|
|
||||||
pBuffer = pDevice->alsa.pIntermediaryBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
||||||
// mmap.
|
// mmap.
|
||||||
|
mal_uint32 framesAvailable = mal_device__wait_for_frames__alsa(pDevice);
|
||||||
|
if (framesAvailable == 0) {
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't bother asking the client for more audio data if we're just stopping the device anyway.
|
||||||
|
if (pDevice->alsa.breakFromMainLoop) {
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const snd_pcm_channel_area_t* pAreas;
|
||||||
|
snd_pcm_uframes_t mappedOffset;
|
||||||
|
snd_pcm_uframes_t mappedFrames = framesAvailable;
|
||||||
|
while (framesAvailable > 0) {
|
||||||
|
int result = snd_pcm_mmap_begin(pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
|
||||||
|
if (result < 0) {
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pBuffer = (mal_uint8*)pAreas[0].addr + ((pAreas[0].first + (mappedOffset * pAreas[0].step)) / 8);
|
||||||
|
mal_device__read_samples_from_client(pDevice, mappedFrames * pDevice->channels, pBuffer);
|
||||||
|
|
||||||
|
result = snd_pcm_mmap_commit(pDevice->alsa.pPCM, mappedOffset, mappedFrames);
|
||||||
|
if (result < 0 || result != mappedFrames) {
|
||||||
|
snd_pcm_recover(pDevice->alsa.pPCM, result, MAL_TRUE);
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
framesAvailable -= mappedFrames;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// readi/writei.
|
// readi/writei.
|
||||||
while (!pDevice->alsa.breakFromMainLoop) {
|
while (!pDevice->alsa.breakFromMainLoop) {
|
||||||
@@ -1691,7 +1716,7 @@ mal_bool32 mal_device_write__alsa(mal_device* pDevice)
|
|||||||
return MAL_FALSE;
|
return MAL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_device__read_samples_from_client(pDevice, framesAvailable * pDevice->channels, pBuffer);
|
mal_device__read_samples_from_client(pDevice, framesAvailable * pDevice->channels, pDevice->alsa.pIntermediaryBuffer);
|
||||||
|
|
||||||
snd_pcm_sframes_t framesWritten = snd_pcm_writei(pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
|
snd_pcm_sframes_t framesWritten = snd_pcm_writei(pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
|
||||||
if (framesWritten < 0) {
|
if (framesWritten < 0) {
|
||||||
@@ -1735,7 +1760,31 @@ mal_bool32 mal_device_read__alsa(mal_device* pDevice)
|
|||||||
void* pBuffer = NULL;
|
void* pBuffer = NULL;
|
||||||
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
||||||
// mmap.
|
// mmap.
|
||||||
return MAL_FALSE;
|
mal_uint32 framesAvailable = mal_device__wait_for_frames__alsa(pDevice);
|
||||||
|
if (framesAvailable == 0) {
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const snd_pcm_channel_area_t* pAreas;
|
||||||
|
snd_pcm_uframes_t mappedOffset;
|
||||||
|
snd_pcm_uframes_t mappedFrames = framesAvailable;
|
||||||
|
while (framesAvailable > 0) {
|
||||||
|
int result = snd_pcm_mmap_begin(pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
|
||||||
|
if (result < 0) {
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pBuffer = (mal_uint8*)pAreas[0].addr + ((pAreas[0].first + (mappedOffset * pAreas[0].step)) / 8);
|
||||||
|
mal_device__send_samples_to_client(pDevice, mappedFrames * pDevice->channels, pBuffer);
|
||||||
|
|
||||||
|
result = snd_pcm_mmap_commit(pDevice->alsa.pPCM, mappedOffset, mappedFrames);
|
||||||
|
if (result < 0 || result != mappedFrames) {
|
||||||
|
snd_pcm_recover(pDevice->alsa.pPCM, result, MAL_TRUE);
|
||||||
|
return MAL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
framesAvailable -= mappedFrames;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// readi/writei.
|
// readi/writei.
|
||||||
snd_pcm_sframes_t framesRead = 0;
|
snd_pcm_sframes_t framesRead = 0;
|
||||||
@@ -1841,7 +1890,7 @@ void mal_device_uninit__alsa(mal_device* pDevice)
|
|||||||
if (pDevice->alsa.pPCM) {
|
if (pDevice->alsa.pPCM) {
|
||||||
snd_pcm_close((snd_pcm_t*)pDevice->alsa.pPCM);
|
snd_pcm_close((snd_pcm_t*)pDevice->alsa.pPCM);
|
||||||
|
|
||||||
if (pDevice->alsa.pIntermediaryBuffer == NULL) {
|
if (pDevice->alsa.pIntermediaryBuffer != NULL) {
|
||||||
mal_free(pDevice->alsa.pIntermediaryBuffer);
|
mal_free(pDevice->alsa.pIntermediaryBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1883,38 +1932,44 @@ mal_result mal_device_init__alsa(mal_device* pDevice, mal_device_type type, mal_
|
|||||||
snd_pcm_hw_params_alloca(&pHWParams);
|
snd_pcm_hw_params_alloca(&pHWParams);
|
||||||
|
|
||||||
if (snd_pcm_hw_params_any((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
if (snd_pcm_hw_params_any((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to initialize hardware parameters. snd_pcm_hw_params_any() failed.", MAL_ALSA_FAILED_TO_SET_HW_PARAMS);
|
return mal_post_error(pDevice, "[ALSA] Failed to initialize hardware parameters. snd_pcm_hw_params_any() failed.", MAL_ALSA_FAILED_TO_SET_HW_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_hw_params_set_access((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
|
// Try using interleaved MMAP access. If this fails, fall back to standard readi/writei.
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
pDevice->alsa.isUsingMMap = MAL_FALSE;
|
||||||
mal_device_uninit__alsa(pDevice);
|
#ifdef MAL_ENABLE_EXPERIMENTAL_ALSA_MMAP
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set access mode to SND_PCM_ACCESS_RW_INTERLEAVED. snd_pcm_hw_params_set_access() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
if (snd_pcm_hw_params_set_access((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
|
||||||
}
|
pDevice->alsa.isUsingMMap = MAL_TRUE;
|
||||||
|
mal_log(pDevice, "USING MMAP\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!pDevice->alsa.isUsingMMap) {
|
||||||
|
if (snd_pcm_hw_params_set_access((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {;
|
||||||
|
mal_device_uninit__alsa(pDevice);
|
||||||
|
return mal_post_error(pDevice, "[ALSA] Failed to set access mode to neither SND_PCM_ACCESS_MMAP_INTERLEAVED nor SND_PCM_ACCESS_RW_INTERLEAVED. snd_pcm_hw_params_set_access() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (snd_pcm_hw_params_set_format((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, formatALSA) < 0) {
|
if (snd_pcm_hw_params_set_format((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, formatALSA) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Format not supported. snd_pcm_hw_params_set_format() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Format not supported. snd_pcm_hw_params_set_format() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (snd_pcm_hw_params_set_rate_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &sampleRate, 0) < 0) {
|
if (snd_pcm_hw_params_set_rate_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &sampleRate, 0) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Sample rate not supported. snd_pcm_hw_params_set_rate_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Sample rate not supported. snd_pcm_hw_params_set_rate_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_hw_params_set_channels_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &channels) < 0) {
|
if (snd_pcm_hw_params_set_channels_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &channels) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set channel count. snd_pcm_hw_params_set_channels_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Failed to set channel count. snd_pcm_hw_params_set_channels_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dir = 0;
|
int dir = 1;
|
||||||
if (snd_pcm_hw_params_set_periods_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &fragmentCount, &dir) < 0) {
|
if (snd_pcm_hw_params_set_periods_near((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &fragmentCount, &dir) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set fragment count. snd_pcm_hw_params_set_periods_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Failed to set fragment count. snd_pcm_hw_params_set_periods_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
@@ -1931,13 +1986,11 @@ mal_result mal_device_init__alsa(mal_device* pDevice, mal_device_type type, mal_
|
|||||||
pDevice->fragmentSizeInFrames = mal_next_power_of_2(fragmentSizeInFrames);
|
pDevice->fragmentSizeInFrames = mal_next_power_of_2(fragmentSizeInFrames);
|
||||||
|
|
||||||
if (snd_pcm_hw_params_set_buffer_size((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, pDevice->fragmentSizeInFrames * pDevice->fragmentCount) < 0) {
|
if (snd_pcm_hw_params_set_buffer_size((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, pDevice->fragmentSizeInFrames * pDevice->fragmentCount) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set buffer size for device. snd_pcm_hw_params_set_buffer_size() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Failed to set buffer size for device. snd_pcm_hw_params_set_buffer_size() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_hw_params((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
if (snd_pcm_hw_params((snd_pcm_t*)pDevice->alsa.pPCM, pHWParams) < 0) {
|
||||||
snd_pcm_hw_params_free(pHWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set hardware parameters. snd_pcm_hw_params() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
return mal_post_error(pDevice, "[ALSA] Failed to set hardware parameters. snd_pcm_hw_params() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
||||||
}
|
}
|
||||||
@@ -1948,33 +2001,30 @@ mal_result mal_device_init__alsa(mal_device* pDevice, mal_device_type type, mal_
|
|||||||
snd_pcm_sw_params_alloca(&pSWParams);
|
snd_pcm_sw_params_alloca(&pSWParams);
|
||||||
|
|
||||||
if (snd_pcm_sw_params_current((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams) != 0) {
|
if (snd_pcm_sw_params_current((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams) != 0) {
|
||||||
snd_pcm_sw_params_free(pSWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to initialize software parameters. snd_pcm_sw_params_current() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
return mal_post_error(pDevice, "[ALSA] Failed to initialize software parameters. snd_pcm_sw_params_current() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_sw_params_set_avail_min((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams, pDevice->fragmentSizeInFrames) != 0) {
|
if (snd_pcm_sw_params_set_avail_min((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams, pDevice->fragmentSizeInFrames) != 0) {
|
||||||
snd_pcm_sw_params_free(pSWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set fragment size. snd_pcm_sw_params_set_avail_min() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Failed to set fragment size. snd_pcm_sw_params_set_avail_min() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == mal_device_type_playback) {
|
if (type == mal_device_type_playback) {
|
||||||
if (snd_pcm_sw_params_set_start_threshold((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams, pDevice->fragmentSizeInFrames) != 0) {
|
if (snd_pcm_sw_params_set_start_threshold((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams, pDevice->fragmentSizeInFrames) != 0) {
|
||||||
snd_pcm_sw_params_free(pSWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set start threshold for playback device. snd_pcm_sw_params_set_start_threshold() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
return mal_post_error(pDevice, "[ALSA] Failed to set start threshold for playback device. snd_pcm_sw_params_set_start_threshold() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_sw_params((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams) != 0) {
|
if (snd_pcm_sw_params((snd_pcm_t*)pDevice->alsa.pPCM, pSWParams) != 0) {
|
||||||
snd_pcm_sw_params_free(pSWParams);
|
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set software parameters. snd_pcm_sw_params() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
return mal_post_error(pDevice, "[ALSA] Failed to set software parameters. snd_pcm_sw_params() failed.", MAL_ALSA_FAILED_TO_SET_SW_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// If we're _not_ using mmap we need to use an intermediary buffer.
|
// If we're _not_ using mmap we need to use an intermediary buffer.
|
||||||
if (!pDevice->alsa.isUsingMMap) {
|
if (!pDevice->alsa.isUsingMMap) {
|
||||||
pDevice->alsa.pIntermediaryBuffer = mal_malloc(pDevice->fragmentSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format));
|
pDevice->alsa.pIntermediaryBuffer = mal_malloc(pDevice->fragmentSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format));
|
||||||
@@ -2456,14 +2506,20 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format)
|
|||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// ====
|
// ====
|
||||||
// - Profiling. Need to measure mal_device_start() and mal_device_stop() in particular. One of the two seems to be taking a bit
|
|
||||||
// longer than it should.
|
|
||||||
// - Initial test for start/stop times show that it's _not_ tied to the fragment size...
|
|
||||||
// - Implement mmap mode for ALSA.
|
|
||||||
// - Make device initialization more robust for ALSA
|
|
||||||
// - Clamp period sizes to their min/max.
|
|
||||||
// - Support rewinding. This will enable applications to employ better anti-latency.
|
// - Support rewinding. This will enable applications to employ better anti-latency.
|
||||||
// - Implement the null device.
|
// - Implement the null device.
|
||||||
|
// - Pass the log callback to mal_device_init().
|
||||||
|
// - Consider having some core formats which are guaranteed to work. Perhaps u8, s16 and
|
||||||
|
// f32 to cover the 8-, 16 and 32-bit ranges.
|
||||||
|
// - The rationale for this is to make it easier for
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ALSA
|
||||||
|
// ----
|
||||||
|
// - Fix device iteration.
|
||||||
|
// - Make device initialization more robust.
|
||||||
|
// - Need to have my test hardware working with plughw at a minimum.
|
||||||
|
// - Finish mmap mode for ALSA.
|
||||||
|
|
||||||
|
|
||||||
// DEVELOPMENT NOTES
|
// DEVELOPMENT NOTES
|
||||||
|
|||||||
Reference in New Issue
Block a user