Pop-free sound from a Raspberry Pi running XBMC

UPDATE: I’ll leave this around for posterity but a large part of this problem has now been fixed in the latest Raspberry Pi firmware. See here for instructions for raspbmc until that gets updated.

I’ve been in the process of setting up a Raspberry Pi in my office so I can play my mp3 collection through my old stereo. It’s generally gone well and I have to take my hat off to the developers of Raspbmc which makes setting up XBMC on the Pi ridiculously easy and fast. It didn’t take me long to have Airplay set up and running as well as being able to use my phone to remote control XBMC to play things direct from my music library sitting on my Synology NAS. Quite a nice setup really.

Just one problem. I play the music out through the Pi’s audio jack which doesn’t have a fantastic DAC. The big noticeable issue is audible pops every-time XBMC starts and stops playing. For Airplay this isn’t too bad, you get a pop when it first starts but only another after you stop playing. Playing direct on XBMC though you get two pops between each track as it stops playing one and starts the next. Very annoying. It’s a pretty well known problem and the best solution so far is to simply never stop playing. If you have a player that uses pulseaudio then you can configure it to keep the audio stream going even when idle. Of course it isn’t that easy, XBMC doesn’t use pulseaudio on the Pi. There is some work going on that might change that but for now it is very buggy to the point of being unusable. It seemed I was stuck … or was I?

It took some experimentation but I finally came across something of a hack that solves the problem for me. It probably works on other distributions but I did all this using Raspbmc.

First as root you want to do this:

echo "snd-bcm2835" >>/etc/modules

This makes the kernel module for the sound devices load on startup. It allows alsa and by proxy pulseaudio to talk to the audio hardware. Next edit /etc/pulse/system.pa and comment out this line:

load-module module-suspend-on-idle

This tells pulseaudio to keep the audio stream alive even when not playing anything. Now reboot your Pi. Once it is started up copy a plain wav file (nothing mp3 encoded or anything) to the Pi, log in and play it through pulseaudio:

paplay test.wav

If it doesn’t come out of the speakers then alsa might be trying to play to the HDMI port. Try running this then running the above command again:

sudo amixer cset numid=3 1

What just happened is pulseaudio played the sound file, but now should have kept the audio hardware active and will continue to do so until the Pi is next turned off. You might think that that might mean that XBMC can’t play anything now. You’d be wrong, it plays just fine and no longer suffers from the popping between tracks. Occasionally I hear a pop when I first start playing after startup, but after that I’ve not heard any issues.

There are probably easier ways to initialise pulseaudio but I don’t mind playing some sound on every startup to let me know my Pi is ready. I made it automatic by sticking this at the top of .bashrc for the pi user (which is used to run xbmc):

/usr/bin/paplay $HOME/test.wav

It means it also plays every-time I log in with ssh but I’m not expecting to do that much now it’s all working. I’m sure someone will point out the better way to do this that I’m too lazy to look for now everything is working for me.

