Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: ALSA sample rate conversion (Read 120419 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

ALSA sample rate conversion

The newer versions of ALSA (the Advanced Linux Sound Architecture) enable software mixing by default. All sounds which are played are converted to 48kHz (by default) and mixed in software. When I installed the new Ubuntu and it was set up this way, I was somewhat concerned about the sound quality implications of this setup. I dove into the ALSA source and discovered some very interesting things.

The first issue is the actual mixing. This is done with 24 bits of precision (32 bits are used internally, but the lowest 8 are used for saturation). The algorithm seems to be fairly good and I don't see any major quality implications are using it.

The second (and much bigger) issue is sample rate conversion. Obviously for software mixing all the signals need to be converted to a single rate. This rate, by default, is 48kHz. The algorithm used by default is a very rudimentry linear interpolation algorithm. This algorithm is fast but very low quality and is likely to audibly degrade the sound quality of 44100 material played through a mixed device. I tested this SRC using a loopback cable and some generated square, sine and triangle waves of various frequencies. It appears to add harmonic distortion of around -10dB in some cases and about -20dB on music. I'll post some graphs when I get home this afternoon.

There are a number of solutions to this problem.

1) Install the libasound_module_rate plugin and set defaults.pcm.rate_converter "samplerate_best" in your .asoundrc. This plugin uses the SRC_SINC_BEST_QUALITY algorithm from libsamplerate and seems to offer excellent quality. The problem here is that most distributions don't package this plugin and it is only included with very new versions of ALSA. I would say this is the ideal solution and it would be nice if the ALSA developers would make this (or at least libsamplerate's SRC_SINC_FASTEST algorithm) the default.

2) Set the dmix plug to use 44.1kHz. This is great if you are mostly listening to 44.1kHz material, but not so useful if you are listening to a mixture of 48kHz and 44.1kHz material.

3) Create seperate plugs for 44.1kHz and 48kHz material. This works fine if you don't want software mixing to work when playing both types of material simultaneously. A good setup here would be a 44.1kHz plug for used by default and by your MP3 player and a 48kHz plug used by your movie player. System sounds and other stuff can use either (I don't generally care about sound quality when watching Google Video content, for example).

ALSA by default seems to offer very dissapointing sound quality, but it is possible to set it up to offer much better quality. I will post a detailed guide in the next couple of days to explain how to set up your Linux machine for better playback and capture quality.

ALSA sample rate conversion

Reply #1
At least for Creative game soundcards with only one frequency of 48 kHz setting dmix plug to 44.1 kHz makes nothing good, the only way is to setup ALSA use high quality resampler to 48 kHz. It will be very useful to have good manual how to make it!

ALSA sample rate conversion

Reply #2
At least for Creative game soundcards with only one frequency of 48 kHz setting dmix plug to 44.1 kHz makes nothing good, the only way is to setup ALSA use high quality resampler to 48 kHz. It will be very useful to have good manual how to make it!
That is another good argument for high quality SRC in ALSA. It would be quite a bonus to Live!/Audigy owners to have a high quality SRC available, especially as these cards are well supported by ALSA already.

ALSA sample rate conversion

Reply #3
Thanks for the info. I'm replacing amarok and foobar with an mpd backend using alsa. It's amazing how difficult the latter is to setup properly.

ALSA sample rate conversion

