mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 01:04:02 +02:00
ALSA: Fix an error with channel mapping.
This commit is contained in:
@@ -6018,10 +6018,40 @@ static mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type t
|
|||||||
// instead just do it ourselves.
|
// instead just do it ourselves.
|
||||||
snd_pcm_chmap_t* pChmap = ((mal_snd_pcm_get_chmap_proc)pContext->alsa.snd_pcm_get_chmap)((snd_pcm_t*)pDevice->alsa.pPCM);
|
snd_pcm_chmap_t* pChmap = ((mal_snd_pcm_get_chmap_proc)pContext->alsa.snd_pcm_get_chmap)((snd_pcm_t*)pDevice->alsa.pPCM);
|
||||||
if (pChmap != NULL) {
|
if (pChmap != NULL) {
|
||||||
mal_assert(pChmap->channels == pDevice->internalChannels);
|
// There are cases where the returned channel map can have a different channel count than was returned by snd_pcm_hw_params_set_channels_near().
|
||||||
|
if (pChmap->channels >= pDevice->internalChannels) {
|
||||||
|
// Drop excess channels.
|
||||||
for (mal_uint32 iChannel = 0; iChannel < pDevice->internalChannels; ++iChannel) {
|
for (mal_uint32 iChannel = 0; iChannel < pDevice->internalChannels; ++iChannel) {
|
||||||
pDevice->internalChannelMap[iChannel] = mal_convert_alsa_channel_position_to_mal_channel(pChmap->pos[iChannel]);
|
pDevice->internalChannelMap[iChannel] = mal_convert_alsa_channel_position_to_mal_channel(pChmap->pos[iChannel]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Excess channels use defaults. Do an initial fill with defaults, overwrite the first pChmap->channels, validate to ensure there are no duplicate
|
||||||
|
// channels. If validation fails, fall back to defaults.
|
||||||
|
|
||||||
|
// Fill with defaults.
|
||||||
|
mal_get_default_channel_mapping(pDevice->pContext->backend, pDevice->internalChannels, pDevice->internalChannelMap);
|
||||||
|
|
||||||
|
// Overwrite first pChmap->channels channels.
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < pChmap->channels; ++iChannel) {
|
||||||
|
pDevice->internalChannelMap[iChannel] = mal_convert_alsa_channel_position_to_mal_channel(pChmap->pos[iChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate.
|
||||||
|
mal_bool32 isValid = MAL_TRUE;
|
||||||
|
for (mal_uint32 i = 0; i < pDevice->internalChannels && isValid; ++i) {
|
||||||
|
for (mal_uint32 j = i+1; j < pDevice->internalChannels; ++j) {
|
||||||
|
if (pDevice->internalChannelMap[i] == pDevice->internalChannelMap[j]) {
|
||||||
|
isValid = MAL_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If our channel map is invalid, fall back to defaults.
|
||||||
|
if (!isValid) {
|
||||||
|
mal_get_default_channel_mapping(pDevice->pContext->backend, pDevice->internalChannels, pDevice->internalChannelMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(pChmap);
|
free(pChmap);
|
||||||
pChmap = NULL;
|
pChmap = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user