Support wrong-endian ALSA output
This commit is contained in:
parent
05693e2d5d
commit
49ede85827
|
@ -183,6 +183,19 @@ get_bitformat(const struct audio_format *af)
|
|||
return SND_PCM_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
static snd_pcm_format_t
|
||||
byteswap_bitformat(snd_pcm_format_t fmt)
|
||||
{
|
||||
switch(fmt) {
|
||||
case SND_PCM_FORMAT_S16_LE: return SND_PCM_FORMAT_S16_BE;
|
||||
case SND_PCM_FORMAT_S24_LE: return SND_PCM_FORMAT_S24_BE;
|
||||
case SND_PCM_FORMAT_S32_LE: return SND_PCM_FORMAT_S32_BE;
|
||||
case SND_PCM_FORMAT_S16_BE: return SND_PCM_FORMAT_S16_LE;
|
||||
case SND_PCM_FORMAT_S24_BE: return SND_PCM_FORMAT_S24_LE;
|
||||
case SND_PCM_FORMAT_S32_BE: return SND_PCM_FORMAT_S32_LE;
|
||||
default: return SND_PCM_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set up the snd_pcm_t object which was opened by the caller. Set up
|
||||
* the configured settings and the audio format.
|
||||
|
@ -208,7 +221,6 @@ alsa_setup(struct alsa_data *ad, struct audio_format *audio_format,
|
|||
configure_hw:
|
||||
/* configure HW params */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
cmd = "snd_pcm_hw_params_any";
|
||||
err = snd_pcm_hw_params_any(ad->pcm, hwparams);
|
||||
if (err < 0)
|
||||
|
@ -236,14 +248,39 @@ configure_hw:
|
|||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, bitformat);
|
||||
if (err == -EINVAL &&
|
||||
byteswap_bitformat(bitformat) != SND_PCM_FORMAT_UNKNOWN) {
|
||||
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
|
||||
byteswap_bitformat(bitformat));
|
||||
if (err == 0) {
|
||||
g_debug("ALSA device \"%s\": converting %u bit to reverse-endian\n",
|
||||
alsa_device(ad), audio_format->bits);
|
||||
audio_format->reverse_endian = 1;
|
||||
}
|
||||
}
|
||||
if (err == -EINVAL && (audio_format->bits == 24 ||
|
||||
audio_format->bits == 16)) {
|
||||
/* fall back to 32 bit, let pcm_convert.c do the conversion */
|
||||
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
|
||||
SND_PCM_FORMAT_S32);
|
||||
if (err == 0)
|
||||
if (err == 0) {
|
||||
g_debug("ALSA device \"%s\": converting %u bit to 32 bit\n",
|
||||
alsa_device(ad), audio_format->bits);
|
||||
audio_format->bits = 32;
|
||||
}
|
||||
}
|
||||
if (err == -EINVAL && (audio_format->bits == 24 ||
|
||||
audio_format->bits == 16)) {
|
||||
/* fall back to 32 bit, let pcm_convert.c do the conversion */
|
||||
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
|
||||
byteswap_bitformat(SND_PCM_FORMAT_S32));
|
||||
if (err == 0) {
|
||||
g_debug("ALSA device \"%s\": converting %u bit to 32 bit backward-endian\n",
|
||||
alsa_device(ad), audio_format->bits);
|
||||
audio_format->bits = 32;
|
||||
audio_format->reverse_endian = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == -EINVAL && audio_format->bits != 16) {
|
||||
/* fall back to 16 bit, let pcm_convert.c do the conversion */
|
||||
|
@ -255,6 +292,17 @@ configure_hw:
|
|||
audio_format->bits = 16;
|
||||
}
|
||||
}
|
||||
if (err == -EINVAL && audio_format->bits != 16) {
|
||||
/* fall back to 16 bit, let pcm_convert.c do the conversion */
|
||||
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
|
||||
byteswap_bitformat(SND_PCM_FORMAT_S16));
|
||||
if (err == 0) {
|
||||
g_debug("ALSA device \"%s\": converting %u bit to 16 bit backward-endian\n",
|
||||
alsa_device(ad), audio_format->bits);
|
||||
audio_format->bits = 16;
|
||||
audio_format->reverse_endian = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
g_set_error(error, alsa_output_quark(), err,
|
||||
|
|
Loading…
Reference in New Issue