Reply #4
After quick look at sources of ALSA I can say what rate converter plugin available only in version 1.0.11 or newer, for compiling plugin libsamplerate must be installed (together with developer files, for debian/ubuntu it's libsamplerate0-dev package). Also, ubuntu alsa-plugins even in 1.0.11 use only jack plugin from the sources when build binary package. I've open new bug at ubuntu launchpad.net, feel free to confirm.

ALSA sample rate conversion

Reply #5
Thanks for the info. I'm replacing amarok and foobar with an mpd backend using alsa. It's amazing how difficult the latter is to setup properly.
Alsa since 1.0.9 has had much more sensible defaults (like dmix enabled by default, which despite the current quality problems, is a good idea) and is easier to set up. You could also have a look at my .asoundrc frontend kasound, which is still beta but might offer some help. I agree with you, though, that ALSA is a pain to set up. The developers have been doing  a good job on making it easier recently.

iGold - I'll post to confirm that bug in alsa-plugins as soon as my net connection starts behaving. I am also posting a bug report against the equivalent Debian package.

ALSA sample rate conversion

Reply #6
Update: I have posted about this issue to the alsa-devel mailing list and received a number of good responses. Hopefully there will be enough interest among alsa developers that this issue will be fixed soon. I see it as a bit of a showstopping bug in ALSA and hope to communicate that to the list.

One of the more interesting replies I got was:
Quote
The problem is actually far more complicated than you described. A fair amount of ALSA core will have to be modified to really fix the problem. The main problem is the buffer and period sized as they pass through dmix. For example, if the sound card hardware is running with 1024 samples per period at 48000, and an application wished to use a sample rate of 44100, the application should really get 940.8 samples per period. That is nor possible, so the application gets 940. dmix then tries to convert 940 samples to 1024 samples ready for the hardware. So, even if the dmix algorithm used the super high quality sample rate conversion function, the actual rate change applied would still be slightly off.

To which I replied
Quote
In the scenario that you presented the application is told that there are 940 samples per period. ALSA, internally, converts these to 1024 samples per period at 48kHz sample rate. So the material (sampled at 44100Hz) is played back at a rate of 44062Hz? I don't know enough about the field to know if this error (0.08%) will be audible.

While this isn't, in my opinion, as big a problem as the bad SRC, it is one more problem with dmix and a reason you shouldn't use it for music playback (for now, at least) until this problem is fixed. Without dmix, ALSA's sound output quality isn't a problem - so don't panic about it.

Does anybody know how, for example, Foobar 2000's DSPs handle this problem of chunk size mismatch? Or do they not use chunks?

ALSA sample rate conversion

Reply #7

Thanks for the info. I'm replacing amarok and foobar with an mpd backend using alsa. It's amazing how difficult the latter is to setup properly.
Alsa since 1.0.9 has had much more sensible defaults (like dmix enabled by default, which despite the current quality problems, is a good idea) and is easier to set up. You could also have a look at my .asoundrc frontend kasound, which is still beta but might offer some help. I agree with you, though, that ALSA is a pain to set up. The developers have been doing  a good job on making it easier recently.

iGold - I'll post to confirm that bug in alsa-plugins as soon as my net connection starts behaving. I am also posting a bug report against the equivalent Debian package.


Thanks. Most of my alsa problems were to do with support of my chipset. Now my problems are mythtv wanting to use the card exclusively, even through ALSA, and software packaged with FC5 still using OSS. Yes, Firefox, i'm looking at you

ALSA sample rate conversion

Reply #8
I have posted about this issue to the alsa-devel mailing list and received a number of good responses. Hopefully there will be enough interest among alsa developers that this issue will be fixed soon.

Is this issue related to upstream alsa-plugins sources too? It's definitely debian/ubuntu packaging issue, are the developers want to fix it in debian? Or there is some other problem in alsa-plugins?

According to frequencies - is default linear alsa's SRC has no such problem? If it has the more quality algorithm will be already better till internal structure of ALSA not reworked.

ALSA sample rate conversion

Reply #9
Is this issue related to upstream alsa-plugins sources too? It's definitely debian/ubuntu packaging issue, are the developers want to fix it in debian? Or there is some other problem in alsa-plugins?

What I was hoping to achieve with alsa-devel was to get a change in the default behaviour of ALSA on desktop systems to use a higher quality SRC algorithm. In my mind, while getting the plugin packaged is a start, many people are complaining that ALSA sound quality is poor and not that many know that it can be improved. It would be nice if the default behaviour of ALSA was improved so everybody could benefit from better sound quality.
According to frequencies - is default linear alsa's SRC has no such problem? If it has the more quality algorithm will be already better till internal structure of ALSA not reworked.
From my reading of the source the linear SRC does still have this problem - but it's effect (compared to that of the poor SRC) is comparatively small. I agree that implementing a higher quality algorithm by default will improve things immensely. It would be interesting to know how Windows and OSX solve this problem.

ALSA sample rate conversion

Reply #10
Don't forget that there's the hw devices as well. Those should outright bypass dmix and directly output to the card. Sure, you don't get software mixing, but if you got a decent card it should do hardware mixing.

You might still get the resampling problem due to the card itself, but depending on the model, it might be just as good as samplerate_best.
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #11
Don't forget that there's the hw devices as well. Those should outright bypass dmix and directly output to the card. Sure, you don't get software mixing, but if you got a decent card it should do hardware mixing.
The hw devices do go straight to the hardware, which solves the whole problem. However, it would still be nice to have good quality AND software mixing. Also, many cards, like ones based on the ENVY24HT, HT-S and PT (which include the AV710, ESI Juli@ many other popular cards) don't do hardware mixing.

For what it's worth, the samplerate (SNR 97dB, bandwidth 80%) plugin measures very well on my system and uses up an extra 4% cpu (over the standard linear interpolator). samplerate_best (SNR 97dB, bandwidth 97%) uses up an extra 20% (for a total of 22% when playing an MP3) which is, for me, unacceptably high. A happy medium is the samplerate_medium setting, offering (according the the libsamplerate docs) an SNR of 97dB and bandwidth of 90%, while using 7% CPU on my system. I haven't tried to ABX the two yet, but I will over the course of the next few days and give results. Based on the measurements, it shouldn't be too hard (1% THD in the linear version, for a start).

I have built packages of libasound2, libasound2-dev and libasound2-plugins version 1.0.11 for Ubuntu Dapper (standard version is 1.0.10) with full samplerate support. Drop me a PM and I will email them to you, or find web hosting for them. If there is any demand, I will build libasound2-plugins with samplerate support for Debian unstable at work tomorrow.

ALSA sample rate conversion

Reply #12
Hmm, thought I'd give this a try.

Code: [Select]
pcm.48khq {
        type plug
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        rate_converter "samplerate_best"
}

pcm.48k {
        type plug
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        rate_converter "samplerate"
}


I don't notice any CPU usage difference at all between them. (I got a Celeron D 2.93Ghz) Although, I did notice a difference in sound between samplerate and samplerate_best. But, I don't really notice any difference between hw and samplerate_best. Guess in my case my SB Live! OEM is decent enough.

I sadly don't have any "professional" testing waves to use, so I was just using music I had to do the tests. Using just samplerate, there is a kinda of, muffleness in the highend. But both samplerate_best and hw sound, well, as they should I guess. Wish I had a patchcord, I'd do some recordings to see just how close samplerate_best and hw are.
"It's the panties fault! The panties made me a pervert!"


ALSA sample rate conversion

Reply #14
What version of ALSA are you using? Do you have the rate plugin installed (look what's in /usr/lib/alsa-lib if you aren't sure). I would be very interested if you did not have an increase in CPU usage with the plugin.



Well, Kernel ALSA module version is 1.0.11rc4 (Kernel is 2.6.17-gentoo-r5), alsa-lib is 1.0.12_rc1-r1 and alsa-plugins is 1.0.12_rc1-r1. And rate_samplerate is present in /usr/lib/alsa-lib:

Code: [Select]
cyberfoxx@Sally /usr/lib/alsa-lib $ ls -al libasound_module_rate_samplerate*
lrwxrwxrwx 1 root root   35 2006-08-21 12:40 libasound_module_rate_samplerate_best.so -> libasound_module_rate_samplerate.so
-rwxr-xr-x 1 root root  994 2006-08-21 12:40 libasound_module_rate_samplerate.la
lrwxrwxrwx 1 root root   35 2006-08-21 12:40 libasound_module_rate_samplerate_linear.so -> libasound_module_rate_samplerate.so
lrwxrwxrwx 1 root root   35 2006-08-21 12:40 libasound_module_rate_samplerate_medium.so -> libasound_module_rate_samplerate.so
lrwxrwxrwx 1 root root   35 2006-08-21 12:40 libasound_module_rate_samplerate_order.so -> libasound_module_rate_samplerate.so
-rwxr-xr-x 1 root root 5176 2006-08-21 12:40 libasound_module_rate_samplerate.so


Maybe for some strange reason, my Celeron D just handles mucking around with audio data really well. It's not like I'm using any major CFLAGS either, just "-march=prescott -Os -pipe -funroll-loops -fomit-frame-pointer", that's it.
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #15
I don't notice any CPU usage difference at all between them. (I got a Celeron D 2.93Ghz) Although, I did notice a difference in sound between samplerate and samplerate_best. But, I don't really notice any difference between hw and samplerate_best. Guess in my case my SB Live! OEM is decent enough.


What did you use to play the files?  I tried with mplayer first and got no change in cpu usage, but it jumped to around 27% using mpg321.  I guess mplayer might automatically do the resampling internally.

ALSA sample rate conversion

Reply #16
What did you use to play the files?  I tried with mplayer first and got no change in cpu usage, but it jumped to around 27% using mpg321.  I guess mplayer might automatically do the resampling internally.


I tried just mplayer. I haven't gotten around to emerging any other CLI players yet, so I'm not sure about mpg123/mpg321. For some reason, Audacious doesn't seem to like me setting the ALSA device to 48k or 48khq. Says it can't find the device. 

K, just tried in Xine, ~12% CPU usage with samplerate, samplerate_best and hw.

Although, I did notice that if I set the pcm.48k or pcm.48khq as pcm.!default, other apps that use waves, (eg: aMSN using SDL's playsound command) tended to stutter on playback. And just now test playing a wave in mplayer causes the stuttering as well, but, only on short waves. On longer waves, there's a tiny stutter at the beginning, 1secs worth, but it's smooth playing after that. Odd that it only happens on waves, but not MP3s, OGGs or Flacs.
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #17

What did you use to play the files?  I tried with mplayer first and got no change in cpu usage, but it jumped to around 27% using mpg321.  I guess mplayer might automatically do the resampling internally.

I tried just mplayer. I haven't gotten around to emerging any other CLI players yet, so I'm not sure about mpg123/mpg321.
mplayer by default resamples everything to 48kHz internally, as far as I can see. Try using aplay (comes with the alsa-utils source) to play back a 44.1 wave file.

ALSA sample rate conversion

Reply #18
Hmm, well, I tried playing a wave of the first track from the Halo 2 OST with aplay, and well, I'm getting an error. If I just use "aplay Halo\ 2\,\ Volume\ 1\ -\ 01\ -\ Halo\ Theme\ \(Mjolnir\ mix\).wav" it works fine. But if I try to use "aplay --device=48k Halo\ 2\,\ Volume\ 1\ -\ 01\ -\ Halo\ Theme\ \(Mjolnir\ mix\).wav" or "aplay --device=48khq Halo\ 2\,\ Volume\ 1\ -\ 01\ -\ Halo\ Theme\ \(Mjolnir\ mix\).wav" it tosses up an error.

aplay --device=48k Halo\ 2\,\ Volume\ 1\ -\ 01\ -\ Halo\ Theme\ \(Mjolnir\ mix\).wav
Code: [Select]
ALSA lib pcm_rate.c:1308:(snd_pcm_rate_open) Cannot open library for type x▒A
aplay: set_params:962: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S16_LE
SUBFORMAT:  STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (85331 85332)
PERIOD_SIZE: (3763 3764)
PERIOD_BYTES: (15052 15056)
PERIODS: (3 4)
BUFFER_TIME: (341315 341316)
BUFFER_SIZE: 15052
BUFFER_BYTES: 60208
TICK_TIME: 1000


aplay --device=48khq Halo\ 2\,\ Volume\ 1\ -\ 01\ -\ Halo\ Theme\ \(Mjolnir\ mix\).wav
Code: [Select]
ALSA lib pcm_rate.c:1308:(snd_pcm_rate_open) Cannot open library for type te_best
aplay: set_params:962: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S16_LE
SUBFORMAT:  STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (85331 85332)
PERIOD_SIZE: (3763 3764)
PERIOD_BYTES: (15052 15056)
PERIODS: (3 4)
BUFFER_TIME: (341315 341316)
BUFFER_SIZE: 15052
BUFFER_BYTES: 60208
TICK_TIME: 1000


Wonder if I'm missing something from my .asoundrc. I pretty much based it on the info from the PCM (digital audio) plugins page.

.asoundrc
Code: [Select]
pcm.48khq {
        type plug
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        rate_converter "samplerate_best"
}

pcm.48k {
        type plug
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        rate_converter "samplerate"
}


EDIT:

Aha! Figured out what I was doing wrong. plug should be rate, and rate_converter should be converter.
Code: [Select]
pcm.48khq {
        type rate
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        converter "samplerate_best"
}

pcm.48k {
        type rate
        slave {
                pcm "hw:0,0"
                rate 48000
        }
        converter "samplerate"
}


Seems to work fine now. K, thanks to top I'm able to see that using 48k causes aplay to 5% CPU, and 48khq causes aplay to use 25% CPU, and hw only uses 0% CPU.

Still need to get a patchcord and see about doing some ABX tests to see if I can tell the difference between 48khq and hw. There is a difference with 48k though, mostly muffleness in the highend.
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #19
Seems to work fine now. K, thanks to top I'm able to see that using 48k causes aplay to 5% CPU, and 48khq causes aplay to use 25% CPU, and hw only uses 0% CPU.
That's more like the CPU figures I was expecting, or I would be very dissapointed with my Athlon 

For a start at ABXing, I would recomment the chenoa and mustang samples (search for them, I think I got them from ff123's site). I have done the default versus samplerate_high and samplerate_linear versus samplerate_high but have had no success with samplerate versus samplerate_high. It would be very interesting to see how you get on.

ALSA sample rate conversion

Reply #20
Well, I managed to do a simple form of ABX'ng. Pretty much I just had a friend make up some .asoundrc configs for me to try. Each config had three devices setup, Test1, Test2 and Test3. Pretty much I just had to try and figure out which of Test2 and Test3 was Test1. And I was using the mustang and duel samples to test with.
The commandline I was using was:
Code: [Select]
aplay --quiet --device=<device> <wave>


We started out with a simple comparing of samplerate and samplerate_order. Out of the 5 he sent me, I got 5 correct. Was pretty simple considering that samplerate_order is pretty bad. We just did this one to make sure my ears were working.

Comparing samplerate and samplerate_best managed to embarrass me though. Out of 10, I got 1 right, 2 wrong, and 7 unsure. And honestly, I think the one I got right was a guess.

Based on those results, I decided that a test between samplerate and hw was needed. Out of the 10 tests, I said unsure on all of them. I honestly could not tell a difference between them.

Guess for me, using just hw for my SB Live! OEM is good enough. But, if I were to use the onboard sound, guess I'd just use samplerate and not waste the CPU that samplerate_best takes.
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #21
If I understand correct input audio data for my SB Live! 24-bit must be in 48 (or 96) kHz. Under Windows creative's drivers do this work and convert 44.1kHz to 48kHz. And under Linux ALSA does the same things (not at dmix stage, but at hardware driver's one).
Or this card (and similar Creative's cards from Live!/Audigy family) can hardware resample 44.1kHz to 48kHz? It's important for me because from Windows review resampling on this card is bad and good software resampler required for a good sound (resampler of the card (or driver?) is bad but the DAC is pretty good especially for music playback in stereo mode). So when I using hw: device in ALSA is the card resample 44.1 kHz itself of ALSA does it before (as I can suppose just linear)?
If ALSA does then output through dmix (with default resampling) and to hw directly must get the same software conversion by ALSA and there is no difference at all between dmix+linear resampling and hw output.

ALSA sample rate conversion

Reply #22
If I understand correct input audio data for my SB Live! 24-bit must be in 48 (or 96) kHz. Under Windows creative's drivers do this work and convert 44.1kHz to 48kHz. And under Linux ALSA does the same things (not at dmix stage, but at hardware driver's one).
Or this card (and similar Creative's cards from Live!/Audigy family) can hardware resample 44.1kHz to 48kHz? It's important for me because from Windows review resampling on this card is bad and good software resampler required for a good sound (resampler of the card (or driver?) is bad but the DAC is pretty good especially for music playback in stereo mode). So when I using hw: device in ALSA is the card resample 44.1 kHz itself of ALSA does it before (as I can suppose just linear)?
If ALSA does then output through dmix (with default resampling) and to hw directly must get the same software conversion by ALSA and there is no difference at all between dmix+linear resampling and hw output.



The thing with the hw device, is that it's pretty much a direct port to the sound hardware. All ALSA does with it is set the path and toss the data at the card. Thus, the data you send must be something that the DAC can handle because ALSA won't touch it.

Thus by using the hw device with the Live!/Audigy cards, if it's doing resampling, it's doing the resampling in hardware.

Now, I'm not too sure about this, but I would hazard a guess that the EMU chip is doing the resampling. Hey, it would explain why it gets so hot. (I even put a heatsink on mine because I was getting worried.)
"It's the panties fault! The panties made me a pervert!"

ALSA sample rate conversion

Reply #23
Now, I'm not too sure about this, but I would hazard a guess that the EMU chip is doing the resampling. Hey, it would explain why it gets so hot. (I even put a heatsink on mine because I was getting worried.)

According to Wikipedia:
Quote
The Sound Blaster Live! 24-bit was not actually a member of the Sound Blaster Live! family, because it lacked the EMU10k1/10k2 processor. It was a stripped down version of the Audigy 2 Value, with an SNR of 100 dB, software based EAX, no advanced resolution DVD-Audio Playback, and no Dolby Digital 5.1 or Dolby Digital EX 6.1 playback.
(But DAC in it better then in Audigy 2 Value, it's as in Audigy 2 ZS.)
So your Live! 5.1 and my Live! 24bit 7.1 are not from same family. And may have different quality hardware resampler.

But knowledge about ALSA work with hw device is useful, thank you for explanation.

Can anyone give link to good test sample for checking resampling quality? I know about dial.wav but maybe better test sample exists?