[vlc-commits] ALSA: improve (and uglify) channels configuration selection
Rémi Denis-Courmont
git at videolan.org
Tue Sep 27 22:40:36 CEST 2011
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Sep 27 23:23:44 2011 +0300| [c40ffdfe072dcb885b4f3f8b562ac750e1f1c569] | committer: Rémi Denis-Courmont
ALSA: improve (and uglify) channels configuration selection
Unfortunately, I cannot see how not to second guess ALSA as some
devices exhibit inconsistent hardware configuration spaces
(namely front, surround41 and surround50). Also I do not know any
API to query the order of channels.
Note that 7.1 is not supported but it could be added with some extra
reordering code.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c40ffdfe072dcb885b4f3f8b562ac750e1f1c569
---
modules/audio_output/alsa.c | 91 +++++++++++++++++++++++++++++++++++++-----
1 files changed, 80 insertions(+), 11 deletions(-)
diff --git a/modules/audio_output/alsa.c b/modules/audio_output/alsa.c
index 1d1bfa3..f4ca1fc 100644
--- a/modules/audio_output/alsa.c
+++ b/modules/audio_output/alsa.c
@@ -393,18 +393,45 @@ static int Open (vlc_object_t *obj)
}
/* Set channels count */
- val = snd_pcm_hw_params_set_channels (pcm, hw, channels);
- if (val && channels != 2) /* Fallback to stereo */
- {
- val = snd_pcm_hw_params_set_channels (pcm, hw, 2);
- channels = 2;
- }
- if (val)
+ unsigned chans;
+ /* By default, ALSA plug will discard extra channels and zero missing ones
+ * instead of remixing, so remixing was disabled at snd_pcm_open() above.
+ * Then, the configuration space will contain only channels configurations
+ * supported by the audio device, but not necessarily functional (e.g.
+ * surround-capable card with stereo speakers). */
+ /* If there is only channels configuration, use that one.
+ * This should deal with "surround40", "surround51" and "surround71". */
+ if (snd_pcm_hw_params_get_channels (hw, &chans) == 0)
+ ;
+ /* Otherwise, if we have 5 channels and they are supported, use that.
+ * This should deal with "surround41" and "surround50" routers.
+ * This assumes that no real hardware supports exactly 5 channels. */
+ else if (channels == 5
+ && snd_pcm_hw_params_set_channels (pcm, hw, channels))
+ chans = channels;
+ /* Otherwise, if stereo is supported, then use that. This deals with
+ * the "front" device that fails to enforce stereo on Surround cards. */
+ else if (snd_pcm_hw_params_set_channels (pcm, hw, 2) == 0)
+ chans = 2;
+ /* Out of desperation, try the original channels count. */
+ else if (snd_pcm_hw_params_set_channels (pcm, hw, channels) == 0)
+ ;
+ /* As last chance, try anything. */
+ else
{
- msg_Err (aout, "cannot set channels count: %s", snd_strerror (val));
- goto error;
+ chans = channels;
+ val = snd_pcm_hw_params_set_channels_near (pcm, hw, &chans);
+ if (val)
+ {
+ msg_Err (aout, "cannot set channels count: %s",
+ snd_strerror (val));
+ goto error;
+ }
}
+ if (channels != chans)
+ msg_Dbg (aout, "remixing from %u to %u channels", channels, chans);
+
/* Set sample rate */
unsigned rate = aout->format.i_rate;
val = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, NULL);
@@ -484,11 +511,53 @@ static int Open (vlc_object_t *obj)
goto error;
}
+ /* Guess the channel map */
+ switch (chans)
+ {
+ case 1:
+ chans = AOUT_CHAN_CENTER;
+ break;
+ case 2: /* front */
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ break;
+ case 4: /* surround40 */
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
+ break;
+ case 5: /* surround50 ... or surround41! Uho! */
+#if 1
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_LFE;
+#else
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER;
+#endif
+ break;
+ case 6: /* surround51 */
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
+ break;
+#if 0 /* FIXME reorder */
+ case 8: /* surround71 */
+ chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER | AOUT_CHAN_LFE
+ | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
+ break;
+#endif
+ default:
+ msg_Err (aout, "unknown %u channels configuration", chans);
+ goto error;
+ }
+
/* Setup audio_output_t */
aout->format.i_format = fourcc;
aout->format.i_rate = rate;
- if (channels == 2)
- aout->format.i_physical_channels = AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT;
+ aout->format.i_original_channels =
+ aout->format.i_physical_channels = chans;
if (spdif)
{
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
More information about the vlc-commits
mailing list