Multiple Sound Cards (ICE1712/Delta 1010)


Index

Français/French translation of this page

ICE1712 based sound cards like the M-Audio Delta 1010 are a popular choice for Linux sound recording. However, setting up several of them so that ALSA and jackd will play nicely is a little tricky.

This tutorial assumes a certain level of familiarity with Linux audio configuration. As I said, using multiple sound cards with Linux and ALSA is tricky, so much so that it is officially `not recommended' by the JACK and Ardour developers. Please read the whole page before you try any of it.

ALSA .asoundrc

The ALSA pcm_multi plugin is used to merge several cards into one large virtual card. This allows programs like jackd, which can only handle one card at a time, to deal with them. This isn't completely straightforward with the ICE1712 chip, as it has 12 inputs and 10 outputs (regardless of how many hardware inputs/outputs your card has). This means that separate devices need to be defined in the .asoundrc file for capture and playback. Here's an example .asoundrc for two Delta 1010s used for 16 channels of input and output:

# .asoundrc for two Delta 1010s
#
# Create virtual devices out of multiple soundcards.
# JACK will need MMAP_COMPLEX support to use this. 
# ICE1712 chip has 12 capture channels and 10 playback channels.
# No. of channels in slaves must equal 12 for capture and 10 for playback
# otherwise "invalid argument" errors result.
#
# Note that jackd ignores the -r (sample rate) command line
# option when using pcm_multi. Sample rate must be set
# manually using alsactl or envy24control before starting
# jackd.

pcm.multi_capture {
	type multi
	slaves.a.pcm hw:0 
	slaves.a.channels 12
	slaves.b.pcm hw:1
	slaves.b.channels 12

# First 8 channels of first soundcard (capture)
 	bindings.0.slave a
 	bindings.0.channel 0
 	bindings.1.slave a
 	bindings.1.channel 1
 	bindings.2.slave a
 	bindings.2.channel 2
 	bindings.3.slave a
 	bindings.3.channel 3
 	bindings.4.slave a
 	bindings.4.channel 4
 	bindings.5.slave a
 	bindings.5.channel 5
 	bindings.6.slave a
 	bindings.6.channel 6
 	bindings.7.slave a
 	bindings.7.channel 7
    
# First 8 channels of second soundcard (capture)
 	bindings.8.slave b
 	bindings.8.channel 0
 	bindings.9.slave b
 	bindings.9.channel 1
 	bindings.10.slave b
 	bindings.10.channel 2
 	bindings.11.slave b
 	bindings.11.channel 3
 	bindings.12.slave b
 	bindings.12.channel 4
 	bindings.13.slave b
 	bindings.13.channel 5
 	bindings.14.slave b
 	bindings.14.channel 6
 	bindings.15.slave b
 	bindings.15.channel 7

# S/PDIF section. Uncomment bindings if required.

# S/PDIF first soundcard (capture)
 	#bindings.16.slave a
 	#bindings.16.channel 8
 	#bindings.17.slave a
 	#bindings.17.channel 9
    
# S/PDIF second soundcard (capture)
 	#bindings.18.slave b
 	#bindings.18.channel 8
 	#bindings.19.slave b
 	#bindings.19.channel 9
}

ctl.multi_capture {
	type hw
	card 0
}

pcm.multi_playback {
	type multi
	slaves.a.pcm hw:0
	slaves.a.channels 10
	slaves.b.pcm hw:1
	slaves.b.channels 10

# First 8 channels of first soundcard (playback)
 	bindings.0.slave a
 	bindings.0.channel 0
 	bindings.1.slave a
 	bindings.1.channel 1
 	bindings.2.slave a
 	bindings.2.channel 2
 	bindings.3.slave a
 	bindings.3.channel 3
 	bindings.4.slave a
 	bindings.4.channel 4
 	bindings.5.slave a
 	bindings.5.channel 5
 	bindings.6.slave a
 	bindings.6.channel 6
 	bindings.7.slave a
 	bindings.7.channel 7

# First 8 channels of second soundcard (playback)
 	bindings.8.slave b
 	bindings.8.channel 0
 	bindings.9.slave b
 	bindings.9.channel 1
 	bindings.10.slave b
 	bindings.10.channel 2
 	bindings.11.slave b
 	bindings.11.channel 3
 	bindings.12.slave b
 	bindings.12.channel 4
 	bindings.13.slave b
 	bindings.13.channel 5
 	bindings.14.slave b
 	bindings.14.channel 6
 	bindings.15.slave b
 	bindings.15.channel 7

# S/PDIF section. Uncomment bindings if required.

# S/PDIF first soundcard (playback)
 	#bindings.16.slave a
 	#bindings.16.channel 8
 	#bindings.17.slave a
 	#bindings.17.channel 9
    
# S/PDIF second soundcard (playback)
 	#bindings.18.slave b
 	#bindings.18.channel 8
 	#bindings.19.slave b
 	#bindings.19.channel 9
}

ctl.multi_playback {
	type hw
	card 0
}


Here's another example .asoundrc for three Delta 1010's. It allows either the first two cards or all three to be run depending on the device names used when starting JACK.

The above .asoundrc's require MMAP_COMPLEX support in JACK (any version later than 0.102.20 has this). It is possible to use the ALSA route plugin to interleave the blocks of channels so MMAP_COMPLEX isn't needed, but the extra overhead of the route plugin will increase latency (in fact it completely screws up low latency operation). If this doesn't bother you, there's an example .asoundrc here.


JACK

This tutorial assumes the use of JACK 1, version 0.116.1 or later.

jackd can be started using the following command-line syntax:
$ jackd -d alsa -C multi_capture -P multi_playback

Note that jackd ignores the -r (sample rate) command line option when using pcm_multi, despite what its startup messages say. Sample rate must be set manually, eg. using envy24control, before starting jackd. Actual sample rate can be checked with the 'jack_samplerate' command once jackd is running.

Older versions of jackd needed the -R option to run with realtime privileges but this is now the default:
$ jackd -R -d alsa -C multi_capture -P multi_playback
Recent versions of jackd need the -r option to run without realtime privileges (eg. when troubleshooting):
$ jackd -r -d alsa -C multi_capture -P multi_playback
Obviously you'd add extra options as necessary.

UPDATE: At time of writing, recent versions of JACK 2 also work well with pcm_multi.


qjackctl

qjackctl will not work with pcm_multi virtual devices as there is no way to tell it to use them. You need to use the command line to start jackd. If you need a connection manager, patchage works well, or for simpler setups njconnect also works well.


Problems with pcm_multi

Users may have problems using the -rt kernel with pcm_multi. The versions of -rt that I've tried in the past gave lots of xruns when using pcm_multi (that's on AMD64 SMP - on UP it locked up completely). It works fine with a single sound card. Recent linux kernels do work well with preemption enabled (CONFIG_PREEMPT=y) and no -rt patch however.

Update - There have been reports that -rt kernels work with jackd and pcm_multi on AMD64x2 dual core systems, but so far I have been unable to confirm this on my own hardware.


Clock Sync

To run multiple cards the word clocks need to be synchronized. With two Delta 1010 cards this can be done by connecting the S/PDIF output on the first card to the S/PDIF input on the second. Alternatively, the word clock output on the first breakout box can be connected to the word clock input on the second box.

Then use envy24control from the alsa-tools package to set up the first card to use its internal clock and the other card(s) to use the S/PDIF or word clock input.

If you have more than two cards you can either daisy chain them by linking the third card to the second etc., or make a multi-way splitter cable for the first card's S/PDIF output. I've successfully used a three way S/PDIF splitter to link three cards to the first one (more than that might not work due to the extra load attenuating the signal too far).

IMPORTANT: Always remember to check the slave cards are set to get their clock from the S/PDIF or word clock inputs (and the clock sync cables are connected) before starting jackd. It may not be immediately obvious if you forget. Typical symptoms range from xrun messages slewing off the text terminal to jackd CPU load creeping slowly upwards along with audible dropouts but no error messages. JACK 2 tends to output lots of CheckSize and CheckRead errors.

Some distros might remember the clock settings beween boots, but this can change between versions so always check after an upgrade.


Problems with Delta 1010 Word Clock Sync

The English edition of the Delta 1010 manual gives the maximum word clock input frequency as 50kHz. This looks like it could be a typo but unfortunately it isn't. The phase locked loop (PLL) that is used to lock onto the word clock input signal can't go to a high enough frequency to lock to 96kHz. You might be lucky and find that your particular cards work beyond specification, but it isn't something you should rely on.

The S/PDIF receiver on the other hand uses its own internal PLL which works fine at 96kHz sample rate.

For those with good electronics skills who want to improve the 1010's clocking here's a page showing some possible modifications.


Problems with envy24control

If something in envy24control doesn't work, make sure the version of alsa in your kernel matches your version of alsa-tools/envy24control. If they do match and the problem still occurs, it's a bug and should be reported on the alsa-devel mailing list.

Some users get confused about envy24control's behaviour when jackd is running. The sample rate buttons in the `Master Clock' section do not necessarily indicate the correct sample rate when jackd is running, but the `Actual Rate' window is correct. The sample rate buttons are disabled when jackd is running, but `S/PDIF in' and `Word Clock' buttons work. If you select one of the latter two while jackd is running, you will not be able to go back to internal clock without stopping jackd. The obvious solution is not to mess with clock sources or sample rates while jackd is running.


