- when more than one application was playing sound, the first one played nicely but the others wasn't playing at all, complaining about a "busy resource"
- solved this one, I had to setup the whole thing to work with two sound cards at the same time
- eventually, I wanted to enable concurrent sound for multiple users
pcm.USBmic {
type hw
card CNF8215
}
ctl.USBmic {
type hw
card CNF8215
}
pcm.internal {
type hw
card SB
}
ctl.internal {
type hw
card SB
}
pcm.wireless {
type hw
card Transceiver
}
ctl.wireless {
type hw
card Transceiver
}
pcm.internalDmixed {
type dmix
ipc_key 1024
ipc_key_add_uid false
ipc_perm 0666
slave {
pcm "internal"
period_time 0
period_size 2048
channels 4
}
bindings {
0 0
1 1
2 2
3 3
}
}
pcm.wirelessDmixed {
type dmix
ipc_key 2048
ipc_key_add_uid false
ipc_perm 0666
slave {
pcm "wireless"
period_time 0
period_size 2048
channels 2
}
bindings {
0 0
1 1
}
}
pcm.both {
type route;
slave.pcm {
type multi;
slaves.a.pcm "wirelessDmixed";
slaves.b.pcm "internalDmixed";
slaves.a.channels 2;
slaves.b.channels 4;
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;
bindings.4.slave b;
bindings.4.channel 2;
bindings.5.slave b;
bindings.5.channel 3;
}
ttable.0.0 1;
ttable.1.1 1;
ttable.0.2 1;
ttable.1.3 1;
ttable.2.4 1;
ttable.3.5 1;
}
pcm.!default {
type plug
slave {
pcm both
}
}
ctl.!default {
type hw
card SB
}
How does this strange thing work? Let's look at it step by step:
Understanding which cards you want to use
To get your cards names, the easiest way is to use aplay -l command. When I execute it I get this output:
:~$ aplay -lIf you use your card's name as reference for alsa is better, because it will always connect to the right card no matter what the cards' order is. Above the card names are the ones I bolded (yours will be different).
**** List of PLAYBACK Hardware Devices ****
card 0: Transceiver [2.4G Wireless Transceiver], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 2: SB [HDA ATI SB], device 0: ALC662 rev1 Analog [ALC662 rev1 Analog]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 2: SB [HDA ATI SB], device 1: ALC662 rev1 Digital [ALC662 rev1 Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 3: HDMI [HDA ATI HDMI], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
As you can see, I have a lot of devices here, but the ones I care about are the first two, Transceiver and SB. SB is the internal card, with four speakers plugged, and Transceiver is a USB wireless sound card, transmitting to two speakers in another room.
Setup basic pcms
Once you know your card's names, you have to setup basic hardware pcms and ctls. A pcm is an input/output device, and a ctl is a control for a device. So I wrote this:
pcm.USBmic {As you can see there are one pcm and one ctl for each card I want to use, defined by type.devicename. So now if I want to output sound on my internal card I can use aplay -Dinternal sound.wav (thanks to pcm), and alsamixer -Dinternal to manage the volume only for that card (thanks to ctl).
type hw
card CNF8215
}
ctl.USBmic {
type hw
card CNF8215
}
pcm.internal {
type hw
card SB
}
ctl.internal {
type hw
card SB
}
pcm.wireless {
type hw
card Transceiver
}
ctl.wireless {
type hw
card Transceiver
}
Dmix: concurrent sound from more than one application
Now we have all this pcms, but we still have that resource busy error hanging around. How do we solve it? We setup a few more pcms:
pcm.internalDmixed {Here I define two more pcms, using the previously defined ones as slaves. In this way I can use dmix to mix various outputs channels and get rid of that awful resource busy error.
type dmix
ipc_key 1024
ipc_key_add_uid false
ipc_perm 0666
slave {
pcm "internal"
period_time 0
period_size 2048
channels 4
}
bindings {
0 0
1 1
2 2
3 3
}
}
pcm.wirelessDmixed {
type dmix
ipc_key 2048
ipc_key_add_uid false
ipc_perm 0666
slave {
pcm "wireless"
period_time 0
period_size 2048
channels 2
}
bindings {
0 0
1 1
}
}
More than one user?
This one was hard to find but easy to apply. If you look at the two dmixed pcms you will see two lines, "ipc_key_add_uid false" and "ipc_perm 0666". The first one disables user id for the device (or so I suppose) and the second one sets permissions for the device. The two combined makes the device usable for more than one user at the same time.
Multiple outputs on multiple cards
And here comes the difficult part: getting these two cards to output concurrent sound. How to do it? Luckily I found a good article about it, and after trying and trying again I ended up merging everything together. The trick here is creating another pcm device, named "both", to merge the two dmixed devices:
pcm.both {Aaaand... it has surround too! You can try it using the command "speaker-test -c6 -D both -t wav". Here you define a 6-channel device, using the two channels of the first sound card as the first two channels (0-1) and the four channels of the second sound card as the last four channels (2-5). Then using ttable the four channels of the second sound card are copied to the first four channels, so we will have the same otput on the first card and at the same time on the two front speakers of the second card. The last two channels, front center and rear center, will not output sound ad all, but I didn't understand how to change this pcm into a 4-channel one (comments are welcome).
type route;
slave.pcm {
type multi;
slaves.a.pcm "wirelessDmixed";
slaves.b.pcm "internalDmixed";
slaves.a.channels 2;
slaves.b.channels 4;
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;
bindings.4.slave b;
bindings.4.channel 2;
bindings.5.slave b;
bindings.5.channel 3;
}
ttable.0.0 1;
ttable.1.1 1;
ttable.0.2 1;
ttable.1.3 1;
ttable.2.4 1;
ttable.3.5 1;
}
If all the 6 speakers were in the same room, I would have done something like this:
pcm.both {
type route;
slave.pcm {
type multi;
slaves.a.pcm "wirelessDmixed";
slaves.b.pcm "internalDmixed";
slaves.a.channels 2;
slaves.b.channels 4;
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;
bindings.4.slave b;
bindings.4.channel 2;
bindings.5.slave b;
bindings.5.channel 3;
}
ttable.0.0 1;
ttable.1.1 1;
ttable.2.2 1;
ttable.3.3 1;
ttable.4.4 1;
ttable.5.5 1;
}
merging the 2 speakers on one card and 4 speakers on the other into an unique 6-channel setting.
Set the default output device
Ok, now that this monstrous multichannel stream-mixing device is ready, the last thing to do is set it as the default output device. Here it is:
pcm.!default {So simple that doesn't need explanation at all. The ctl here is a bit picky, so it is set to control the main hardware card. Now if you try "speaker-test -c4 -D default -t wav" you will be amazed by the result.
type plug
slave {
pcm both
}
}
ctl.!default {
type hw
card SB
}
Making it work with Skype and Amarok 1.4
Skype is easy: just set your mic pcm as the input device (in my case, USBMic), and the default pcm as the output device.
Amarok doesn't like the default alsa device, but it's not so hard to fix. Just go in Settings > Configure Amarok > Engine, select xine-engine, select alsa as output plugin, select your speaker arrangment and then set all the fields in "ALSA Devices Configuration" to plug:both.
Here, done! :)
If you want one application to output sound only to one card, remember to use always the dmixed pcm and not the basic one, otherwise you will be stuck again with the resource busy error.
System-wide or single user config
To make this setting available for all users, just copy it into /etc/asound.conf (as root), otherwise you can write it into .asoundrc (in the home dir of one or more users), but I fear that the multiuser setting will result useless in this case.
To have the system-wide settings work, just restart alsa with /etc/rc.d/rc.alsa restart (as root). If you edited .asoundrc you have to logout and login again.
Thank you very much for putting this together for all of us...sound setup has been the biggest problem I have had in making a permanent move over to Linux.
I have a somewhat similar setup to your configuration. My first question is how did you find the name of your USB MIC? It is not among the list of devices in your aplay -l output.
Thank you again for this tutorial.
-Rick Evans
Its wok, thank you very much
ReplyDelete