# vim:set ft=alsaconf noet ts=8 sw=2: # Updated 090117 notes {at} notes.for.sabi.co.UK # Copyright (C) 2009 PeterG. This program is free software: you # can redistribute it and/or modify it under the terms of the # GNU General Public License as published by the Free Software # Foundation, either version 2 of the License, or (at your # option) any later version. This program is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Syntax (somewhat) described in these links: # http://ALSA-project.org/alsa-doc/alsa-lib/conf.html # http://ALSA-project.org/alsa-doc/alsa-lib/confarg.html # http://ALSA-project.org/alsa-doc/alsa-lib/conffunc.html # http://ALSA-project.org/alsa-doc/alsa-lib/confhooks.html # In this file I use a style similar to the one I use for CSS style sheets. # It may also help to read: # http://WWW.sabi.co.UK/Notes/linuxSoundALSA.html # Also check carefully the contents of '/usr/share/alsa/alsa.conf', # especially for the one liners defining standard device names # and attributess, or the output of 'arecord -L' or 'aplay -L'. # The device names "default", "dsp0", "mixer0" have special meanings. # Standard channel number assignments: # 0 front left 1 front right, # 2 rear left 3 rear right # 4 center 5 lfe/subwoofer # 6 side left 7 side right ######################################################################## # Read very carefully the ALSA PCM plugin page at: # http://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html # For the 'asym', 'dsnoop', 'dmix' plugins also read: # http://ALSA.OpenSrc.org/index.php/Asym # http://ALSA.OpenSrc.org/index.php/Dsnoop # http://ALSA.OpenSrc.org/index.php/Dmix # http://ALSA.OpenSrc.org/index.php/How_to_use_softvol_to_control_the_master_volume pcm.c20 { @args [ CARD ] @args.CARD { type string; default "0"; } type hw; card $CARD; } pcm.c40 = pcm.surround40; pcm.c51 = pcm.surround51; pcm.dsp { @args [ SNOOP MIX ] @args.SNOOP { type string; } @args.MIX { type string; } type asym; capture.pcm $SNOOP; playback.pcm $MIX; } pcm.rec { @args [ KEY PCM ] @args.KEY { type integer; } @args.PCM { type string; } type dsnoop; ipc_key $KEY; slave.pcm $PCM; } pcm.iec { @args [ PCM ] @args.PCM { type string; } type iec958; slave.pcm $PCM; } # For Tribes 2, which has the channels reversed. # http://home.Erin.UToronto.CA/~jbonham/tribes2-alsa.html pcm.swap { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; ttable.0.1 1; ttable.1.0 1; } # Buffering (period time defaults to 125000 usecs). # Size of period, expressed either in usec or byte units: # period_time USECS # period_size BYTES # Size of buffers, expressed either in period, usec, or byte units: # periods PERIODS # buffer_time USECS # buffer_size BYTES # The ALSA docs have examples with 'period_time' set to 0, when # 'period_size' and 'buffer_size' are used instead, but this can # cause trouble in later releases of ALSA. # For OSS compatibility, 'period_size' and 'buffer_size' should # be powers of 2. Also, many cards cannot accept a 'period_size' # much greater than 4096, so 4096 is mostly safe. Some like the # nForce 8x0 compatibles require a smaller one still. # On my VIA 8233A, any value for 'period_time' greater than # 85333 usecs (precisely!) causes hiccups in sound output. # Why? At 48kHz, 85333 usec are just over 4096 bytes/channel. pcm_slave.dmix-slave { @args [ CHAN PCM RATE PSIZE BSIZE PTIME BTIME ] @args.CHAN { type integer; } @args.PCM { type string; } @args.RATE { type integer; default 48000; } @args.PSIZE { type integer; default 4096; } @args.BSIZE { type integer; default 40960; } @args.PTIME { type integer; default 84000; } @args.BTIME { type integer; default 840000; } pcm $PCM; rate $RATE; period_time $PTIME; buffer_time $BTIME; period_size $PSIZE; buffer_size $BSIZE; channels $CHAN; } # 2/4/6 CHANNEL SW SHARING # ######################## pcm.dmix-20 { @args [ KEY PCM RATE PSIZE BSIZE PTIME BTIME ] @args.KEY { type integer; } @args.PCM { type string; } @args.RATE { type integer; default 48000; } @args.PSIZE { type integer; default 4096; } @args.BSIZE { type integer; default 40960; } @args.PTIME { type integer; default 84000; } @args.BTIME { type integer; default 840000; } type dmix; ipc_key $KEY; # slave { @func concat # strings [ "dmix-slave:2," $PCM "," $RATE "," # $PSIZE "," $BSIZE "," $PTIME "," $BTIME ] }; slave { pcm $PCM; rate $RATE; period_time $PTIME; buffer_time $BTIME; period_size $PSIZE; buffer_size $BSIZE; channels 2; } bindings.0 0; bindings.1 1; } pcm.dmix-40 { @args [ KEY PCM RATE PSIZE BSIZE PTIME BTIME ] @args.KEY { type integer; } @args.PCM { type string; } @args.RATE { type integer; default 48000; } @args.PSIZE { type integer; default 4096; } @args.BSIZE { type integer; default 40960; } @args.PTIME { type integer; default 84000; } @args.BTIME { type integer; default 840000; } type dmix; ipc_key $KEY; # slave { @func concat # strings [ "dmix-slave:4," $PCM "," $RATE "," # $PSIZE "," $BSIZE "," $PTIME "," $BTIME ] }; slave { pcm $PCM; rate $RATE; period_time $PTIME; buffer_time $BTIME; period_size $PSIZE; buffer_size $BSIZE; channels 4; } bindings.0 0; bindings.1 1; bindings.2 2; bindings.3 3; } pcm.dmix-51 { @args [ KEY PCM RATE PSIZE BSIZE PTIME BTIME ] @args.KEY { type integer; } @args.PCM { type string; } @args.RATE { type integer; default 48000; } @args.PSIZE { type integer; default 4096; } @args.BSIZE { type integer; default 40960; } @args.PTIME { type integer; default 84000; } @args.BTIME { type integer; default 840000; } type dmix; ipc_key $KEY; # slave { @func concat # strings [ "dmix-slave:6," $PCM "," $RATE "," # $PSIZE "," $BSIZE "," $PTIME "," $BTIME ] }; slave { pcm $PCM; rate $RATE; period_time $PTIME; buffer_time $BTIME; period_size $PSIZE; buffer_size $BSIZE; channels 6; } bindings.0 0; bindings.1 1; bindings.2 2; bindings.3 3; bindings.4 4; bindings.5 5; } # 4/6 CHANNEL AS STEREO # ##################### # Distribute 2 channel stereo to 4 or 5.1 surround channels # 'surround40' and 'surround51' should be predefined. # http://ALSA.OpenSrc.org/index.php?page=FAQ028 # http://ALSA.OpenSrc.org/index.php?page=SurroundSound # 'table.X.Y Z' means add channel 'X' multiplied by 'Z' to 'Y'. # Does not support sharing, stack 'dmix' for that. # Note that all (some?) USB sound device config do not define the # 'surroundXY' style name, so substitute the equivalent 'hw' name. pcm.stereo-40 { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; slave.channels 4; ttable.0.0 1.0; ttable.0.2 0.6; ttable.1.1 1.0; ttable.1.3 0.6; } pcm.stereo-51 { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; slave.channels 6; ttable.0.0 1.0; ttable.0.2 0.6; ttable.0.4 0.3; ttable.0.5 0.3; ttable.1.1 1.0; ttable.1.3 0.6; ttable.1.4 0.3; ttable.1.5 0.3; } # 4 CHANNEL AS 2 STEREO # ##################### # Using one four channel card as two stereo cards. # http://ALSA.OpenSrc.org/index.php?page=.asoundrc # Note that all (some?) USB sound device config do not define the # 'surroundXY' style name, so substitute the equivalent 'hw' name. pcm.card-f { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; slave.channels 2; ttable.0.0 1.0; ttable.1.1 1.0; } # Note that all (some?) USB sound device config do not define the # 'surroundXY' style name, so substitute the equivalent 'hw' name. pcm.card-r { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; slave.channels 4; ttable.0.2 1.0; ttable.1.3 1.0; } pcm.card-s { @args [ PCM ] @args.PCM { type string; } type route; slave.pcm $PCM; slave.channels 8; ttable.0.6 1.0; ttable.1.7 1.0; } pcm.soft { @args [ CARD CTL PCM ] @args.CARD { type string; default "0"; } @args.CTL { type string; default "Master"; } @args.PCM { type string; } type softvol; slave.pcm $PCM; control { name $CTL; card $CARD; } } ######################################################################## # The top level shared pseudo device, with both PCM and CTL interfaces # The ALSA default is "default", but many programs like XMMS and 'aoss' # assume "dsp0" as default name for PCM and "mixer0" for CTL. # Amazingly, XMMS has problems if one defines 'pcm.dsp0' to be # 'plug' for 'pcm.asym0' and not directly as 'asym'. ctl.!default = ctl.dsp0; pcm.!default = pcm.dsp0; ctl.pulse { type pulse; } pcm.pulse { type pulse; } ######################################################################## # The two detailed card configurations are for generic 2 to 5.1 channel # chipsets. It is assumed that both cards need software sharing, and can # only natively handle 48000Hz. # These assumptions are fairly typical of recent (2004) low end and # on-motherboard cards and chipsets, and their configs are not really # specific to either models. ######################################################################## ctl.dmixer { type hw; card 0 } pcm.dmixer { type dmix ipc_key 1024 slave { pcm "hw:0,0" period_time 0 period_size 1024 buffer_size 4096 rate 44100 } bindings { 0 0 1 1 } } # CARD 0 DEVICES # ############## ctl.card0 { type hw; card 0; } pcm.card0 { type hw; card 0; } pcm.dsnoop0 = "rec:23760,card0"; ctl.dmix0 = ctl.card0; pcm.dmix0 = "dmix-20:13760,card0,48000"; ctl.mixer0 = ctl.card0; ctl.dsp0 = ctl.card0; pcm.dsp0 = "dsp:dsnoop0,dmix0"; ctl.dmix0-rev = ctl.card0; pcm.dmix0-rev = "swap:dmix0"; ctl.stereo0-40 = ctl.card0; pcm.stereo0-40 = "stereo-40:surround40:0"; ctl.stereo0-51 = ctl.card0; pcm.stereo0-51 = "stereo-51:surround51:0"; ctl.digi0 = ctl.card0; pcm.digi0 = "iec:hw:0,2"; ctl.card0-f = ctl.card0; pcm.card0-f = "card-f:dsp0"; ctl.card0-r = ctl.card0; pcm.card0-r = "card-r:surround40:0"; ######################################################################## # CARD 1 DEVICES # ############## # For my #1 card, a CMI8738, the 'hw:1,1' device is either the # rear channels or a multi channel device depending on a mixer # control setting. ctl.card1 { type hw; card 1; } pcm.card1 { type hw; card 1; } ctl.mixer1 = ctl.card1; ctl.dsp1 = ctl.card1; pcm.dsp1 = "dsp:dsnoop1,dmix1"; pcm.dsnoop1 = "rec:29370,card1"; ctl.dmix1 = ctl.card1; pcm.dmix1 = "dmix-20:19370,card1,44100"; ctl.dmix1-rev = ctl.card1; pcm.dmix1-rev = "swap:dmix1"; ctl.stereo1-40 = ctl.card1; pcm.stereo1-40 = "stereo-40:surround40:1"; ctl.stereo1-51 = ctl.card1; pcm.stereo1-51 = "stereo-51:surround51:1"; ctl.digi1 = ctl.card1; pcm.digi1 = "iec:hw:1,2"; ctl.card1-f = ctl.card1; pcm.card1-f = "card-f:dsp1"; ctl.card1-r = ctl.card1; pcm.card1-r = "card-r:surround40:1"; ctl.card1-s = ctl.card1; pcm.card1-s = "card-s:surround71:1"; ######################################################################## # SW VOLUME CONTROL # ################# #pcm.name { type softvol; # slave STR; # control { # name STR; # [card INT;] # [iface STR;] # [index INT;] # [device INT;] # [subdevice INT;] # [count INT;] # } # } ######################################################################## # FILE OUTPUT # ########### pcm.file { @args [ PCM FILE ] @args.PCM { type string; } @args.FILE { type string; default "/tmp/alsa.raw"; } type file; file $FILE; #[format "raw";] #[perm 0600;] slave.pcm $PCM; } ctl.file0 = ctl.card0; pcm.file0 { type copy; slave.pcm "file:dsp0,/tmp/alsa0.raw"; } ctl.file1 = ctl.card1; pcm.file1 { type copy; slave.pcm "file:dsp1,/tmp/alsa1.raw"; } ########################################################################; # 2 CARDS AS 1 # ############ # Using multiple cards to simulate a single card is usually a bad idea # because they have different latencies and multichannel sound can come # out with quite a bit of skew. Some people however have a legitimate # need for this. # Using two cards as one four channel card. # http://ALSA.OpenSrc.org/index.php?page=TwoCardsAsOne ###################################### # 1st >= 2 channels, 2nd >= 2 channels ctl.multi40-22 = ctl.card0; pcm.multi-22 { @args [ PCM1 PCM2 ] @args.PCM1 { type string; } @args.PCM2 { type string; } type multi; slaves.a.pcm $PCM1; slaves.a.channels 2; slaves.b.pcm $PCM2; 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; } # Using two cards as one 5.1 channel card, the first has # 2 channels and the second has 4 channels, and viceversa. # http://ALSA.OpenSrc.org/index.php?page=TwoCardsAsOne ###################################### # 1st >= 2 channels, 2nd >= 4 channels pcm.multi51-24 { @args [ PCM1 PCM2 ] @args.PCM1 { type string; } @args.PCM2 { type string; } type multi; slaves.a.pcm $PCM1; slaves.a.channels 2; slaves.b.pcm $PCM2; 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; # Center, physically rear left, 2nd card bindings.4.slave b; bindings.4.channel 2; # LFE/subwoofer, physically rear right, 2nd card bindings.5.slave b; bindings.5.channel 3; } ###################################### # 1st >= 4 channels, 2nd >= 2 channels pcm.multi51-42 { @args [ PCM1 PCM2 ] @args.PCM1 { type string; } @args.PCM2 { type string; } type multi; # could be "dmix0" slaves.a.pcm $PCM1; slaves.a.channels 4; # could be "dmix1" slaves.b.pcm $PCM2; slaves.b.channels 2; 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; # Center, physically front left, 2nd card bindings.4.slave b; bindings.4.channel 0; # LFE/subwoofer, physically front right, 2nd card bindings.5.slave b; bindings.5.channel 1; }