25 thoughts on “Pop-free sound from a Raspberry Pi running XBMC”

  1. Many thanks for that. I’ve spent many hours in front of my PC to get rid of these crackles and now I got it.
    Many, many thanks again.

  2. Thanks for the fix – it’s brilliant.

    Here’s my wee contribution…
    A tidy version of all of the above wrapped in to a shell script….

    Paste the text below in to ‘/home/pi/pi-sound-fix.sh’ then run it once like so…
    bash ~pi/pi-sound-fix.sh

    #!/bin/bash
    ######################################################
    #Eli K. Breen – 2012
    # Raspberry Pi & Raspbmc Hack – minimize audio popping on playback start/stop
    # This file expects to live in “/home/pi/pi-sound-fix.sh” and be run once manually.
    chmod 711 ~pi/pi-sound-fix.sh
    sudo grep -q “pi-sound-fix.sh” ~pi/.bashrc || echo “/home/pi/pi-sound-fix.sh” >> ~pi/.bashrc
    sudo grep -q “snd-bcm2835” /etc/modules || sudo echo “snd-bcm2835” >> /etc/modules
    sudo perl -pe ‘s/^(load-module module-suspend-on-idle)/#$1/g’ -i /etc/pulse/system.pa
    sudo amixer cset numid=3 1 >/dev/null
    paplay /home/pi/smb3_coin.wav
    ######################################################

    1. I haven’t tested but I’m not sure how well that will work. You’re adding the call to run pi-sound-fix.sh to the end of .bashrc but at least in Raspbmc .bashrc exits early if it isn’t running from an interactive shell (as is the case for when XBMC runs on startup). Secondly the line that writes to /etc/modules will fail unless the pi user has privileges to write to /etc/modules which isn’t normal. Sudo will only run the echo command as root, the pipe will run as the original user.

  3. Great fix, but did’t worked the way I expected it to work. Problem was that I always had to login through ssh to get it working. So after a reboot I still had to login though ssh (hear the wav-file) and then it worked. What I did to get it working without having to login after every reboot (running raspbmc nightly build of 17-01-2013 on model B 512Mb, hdmi video, analog audio):

    $ sudo su
    $ echo “snd-bcm2835” >> /etc/modules
    $ perl -pe ‘s/^(load-module module-suspend-on-idle)/#$1/g’ -i /etc/pulse/system.pa
    $ sed -i ‘1i sleep 1 && /usr/bin/amixer cset numid=3 1 > /dev/null’ /home/pi/.bashrc
    $ reboot

    Unfixed problems (but at least less annoying than the popping sounds):
    1) Popping sounds at boot (and of course at shutdown).
    2) Popping sound still occurs when forwarding within a song.
    3) Login on ssh last 1 sec longer.
    4) When skipping to next song the two songs sometimes play at the same time.

    ps. Didn’t need a whatever.wav (maybe that fixes one of the problems mentioned above). But if still needed at least use an empty wavfile (creating: rec soundfix.wav trim 0 .01)
    pps. Not sure why the sleep is necessary…….

    1. This does help tremendously. I’ve tried Martin Klomp’s version of the fix and it does reduces popping between plays. However, since I did this, now when playing a music playlist, at the beginning of each track the volume goes back up to (what sounds like) full volume, and then after a second or two decreases to whatever volume is indicated by the XBMC volume. This can be just as annoying as the pops, especially when listening late at night, trying not to wake the neighbors with really low volume. Every new track BLASTS in at full volume.
      Can anyone else confirm this problem?
      Any idea how to fix this and keep the pop fix?

      thanks!

      1. Can confirm i’m experiencing The same behaviour although haven’t applied any of the fixes proposed here. Were you able to solve it?

      1. sorry asked too soon, I just removed the comment tag that I put into the system.pa file and it has gone back to its normal popping behaviour at the start and end of tracks! preferable.

  4. So I’ll try again and ask here, but before that here is another one. In the thread (http://forum.stmlabs.com/showthread.php?tid=1052) mentioned above it states:

    >>>
    Onboard audio (hdmi/analogue) device
    With latest RC5 update this is not possible due to problem at compiling kernel alsa driver
    =====================================
    You can enable the experimental alsa driver for the onboard device by
    Code:
    sudo modprobe snd-bcm2835
    This will not survive after a reboot and to make it auto load you should put a entry like snd-bcm2835 inside /etc/modules.
    >>>

    might that (the RC5 not having a compatible kernel alsa driver) be my problem, are you guys all running the latest RC5? And here is my previous post:

    Hey Mossop, I tried your guide but the problem in raspbmc still prevails. Ismod tells me that snd_bcm2835 is loaded. I edited out “load-module module-suspend-on-idle” with a # in system.pa (and default.pa). I edited .bashrc with the test sound and when I ssh in I can hear the test .wav being played, and there don’t seem to be any more pops with paplay. At first in xbmc there was no more sound at all but adding “sudo amixer cset numid=3 1” to .bashrc fixed that, however the pops prevail. I am running Release Candidate 5, Built: 20121231 – fresh install. Do I have to change anything within Raspbmc Settings Addon, i.e. enable the Audio Engine? Would be great to get rid of these popping sounds!
    Cheers

    1. If you’re using the experimental version of Raspbmc that is offered in that thread then yes I wouldn’t be surprised if you hit issues. My hope is that once the work there becomes stable we won’t need this workaround at all, we can just use pulseaudio direct from XBMC.

      I’m just using the Raspbmc that you download from the main site, and yes I seem to be on RC5:

      Release Candidate 5, Built: 20121231

      1. Im using the usual RC5 aswell. So if there are no further settings within Raspbmc which need to be applied, I have no clue why it isn’t working for me. The module is loaded and the pop is gone when plaing through paplay through ssh, but not in xbmc. strange. anyway, thanks for getting back to me.

  5. hi,
    your method doesn’t work for me..
    the bcm module is loaded correctly, I commented the line in pulse config.
    I can’t hear anything from paplay, even after the amixer command..
    xbmc plays sound as usual (with popping)

    I’m using raspbmc nightly build (in the past I enabled, then disabled, the audio engine), I tried also to revert back to raspbmc rc.

    1. I just tried with a clean raspbmc install..
      executed all those commands, still I can’t hear anything with the paplay command

  6. Thanks Mossop,

    Great post, and really clear instructions! Finally eliminated that annoying pop, which slowly, and almost certainly was going to drive me crazy.

    One small suggestions that works for me is to replace your test.wav file with a silent-burst.wav file.
    see link below.

    http://www.jasonn.com/files/silent-burst.wav

    Thanks again.

  7. I just wanted to say a massive thank you for this – I bought my PI for use as an xbmc music player and it has been sat gathering dust since I got it because of the pops – now it works just like I imagined.

    (I followed Martin Klomp’s instructions)

    1. Just wanted to add that first I installed the latest ‘release’ from 20121231 but that had an odd bug that would only play the first song in a playlist so I updated to the latest nightly, followed the above instructions and now everything is perfect and pop free

  8. Are you guys doing movie playback in XBMC without ‘pops’, after applying this fix?

    It just doesn’t work for me – I have followed both the original instructions and Martin Klomp’s. Not matter what I try, I get audio pops at start and stop of movie playback.

    Du you have CoreAudioEngine enabled or disabled (default) in Raspbmc?

    Thanks

    1. I still get pops from video files but am only really interested in audio files. I can live with a pop at either end of a movie, but it’s incredibly annoying for me in between songs.

      1. Thanks for the reply.

        Too bad, I thought all audio, including movies, would be fixed :/

        Using the Pi for TV and movies in the bedroom, at night, the audio pop noise is Very annoying – wakes up the neighbours 😉

        /Martin

    2. (and I use whatever the CoreAudioEngine default is – I don’t remember changing this…)

  9. This may be a related problem. Using OpenElec on Pi, I don’t suffer from the “pop” problem (it’s there but very subdued).

    What I DO have is lot of background noise – it’s not far off zero DB s/n to my ear – during play out of the analog audio port. If I swap from USB WiFI to wired ethernet it’s quite a lot better, but still not great.

    I’ve seen a lot of mention of using “cheap USB audio DACs” but no mention of specific models or chipsets, and I don’t want to end up in module/driver hell.

Comments are closed.