Jack and ALSA: sound through multiple devices

I have designed a simple audio-video solution for my entertainment room at home, where I have a:

  • High quality headphones connected to a decent pre/post amplifier which connects to the computer through USB (and registers as USB audio device with my Windows10 and Gentoo linux).
  • Not so high (but not bad at all!) on-board sound chip provided with my motherboard – this one I’d like to connect to my TV.

The goal is to have sound via the on-board card to the TV for less demanding tasks, such as watching movies and have sound go via USB to the amp while when I listen to music.

After some reseach it appears ALSA on its own cannot do this job, but Jack can be used. At first I did not like the overhead, but quickly realised it is minimal. The below howto is based on JACK. On the 4.3 kernel (no -rt stuff since most of the good work for real time processing is long in the mainline kernel), it works well.

First of all it is good to ensure all packages are build with jack support (and USE flags in Gentoo make this a trivial task) and install the Jack daemon (jackd). Now, for some reason it is a daemon that does not have a startup script, so you’ll need to figure out how you want to start it – for me it ended up in the xfce session controller (so it starts with my user ID when I log in) – but you can write a script too, just ensure it depends on alsasound.

There is a gotcha here – for running the jackd without root privileges, you need to edit limtis.conf to give the audio group rt permissions:

Code:
root@ryba ~ # grep audio /etc/security/limits.conf
@audio      –  rtprio          99
@audio      –  memlock      unlimited
@audio      –  nice      -10


And of course, have your user in the audio group. As always with groups – for them to take effect, all sessions must be finished and re-started.

Now, trick is you still need alsasound daemon running and a proper /etc/asound.conf which mixes multiple devices. Basically the following config works for the first two sound cards, because it uses the indexes instead of the device names (you get those from aplay -l. An exception is with the last config section, because it is apparently a dummy control, alsa needs it):

Code:
root@ryba ~ # cat /etc/asound.conf
pcm.both {
type route;
slave.pcm {
type multi;
slaves.a.pcm “plughw:0,0”
slaves.b.pcm “plughw:1,0”
slaves.a.channels 2;
slaves.b.channels 2;
bindings.0.slave a;
bindings.0.channel 0;
bindings.1.slave a;
bindings.1.channel 1;
bindings.2.slave b;
bindings.2.channel 0;
bindings.3.slave b;
bindings.3.channel 1;
}
ttable.0.0 1;
ttable.1.1 1;
ttable.0.2 1;
ttable.1.3 1;
}pcm.jack {
type jack
playback_ports {
0 system:playback_1
1 system:playback_2
}
capture_ports {
0 system:capture_1
1 system:capture_2
}
}

pcm.!default {
type plug;
slave.pcm “jack”;
}

ctl.!default {
type hw;
card 0;
}

Next, I need to tell jack to start WITH this config too, so my line that starts it under xfce session starter is as follows:

Code:
/usr/bin/jackd -d alsa -P both

Explanation: run jackd using -Device alsa and -Playback both – because that’s how my device is named in /etc/asound.conf: pcm.both

Final step is to tell your software, such as mplayer, moc music on console, or whatever else you use, to switch from alsa to jack – that’s fairly easy, just rtfm, however you can also leave it as alsa, since this one is routed into the jack as well, making jackd the catch-all solution. It is quite important to do so because if you use Firefox and would like sound from flash and HTML5, FF will first try pulseaudio and if it is not present (like in my case, because I don’t want that overhead), then it will try alsa – but not jack and there is no config handle for that. So the above config basically uses jackd every time something tries to use alsa.

Needed: alsa-plugins, jack-audio-connection-kit
Not needed: alsa_out, qjackctl (the gui thing), gst-plugins-alsa, pulseaudio