Stop resampling! under Linux

repo_code

somewhere in the 20th c.
This recipe worked for me.

I have a lot of 44kHz audio (wavs, mp3s, songza) and a USB DAC that can handle 44kHz natively. So Linux should get this right, right? Nope:


john@dash80:~$ cat /proc/asound/card2/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED
format: S24_3LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 1103
buffer_size: 4410


That was while playing a 44.1kHz mp3.

Good news. If the recording is at sample rate X, and the sound hardware can handle sample rate X, we can avoid resampling. It just takes a little configuration kung fu. This recipe works on Ubuntu 13.10, using a QNKTC AB 1.2 USB DAC. YMMV.

By default Ubuntu's sound stack is: Your apps -> PulseAudio -> ALSA -> the driver -> hardware

PulseAudio is a software mixer, it allows multiple apps to play sounds at the same time. It may resample. ALSA may also resample, it has a built in software mixer called 'dmix'. You can disable both software mixers.

** Step 1 ** Disable PulseAudio by uncommenting the 'autospawn' line in /etc/pulse/client.conf and changing it to 'no':


autospawn = no


Kill pulseaudio with "killall pulseaudio" or by rebooting. Notice that it does not return; "ps -ef | grep pulse" won't find it again.

** Step 2 ** Create an .asoundrc file in your home directory. Here's mine:

# -------------------------------------------------------------
#
# Avoid resampling. This is how:
#
# 1. Elsewhere, disable pulseaudio
# 2. Here in .asoundrc, create default pcm and ctl
# handles that don't use alsa's built-in 'dmix'
# software mixer.
# 3. Do use a "plug" wrapper around the underlying
# device. This can do lossless sample format
# adjustments, which lets way more apps work
# than without the "plug" wrapper.
#
# Q) How can you tell this is working?
# A) /proc/asound/card*/pcm0p/sub0/hw_params should show 44kHz
# when playing CD-quality mp3s or wavs.
#
# -------------------------------------------------------------



# Create a pcm handle named "AB12", this
# maps to the underlying hw driver for the "AB12".
#
# Identify the card by name to avoid maintaining
# hardcoded numbers ("hw:2,0") that might change
# depending on what else is plugged into the PC.
#
# Your device has a different name, not AB12.
# Get the name from /proc/asound/card*/id
#
pcm.AB12 {
type hw
card "AB12"
}

# Bind a default ctl to the underlying hw driver
# for the "AB12".
#
ctl.!default {
type hw
card "AB12"
}

# Create a default pcm, use the "plug" wrapper
# to wrap the named PCM we created above.
#
# Plug will adjust sample format as needed; we can
# force it to never change the sample rate! Nice.
#
pcm.!default {
type plug
slave {
#pcm "hw:2,0"
pcm "AB12"
rate "unchanged"
}
}


** STEP 3 ** Configure apps to use ALSA rather than PulseAudio. This required a manual config change in Audacious. I told Audacious to use the "default" mixer and PCM devices -- the same ones defined in the .asoundrc file. Firefox didn't require any config changes, it seems to just use the default pcm and mixer.

Go play music, confirm that /proc/asound/cards/card*/pcm0p/sub0/hw_params matches the samplerate of the source material, and appreciate how much better it sounds :D
 
Nice post.

I will also mention that if you use MPD or squeezelite no resampling takes place when you set the hardware parameter as.

Code:
HW:x,y

where x is the soundcard device and y is the interface

so far a USB DAC it is usually HW:0,0 or HW:1,0

for a optical or coax on a soundcard it probably would be: HW:0,1 or HW:0,2
 
Nice information above. Either I have already done this or it is done automatically under LMS because here is my output while playing a ripped redbook CD:

Code:
loren@xxx:/proc/asound/card1/pcm0p/sub0$ cat hw_params
access: MMAP_INTERLEAVED
format: S24_3LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 441
buffer_size: 1764

and the output while playing a ripped SACD @ 24/96:

Code:
loren@xxx:/proc/asound/card1/pcm0p/sub0$ cat hw_params
access: MMAP_INTERLEAVED
format: S24_3LE
subformat: STD
channels: 2
rate: 96000 (96000/1)
period_size: 960
buffer_size: 3840

The DAC is an HRT Music Streamer II.
 
Nice information above. Either I have already done this or it is done automatically under LMS because here is my output while playing a ripped redbook CD:

Code:
loren@xxx:/proc/asound/card1/pcm0p/sub0$ cat hw_params
access: MMAP_INTERLEAVED
format: S24_3LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 441
buffer_size: 1764

and the output while playing a ripped SACD @ 24/96:

Code:
loren@xxx:/proc/asound/card1/pcm0p/sub0$ cat hw_params
access: MMAP_INTERLEAVED
format: S24_3LE
subformat: STD
channels: 2
rate: 96000 (96000/1)
period_size: 960
buffer_size: 3840

The DAC is an HRT Music Streamer II.

afaik Squeezelite uses alsa directly which bypasses any mixer.
 
In Linux, I run deadbeef for music playback. You can direct the output to flow through ALSA right to the soundcard or external DAC. You can also tweak the ALSA plugin so that it uses no re-sampling. Awesome sound.

I've used Jack as well, which can sometimes be a bit finicky. Not much difference at all that I could discern between Jack and ALSA.
 
Back
Top Bottom