Pulseaudio + ALSA Configuration

Okay… if you have read my previous post on ALSA Configuration you will know that I am trying to solve my sound setup problem in linux. The basic problem can be summarized as:

  • Use the sound cards at their native sample-rate to improve over their rather poor hardware re-samplers.
  • Mix audio from multiple applications on the cards.
  • Be able to easily designate audio cards on a per application basis at application launch time.

I had commented earlier that I decided against pulseaudio because of its lack of 32 bit signed integer audio support. I realized after some general use of my previous alsa configuration that even though some applications use 32 bit audio well, most other applications have problems. Typically mplayer and ut2004 (through aoss) couldn’t correctly figure out that the device was running at 32 bit precision and sent it 16 bit audio data. This caused both the applications to run audio at half the speed with the audio crackling all over. The fix was simple: change S32_LE in .asoundrc to S16_LE. However, that would be the end of any 32 bit audio on my system. I also realized that the only application which I used (heavily) with 32 bit audio was madplay (piped through aplay; madplay directly outputs to hardware alone). I grudgingly agreed to sacrifice that :(.

Pulseaudio configuration is pretty straight forward. I configured the /etc/pulse/default.pa for the two cards in the following way. I happily noticed that pulseaudio used a good resampler by default (speex-float-3 which has similar CPU usage as alsa’s plugin speexrate).

/etc/pulse/default.pa

 
#!/usr/bin/pulseaudio -nF
.nofail

### Load something into the sample cache
#load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav
#load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
#load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
#load-sample-lazy pulse-access /usr/share/sounds/generic.wav

.fail

### Load audio drivers statically
load-module module-alsa-sink device=intelHDA sink_name=Spkr rate=192000
load-module module-alsa-sink device=iMic sink_name=HeadPh rate=48000

### Load several protocols
#load-module module-esound-protocol-unix
load-module module-native-protocol-unix

### Automatically restore the volume of playback streams
#load-module module-volume-restore

### Automatically restore the default sink/source when changed by the user during runtime
#load-module module-default-device-restore

### Automatically move streams to the default sink if the sink they are
### connected to dies, similar for sources
load-module module-rescue-streams

### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle

### Make some devices default
set-default-sink Spkr
#set-default-source input

To make alsa applications work directly with pulseaudio we just need to set the default pcm and ctl to the pulse alsa plugin (configuration shown later). The pulse plugin creates a new audio device called pulseaudio and maps its audio I/O to the default pulse sink which can be changed at runtime. The pulseaudio device also has two mixer controls; a “Master” for playback and a “Capture” for recording.

The problem with the above is that pulseaudio starts looking for mixer controls “Master” for every configured sink hardware device (with a fallback to “PCM”). The default alsa configuration doesn’t provide a “Master” control for either the intelHDA card or the iMic card. The “PCM” on iMic controls the hardware mixer directly and that for intelHDA controls a software volume for alsa’s default dmix configuration. Thus, the pulseaudio fallback to “PCM” works correctly for iMic (changing the pulseaudio “Master” control changes the volume) but not for intelHDA (changing pulseaudio “Master” control has no change on volume, but changing “Front” directly on the hardware using alsamixer -c does work). To work around this I configured two virtual softvol (software volume) devices for my two cards naming the softvol control “Master”. The configuration is shown below.

.asoundrc


pcm.!default {
        type pulse
}

ctl.!default {
        type pulse
}

# Create softvol devices for intelHDA and iMic.
# For intelHDA, its "PCM" control controls its default (not used) softvol.
# For iMic, its "PCM" control controls its hardware directly.
pcm.intelHDA {
        type softvol
        slave.pcm "hw:0,0"
        control.name "Master"
        control.card 0
}

pcm.iMic {
        type softvol
        slave.pcm "hw:1,0"
        control.name "Master"
        control.card 1
}

# It seems we require these dummies as pulseaudio tries to look up mixer devices.
ctl.intelHDA {
        type hw
        card 0
}

ctl.iMic {
        type hw
        card 1
}

# For UT2004 (which uses dsp0 through aoss), always go directly to headphone hardware.
pcm.dsp0 {
        type plug
        slave.pcm "hw:1,0"
}

ctl.dsp0 {
        type hw
        card 1
}

Note that the pcm names used (intelHDA and iMic) are used in /etc/pulse/default.pa as sinks. More information on the softvol alsa plugin can be found here. There is some nice documentation about the various alsa plugins here. There some good documentation about alsa is also present here, here and here.

To change the current default pulseaudio sink I rewrote the audio.sh from the previous post to the following:

audio.sh


#!/bin/bash

pulse_set_default_sink () {
        pacmd << EOF
set-default-sink $1
EOF
}

h=`cat $HOME/.dwm/status_audio`;

if [ "x$1" == "x" ]; then
        if [ "x$h" == "x[ Spkr ] " ]; then
                echo -n "[ HeadPh ] " > $HOME/.dwm/status_audio ;
                pulse_set_default_sink HeadPh ;
        else
                echo -n "[ Spkr ] " > $HOME/.dwm/status_audio ;
                pulse_set_default_sink Spkr ;
        fi
elif [ $1 == "up" ]; then
        amixer set Master 2%+ ;
elif [ $1 == "down" ]; then
        amixer set Master 5%- ;
elif [ $1 == "toggle" ]; then
        amixer set Master toggle ;
else
        echo "$0: Unknown command $1";
fi

v=`amixer get Master | grep "Front Left:" | egrep -o "[0-9]+%"`
m=`amixer get Master | grep "Front Left:" | egrep -o "off"`

if [ "x$m" == "x" ]; then
        echo -n "vol:$v "
else
        echo -n "vol:(M) "
fi > $HOME/.dwm/status_volume

Note that now environment based device settings are gone as the current default pulseaudio sink automatically maps to the global alsa default pcm device. Once an application connects to pulseaudio, it retains its sink mapping even after the default sink is changed. (Update: It seems that module-volume-restore remembers the volume and sink of a client and restores both when it sees the client again. This behavior is definitely useful but we need to disable module-volume-restore if we want our current default sink logic to work). Pulseaudio also support hot swapping an application’s audio from one sink to another. I am still thinking of a way to toggle the sink device of the currently focussed application using dwm shortcuts… that would be some nifty configuration :).

