Multiple ICE1712 Sound Cards
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.
Update (21 April 08): I've had a few reports that this stuff isn't working with
the current software. After testing alsa 1.0.16 and jack 0.109.2 with 2.6.25
kernel, I have found that everything works, but envy24control's
behaviour may cause some confusion.
See envy24control section for details.
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.
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. 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
To use a JACK version earlier than 0.102.20 with the above configuration it
will need to be compiled with
MMAP_COMPLEX support, in the form of Frank van de Pol's
MMAP_COMPLEX patch. (This is a
regenerated version of the original patch. It's been tested with JACK
0.100.7 and 0.101.1.)
The patch is not necessary with JACK 0.102.20 onwards, which already includes
MMAP_COMPLEX support.
After compiling JACK you might need to make this symlink (or similar)
so Ardour etc. can find libjack:
$ ln -s /usr/local/lib/libjack.so.0 /usr/lib/libjack.so.0
or on AMD64 with JACK 0.102.20 onwards:
$ ln -s /usr/local/lib64/libjack.so.0 /usr/lib/libjack.so.0
Alternatively, when configuring JACK before compilation,
specify --prefix=/usr which will install JACK in /usr instead of /usr/local.
You may have to experiment with different symlinks or --prefix options.
jackd can be started using the following command-line syntax:
$ jackd -d alsa -C multi_capture -P multi_playback
Obviously you'd add extra options as necessary.
You will also need this patch
if using any JACK version from 0.99.37 to 0.102.x
to prevent a floating point exception which kills jackd at seemingly random
times (it shows up in syslog as a divide trap error when it occurs).
This is necessary for x86 and x86_64, whatever sound card you are using.
The patch applies to 0.102.20, but can easily be applied
manually to other versions that require it (eg. 0.100.7 and 0.101.1).
It is not necessary with JACK 0.103.0 onwards.
jackdmp
An alternative to JACK is jackdmp, which was designed to use multiple
CPUs more effectively, but will still work with one CPU. Version 0.61
(still in
SVN
at time of writing)
or later is required; previous versions don't work with
pcm_multi. It doesn't need patching.
It is more sensitive to clock skew than jackd, so if you are
running at 88.2 or 96 kHz it might be necessary to clock all cards from an
external S/PDIF clock source. Daisy chaining several cards' S/PDIFs
might not be good enough (you'll probably get away with linking two cards, but
three could be too many).
Problems with pcm_multi
A change was made in alsa-lib-1.0.9rc1 which had the unintended effect of
preventing the pcm_multi plugin from working with jackd (or jackdmp)
in duplex mode, ie.
only the multi_capture or multi_playback device could be started, not both
at the same time. This problem still existed in alsa-lib-1.0.13, but has
been fixed in 1.0.14.
Here's a patch that
works around the problem in alsa-lib versions 1.0.10 to 1.0.13 (not necessary
with 1.0.14).
Users may also have problems using the -rt kernel with pcm_multi. At the time
of writing, the -rt kernel (2.6.17-rt8) gives lots of xruns when using
pcm_multi (that's on AMD64 SMP - on UP it locks up completely). It works fine
with a single sound card.
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.
Word 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 word clock output on the
first breakout box to the word clock input on the second box.
Alternatively, they can be linked via S/PDIF (connect the S/PDIF output on the
first card to the S/PDIF input on the second card).
Then use envy24control
from the alsa-tools package to set up the first card to use its internal clock
and the second card to use the word clock input or S/PDIF. Cards without word
clock in/out can be synchronized via the SPDIF in/out.
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
with 96kHz sample rate.
Something else to be aware of when syncing cards is that the word clock input
uses a 74HC4046 PLL chip, which is quite an efficient jitter generator. In
other words, you could use the best external word clock available and still get
jittery clocking. The S/PDIF input isn't perfect either, but it's better. The
unit that is using its internal clock will sound better than the slave
units, so use those channels for the most critical sounds.
If you really want to minimise jitter, it's worth replacing
the 3m long host cables with shorter ones to reduce the distance between
the clocks on the PCI cards and the converters in the rack box. I use 1m
IEEE 1284 25-pin male-male printer cables with a gender changer at the rack box
end. Don't confuse these with 25 pin RS232 cables which will not work.
The improvement in sound is subtle but quite noticeable (if you don't
have low resolution speakers and/or low resolution ears!).
Problems with envy24control
The version of envy24control in alsa-tools-1.0.10 can't read or set word clock
status with kernel 2.6.14 onwards (fixed in alsa-tools-1.0.11). If
envy24control is started from an xterm
a slew of error messages saying `Unable to determine work clock status'
scrolls off the xterm. A patch to fix it is
available here
(Thanks to Takashi Iwai). Note that this stops it being able to read or set
word clock in kernel 2.6.13 or earlier.
A further note: this problem seems to occur with several different combinations
of alsa-driver and alsa-tools. If it happens, 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.
There's a couple of other minor bugs in the alsa-tools-1.0.10 version of
envy24control:
The button for setting Word Clock
doesn't work unless the S/PDIF In button is clicked first.
Slightly more serious, the word clock `Locked' indicator in envy24control from
alsa-tools 1.0.10 (also back to 1.0.8 and possibly earlier) is faulty.
When syncing via BNC word clock in/out connectors
it says `No Signal' when it's locked, and `Locked' when there's no signal.
Here's a patch
that fixes it in alsa-tools-1.0.10. It's fixed in 1.0.11.
Note: In alsa-tools-1.0.10 envy24control cannot sync Delta1010LT cards
via the wordclock input. S/PDIF is the only sync method that works
with these cards, and it only works if an external S/PDIF device is connected
to the first 1010LT's S/PDIF input to provide a clock signal. (Delta 1010 is
not affected by this). This is fixed in alsa-tools-1.0.11 (thanks to Doug
McLain).
When syncing via S/PDIF, there's no indication to show if it's locked or
unlocked. If it's locked jackd runs, if there's no signal it doesn't run.
It's not necessary to have the S/PDIF inputs and outputs enabled in .asoundrc
to use them for synchronizing.
Update: On Delta 1010LT, the word clock `Locked' indicator now shows
if the card is synced to the S/PDIF input. It also shows `Locked' when
internal clock is selected. Some distros, eg. FC5, already include these
changes. (Thanks to Doug McLain).
Update 21 April 2008: Some users have been getting confused about
envy24control's behaviour when jackd is running. In the version of
envy24control (0.6.0) in alsa-tools-1.0.12
to 1.0.16, 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
(/etc/asound.state by default) 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.
Mastering with Jamin
If you are using Jamin with jackd to master a recording, you will probably
notice that Jamin indicates a lot of xruns when using pcm_multi, even with
large period sizes. As long as no xruns are indicated by the alsa driver this
seems to be harmless - it appears to be a quirk in jackd's xrun reporting
mechanism. (Qjackctl users have reported a similar effect). To be on the safe
side, jackd can be restarted with only one sound card if less inputs and
outputs are required while mastering.
An alternative is to use Jamin with jackdmp, which (at least on an SMP system)
doesn't suffer from this problem.
Debian 3.1 Problems
Users of Debian 3.1 might be feeling smug because they have a working
version of alsa-lib (1.0.8).
Unfortunately the version of libc6 in
3.1 has the well-known NPTL bug which prevents threaded applications
(ie. lots of audio apps) from performing properly.
JACK was changed to work around this,
and the version in Debian 3.1 includes this change. Other apps including jackd
clients are likely to be affected, however. A workaround is to set
LD_ASSUME_KERNEL=2.4.22 for affected programs (see
here for details).
This is a kludge and might have other side effects.
Updating to Debian 4.0 is recommended.
Debian 4.0 Problems
At the time of writing, I've been unable to get realtime priorities working with
Debian 4.0 (Etch) using /etc/security/limits.conf. I'm using the
realtime-lsm
module instead. This is deprecated (and no longer appears to be usable on very
recent kernels), but it still works with the 2.6.20 kernel. The alternative on
more recent kernels is
set_rlimits.