I’m working on a security-related project with the Raspberry Pi and have encountered an annoying problem with the on-board sound output. I’ve managed to work around this, so thought it might be helpful the share my experiences with others in the same situation.
The problem manifests itself as a loud pop or click, just before sound is output and just after sound output is stopped. This is because a PWM output of the BCM2835 CPU is being used, rather than a standard DAC. When the PWM function is activated, there’s a jump in output voltage which results in the popping sound.
Until there’s a driver modification, the work-around suggested (other than using the HDMI sound output or an external USB sound card) is to run PulseAudio on top of ALSA and keep the driver active even when no sound is being output. This is achieved by disabling the module-suspend-on-idle
PulseAudio module, then configuring applications to use PulseAudio rather than ALSA. Daniel Bader describes this work-around and how to configure MPD, in a blog post. However, when I tried this approach, the work-around didn’t work.
When module-suspend-on-idle
was enabled, there was the popping sound but when module-suspend-on-idle
was disabled, there was no sound output. I investigated this, mainly though the debug logs in /var/log/messages
produced by PulseAudio after starting it with pulseaudio --start --log-target=syslog --log-level=4
. I also had to look at the source occasionally too.
The problem turned out to be because the audio files I was playing were mono with a sampling rate of 16,000 Hz or 48,000 Hz, and the default audio input format for the ALSA driver was stereo (with a 48,000 Hz sampling rate). When the audio was being played, PulseAudio had to change the input format to match, even if the only change was stereo to mono. This format change involves resetting the driver and so causes a pop as it is deactivated and re-activated even if module-suspend-on-idle
has not suspended the driver. Once audio playback is finished, the original audio format is restored, leading to a pop then too.
What is worse is that if module-suspend-on-idle
is disabled there’s no audio output. When PulseAudio switches the format, the driver is suspended but never resumes. There are some comments in the PulseAudio source which suggest that module-suspend-on-idle
is assumed to be available and is responsible for resuming drivers on a format change. Therefore the work-around for the popping, of disabling module-suspend-on-idle
, isn’t suitable when the audio input format is not stereo at 48,000 Hz.
Rather than disabling module-suspend-on-idle
, the work-around I arrived on was to set a very long idle timeout. This is done by appending timeout=604800
to the line starting with load-module module-suspend-on-idle
in /etc/pulse/default.pa
. Now, when there was a format change, the driver is still resumed but the driver will not be suspended until a week (604,800 seconds) after the last audio has been played.
Doing this, we don’t get popping between tracks when they are all stereo at 48,000 Hz, and at least other audio input formats play back. However, this doesn’t fix the popping on format change. To deal with this, I converted the audio to 48,000 Hz stereo before sending it to PulseAudio. One program which can do this is mplayer. For example to play back an audio file using PulseAudio do:
mplayer -ao pulse -af channels=2,resample=48000:1 FILENAME
The channels=2
converts mono to stereo and the resample=48000:1
converts the sampling rate to 48,000 Hz. The mplayer manpage gives more detail. These options can also be combined with other uses of mplayer, for example as an audio output program for the Festival speech synthesis program, by adding the following to your ~/.festivalrc
:
(Parameter.set 'Audio_Command "mplayer -really-quiet -noconsolecontrols -nojoystick -nolirc -nomouseinput -demuxer rawaudio -rawaudio channels=1:rate=$SR $FILE -ao pulse -af channels=2,resample=48000:1")
Update (2013-03-07): According to a comment on the Raspberry Pi bug tracker, this problem has now been fixed.
@none
Good point. I’ve updated the post accordingly. I did investigate this option, but I didn’t have an HDMI TV and devices to extract the audio from an HDMI signal seem to be £50+ (since HDMI is digital, they need their own DAC).
@Gareth,
usb audio is more problematic then built in analogue at the moment
sound is often bad (clipping, popping), sometimes you have to switch to usb 1.1 which is very slow for other devices (and for me I got bad sound even with usb1)
Audio and video are out of sync
Thanks for your work! I had the same problem and couldn’t figure it out. I used this information to fix the sound of my
Pi MusicBox! I had to set the sample-rate of pulseaudio fixed to 48000 btw
I also found this problem, and failed to get pulseaudio satisfactorily (it used more CPU than a MP3 decoder!).
I bought an unbranded USB sound card from ebay for £1.50, which works very well and has much better sound quality at low volumes (I guess it has a real DAC rather than PWM into an RC network).
Current firmware reduces issue to single click per reboot.
https://github.com/raspberrypi/linux/issues/128
Major improvement
I just wanted to point folks to the following post solving this problem for many folks. Go here:
http://forum.stmlabs.com/showthread.php?tid=4573&pid=62340#pid62340
There is a lot of good information there along with links in the thread to the firmware (start.elf, fixup.dat or start_x.elf, fixup_x.dat) which has been improved to solve this problem. It is expected these files will be rolled into a future update in a general distribution.
I previously had used the workaround outlined above which makes changes to pulseaudio’s load module module-suspend-on-idle. I found that this stopped audio popping with music (audio) files only. Popping continued with video files.
I found the stmlabs forum thread on this problem and installed the firmware files (the _x versions) and my problem with audio popping completely resolved itself. My system is oddly quiet when it loads files now!
Good luck and thanks for all your help in working this issue in this thread!
festival 2 can resample the rate inside itself:
@lisp
(Parameter.set ‘Audio_Method ‘Audio_Command)
(Parameter.set ‘Audio_Required_Rate 16000)
(Parameter.set ‘Audio_Required_Format ‘snd)
(Parameter.set ‘Audio_Command “sunplay $FILE”)
@end lisp
Unfortunately from a glance at the source, I cannot see a way to force
it to stereo internally (if there was, I suppose you could skip
mplayer and just have festival talk direct to pa).
Hi,
thank you very much! This finally helped me out. Only three lines remain in my system.pa
# lade soundkarte
load-module module-udev-detect
# streaming nur aus dem lokalen Netzwerk annehmen (aber unsicher-anonym)
load-module module-native-protocol-tcp auth-ip-acl=192.168.1.0/24 auth-anonymous=1
# http://www.lightbluetouchpaper.org/2013/02/10/fixing-poppingclicking-audio-on-raspberry-pi/
load-module module-suspend-on-idle timeout=604800
Henning
i had some issues with popping and cracking i commented out
#force_hotplug1 or whatever and i dont get any cracks or weird sounds when going out composite, don’t know how hdmi out will work but i’ll figure that out later.
i know this is a year old post just thought i’d comment on what i did to get rid of the background noise