Alternative to envy24control

All of the parameters set by envy24control can be set on the command line using alsactl. This command uses a configuration file (/var/lib/alsa/asound.state by default on Debian) to load the parameters. There's an example asound.state file here for two Delta 1010s running at 44.1kHz default frequency and using S/PDIF to sync the clocks, first card master, second card slave. To use it run this command:
alsactl -f asound.state.delta1010x2 restore
This will load the parameters from the file. To change anything edit the file and rerun the command. If you set up your cards with envy24control initially, the settings can be stored:
alsactl -f asound.state.delta1010x2 store
This overwrites the file if it already exists, so make a copy first if you want to save the original.


JACK reports xruns

JACK clients like Ardour are likely to indicate xruns when using pcm_multi. At first I was concerned about this, but it doesn't appear to cause any audible effects. I've never noticed any clicks, and haven't been able to find any discontinuities when inspecting sample values in recorded files. Note that this does not apply to xruns reported by the ALSA driver, which are real and will be audible. I run Ardour with xrun markers disabled in the `Misc Options' menu when using pcm_multi to avoid the annoyance of seeing hundreds of xrun markers when nothing is wrong with the sound. If this causes you serious concern, the only way to avoid it is to use a single interface card.

The problem is caused by the way ALSA polls the sound devices and is unlikely to be fixed. Here's a thread on the alsa-devel mailing list discussing the issue.

Top of Page    Index    Contact

Last updated April 15 2019