About these ads
This entry was posted in Linux. Bookmark the permalink.

9 Responses to Pulseaudio + ALSA Configuration

  1. Francis says:

    Hello! I’d like to leave my congratulations for this objective and useful post. There’s times that I’m looking for something like that about pulseaudio with Alsa. I’m using an Intel_hda sound card on my PC, and I’m still trying to configure the sample rate to 96/24 through pulseaudio, no success yet =/. Can you tell me how to get this config?

    sorry my poor english, I’m brazilian.

    good job!

  2. dan sawyer says:

    This very usable.

    My system is an upgrade, some element is gaining control and pulse is unable to find the hardware devices. Do you have any way to identify which module driver has the device? Or what configuration caused that to take place?

    Thanks – Dan

  3. Nik says:

    Hi there, do you know of anything like this for Windows (Vista 64), in particular the ability to designate the default audio device on a per application basis. Ideally it would be integrated in to the audio mixer. I’ve tried looking around the web but the closest I could find was your web site for this Linux tweak.

  4. Ritesh (author) says:

    I am aware that Vista has a per application audio mixing capability. However, I have not used Vista much esp. not with audio so I am unable to tell you exactly how to do that.
    Pulseaudio is available for windows, but I don’t know if you can route windows audio to pulseaudio similar to the alsa routing in linux.

  5. Dave says:

    Pulse Audio is, unfortunately, a LEMON.

    I am in the fortunate position of owning a sound card which can do hardware mixing (it’s a cheap-o SBLive). For the last month or two, since the last upgrade to Ubuntu 8.10, I’ve been thinking that there was a problem with one of my cables connecting my soundcard to my headphones and Creative 4.1 speaker set — often in a game, the sound just deadens quite a bit (as if a cable is half-unplugged), and there is crackling whenever there is a sound with reasonable bass (eg explosions in Quake4, life-leach in Sacred under WINE, etc). I uninstall Pulse Audio so that ALSA is being used directly, and the problem immediately goes away.

    I certainly see the need for something like Pulse Audio — but it seems to be just as broken as ESD and ARTS, failing when the system is under load. Since I don’t need network transparency, sound card unification or a software mixer (nor do I care for per-application sound settings), I’m reverting back to the good old basic ALSA. At least I can play a game without feeling like I’m playing a scratchy old record.

  6. Ritesh (author) says:

    Hi Dave, Its unfortunate that you had a bad experience with Pulseaudio. Your problem might be due to the fact that WINE doesn’t have a driver for pulseaudio. It uses alsa and the redirection from alsa to pulseaudio (and back to alsa) doesn’t work well if the application doesn’t use alsa well. I know there was some talk about the WINE guys writing a really good alsa based sound driver… but I don’t know how far that went. I personally think that its high time the non-pro audio apps on linux move to a standard sound API. Pulseaudio is a good choice because its designed and implemented well, has support from RedHat and comes with a lot of desktop goodies (network transparency is only part of the goodies).

    Personally, I used pasuspender to launch applications I didn’t want to go through pulseaudio. You may have to configure wine to not go through the “default” alsa devices. Just use specific hardware or virtual device names in the wine audio configuration. My two articles on linux audio setup should be sufficient for you to configure and operate such devices. I wish pasuspender could avoid the cumbersome alsa configuration and direct audio directly to alsa.

  7. crypt says:

    This is complete madness with this pulseaudio! I am unable to grasp all this stuff! Post is very informative. Ritesh, it’s a pitty I couldn’t find any contacts of you in this blog. :(

  8. James says:

    You know who’s bloody awesome? You are! Here I am, thinking, ‘oh yeah, I might try out Pulseaudio for Slackware 13.37′ (hopefully Google finds that and points other people in my situation your way). Hmm… But how do I go about configuring it…? Google google google… Ubuntu stuff, some other stuff, aha! I was a bit wary of the age of this post (nearly five years!), but read through it.

    Tried some stuff out here, works perfectly! Not even a reboot required! A++++ Would buy from this seller again.

    PS: for the Slackware 13.37 + KDE folks, go into the System Settings>Multimedia>Phonon and move Esound (ESD) up to the top for every category. Install Pulseaudio from SlackBuilds.org After that, do everything down to (and including) the .asoundrc step here.

  9. John says:

    When are the Developers going to get together make a decent marriage of PulseAudio and ALSA. This just represents how bad audio is in Linux. It’a disgrace. It’s about time these Coders/Overlords get off there high horse and help the common folk here. It’s great that users write their own code to fix an Audio problem here and there, but that just proves there is a PROBLEM. I like the fact that Audio has options but why should common problems have to be recoded just to work? I love the fact that Linux is so customizeable. Sound/Audio support and code generation for this is VERY LACKING. It makes me think I’m working with Windows more and more. I went to Linux for the Freedom of being able to customize my system. Audio is not that way. That is the furthest thing I want, to be restricted by an OS that says you can only do this, PERIOD(sound like windows). I switched to Linux Mint for my system about two years ago. I’m on my system a big part of the day and enjoy great sound. If you want problems where cards have to be assigned and processes stopped and restarted, that just proves there is a problem. It’s great that people come up with solutions but it actually defeats the purpose of what Linux really is. Linux I thought, stands for Freedom without aggrevation. But after doing some digging in the Audio arena I am very disapointed. I think there are a lot of users that would jump in a minute if it wasn’t such a mess. MY two Cents. Sorry for the Venting . Just Dissappointed…. Just for the record I hate Windows… I wish I coded Linux software in my earlier days. I would be leading the charge. End of my Nute Rockny Speech

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s