Qball's Weblog

Dmix, the pain or MPD High cpu usage

Tags mpd  Music 

At mpd we are having an issue with high cpu usage, this started when alsa decided to use the great dmix by default. We now know this is caused by resampling. I never hit this problem and kind of assumed that the soundcards it happens on only supported 48khz sample rate. (with some crappy old on-board soundcards this is the case).
But currently a lot of crappy onboard cards support 44.1khz up to 192khz and 24bit audio. (support the format, not that they actually can reproduce this quality, they don’t even do cd-quality).

So why high cpu usage playing back music (44.1khz) on a card that supported 44.1khz?
Well a quick look in “/proc/asound”

cat /proc/asound/card0/pcm0p/sub0/hw_params

Showed that the card was in 48khz mode, why?.
After some googling i found this link

I quote:
Dmix by default uses 48kHz sample rate.
What? lets read this again:

Dmix by default uses 48kHz sample rate.
ok it really sais it. So even if you are playing 44.1khz sound, on a card that supports 44.1khz it resamples it to 48khz. That is bad.

Why is resampling bad? well 2 things:

  1. It is lossy, espicialy 44.1->48khz as it is irrational conversion. (see your favorite DSP book)
  2. It takes lot of cpu. The better you want the conversion, the more cpu it takes. The internal resampler of alsa does not use a lot of cpu, but is terrible. If you let mpd resample using libsamplerate it will cost you 10-30% cpu. depending on your machine.

So how to solve it?

There are several solutions, 2 are obvious:

  1. Let mpd bypass dmix. You can do this by setting plughw:0,0 (for the first soundcard, first output). However if mpd is playing, nothing can else can use the soundcard. You don’t have mixing anymore. (unless your soundcard supports this in hardware)

  2. Force dmix to use 44.1khz.

Lets see the inpack of all this by setting up a test case on my aspire one laptop:

The souncard supports (following /etc/asound/card0/codec#0) 44.1khz to 192khz for 16,20 and 24 bits. So 44.1khz playback should not be a problem, great.

So lets install mpd (I took the latest snapshot from git), use default config (I haven’t changed anything) and play some music (a 44.1khz 16bit flac rip from the album “slowhand” by “Eric Clapton”).

A quick look in /proc/asound/card0/pcm0p/sub0/hw_params showed that I was playing 32bit 48khz. (From the 32bit only the highest 24bits are used, for more explanation about this see the alsa documentation).

My cpu usage is 4-8%.    I cannot judge quality, this soundcard actual performance  is around 12-13bits. So any imperfections I hear are the soundcard, not the resampling.

Now this uses the bad crapppy internal resampler of alsa, so let mpd resample. This can be done by setting auto_resample “no” in my alsa audio_output block. I do have lsr installed, and use the default settings.

New cpu usage is 12-17%.

But the real solution in this case would be to stop the resampling.  Because I still want to be able to “mix” sounds. So lets try solution 2;  trie to change dmix default sample rate.

This is done by adding the following to my /etc/asound.conf

pcm.!default {
type plug
slave.pcm {
type dmix
ipc_key 1024
slave {
pcm “hw:0,0″
rate 44100

This should make my dmix play at 44.1khz. Lets restart mpd (yes this is required somehow) and play a song, checking /proc/asound/.. entry showed it was actually playing at 44.1khz GREAT!.

The cpu usage is now dropped to 1-2 % on a intel atom running at 800mhz. That is a massife improvement. And you did not loose sound quality this time.

There is a negative side to this solution, trying to play 48khz audio, it will be down-sampled to 44.1khz. This happens when playing a dvd.

I don’t mind, if I play a dvd (that has 48khz audio), I can either bypass dmix, or resample. The quality loss is not what I care about when watching a movie, I cannot even hear it on this crappy soundcard. The extra cpu usage is also not an issue, as the cpu is under a greater load by the playback of the video.

I hope this explains (and help solve) the high-cpu usage problem with mpd.