AC3 5.1 surround sound without passthrough, simultaneous output to both SPDIF and HDMI

Using XBMC Eden on Ubuntu 12.04 (precise pangolin) has been a very positive experience so far, including Live TV. Except for the TV remote (to turn the screen on and off), there's only one controller left that we use - the one for the Linux box running XBMC. Previously we needed another one for the audio receiver, as XBMC wasn't able to adjust the volume of passthrough sound, but that's no longer the case.

The idea is, that XBMC decodes everything into up to six channels (depending on the input source), adjusts the volume, and outputs the channels on a virtual 5.1 device, that encodes the channels into the AC3 format, as required by audio receivers/amplifiers. Passthrough will not be used anymore, but XBMC will be configured to decode and adjust all audio streams using the CPU.

Here I want to share the configuration I use on my Asrock ION 330HT-BD.

First of all, you need to install the A52 plugin for the ALSA sound system, as it's not provided by the Ubuntu distribution. A good howto can be found here:

The A52 plugin is required to provide the virtual 6-channel device that encodes into the AC3 format as required for the audio receivers.
From the HowTo above, only the section "Building/Installing Required a52 Plugin" is required.

The follwing code should be saved as a file ~/.asoundrc in the directory of the user running XBMC. It configures a default device ("both") to accept six channels, and output them to both HDMI and SPDIF.

The audio going to HDMI is downmixed to two channels. Reason is that most TV sets handle stereo HDMI audio, but fail if they receive more than two channels, or if the channels are encoded. Even passthrough from HDMI to SPDIF doesn't work with most TVs.

The audio going to SPDIF is AC3 encoded 5.1 sound.

pcm.a52encode {
  type rate
  slave {
    pcm {
      type a52
      bitrate 448
      channels 6
      card 0
    rate 48000

pcm.hdmi "hw:0,3"

pcm.51to20 {
     type route
     slave.pcm hdmi

     slave.channels 6

     ttable.0.0 1
     ttable.1.1 1
     ttable.2.0 0.707
     ttable.3.1 0.707
     ttable.4.0 0.5
     ttable.4.1 0.5
     ttable.5.0 0.5
     ttable.5.1 0.5

pcm.both {
	type route

	slave.channels 12

	slave.pcm {
		type multi;
		slaves.a.pcm "a52encode"
		slaves.a.channels 6;

		slaves.b.pcm "51to20"
		slaves.b.channels 6;

		bindings.0.slave a; 0;
		bindings.1.slave a; 1;
		bindings.2.slave a; 2;
		bindings.3.slave a; 3;
		bindings.4.slave a; 4;
		bindings.5.slave a; 5;

		bindings.6.slave b; 0;
		bindings.7.slave b; 1;
		bindings.8.slave b; 2;
		bindings.9.slave b; 3;
		bindings.10.slave b; 4;
		bindings.11.slave b; 5;
	ttable.0.0 1;
	ttable.1.1 1;
	ttable.2.2 1;
	ttable.3.3 1;
	ttable.4.4 1;
	ttable.5.5 1;

	ttable.0.6 1;
	ttable.1.7 1;
	ttable.2.8 1;
	ttable.3.9 1;
	ttable.4.10 1;
	ttable.5.11 1;

pcm.default "both"

To completely disable HDMI sound, pcm.default must be set to "pcm.a52encode" instead.

Finally, we need to configure XBMC. This has to be done in its System => Settings => System => Audio output.
Set "Audio output" to "Analog", "Speaker Configuration" to "5.1", "Audio output device" to "Custom" and "Custom audio device" to "both".

That's all. If everything's correct, and XBMC plays input with 5.1 sound, the receiver should also get 5.1 sound, while the volume can be controlled in XBMC :-)

Add new comment