• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

BEGINNER QUESTION : Getting "BitPerfect" output in Linux ?

dasdoing

Major Contributor
Joined
May 20, 2020
Messages
4,301
Likes
2,774
Location
Salvador-Bahia-Brasil
I got a couple of Ubuntu PCs that had glitchy audio both working smoothly with Pulseaudio. Now they play audio at any bit rate without resampling and without glitching. In doing so I documented the config settings I changed. Posted them here, and here, in case this helps anyone else.

pulseaudio can't benefit from "threadirqs" kernel parameter? that's what jack users use for realtime
 

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
Maybe it can, I haven't tried that. My linux audio journey is still underway, I'm willing to try anything.

PS: my original goal was to get audio to play smoothly without distortion or glitches at all bit rates. That mission accomplished, but at the expense of high (200 ms) latency. I don't really need low latency since I'm not a gamer, but low latency is nice to have if the price (in complexity & performance) isn't too high. This could be possible with a different approach, running the kernel with the threadirqs parameter and increasing the IRQ priority of the sound card. I have not yet explored this.
 
Last edited:

johnk

Member
Joined
Aug 4, 2019
Messages
55
Likes
47
I got a couple of Ubuntu PCs that had glitchy audio both working smoothly with Pulseaudio. Now they play audio at any bit rate without resampling and without glitching. In doing so I documented the config settings I changed. Posted them here, and here, in case this helps anyone else.
Thank you for your suggestions. I have updated my Pulseaudio config with your settings (I'm on Ubuntu 20.04).
I mainly use spotify as my source, but I would be interested in trying to understand if I have set up my system optimally.
Is there anything else that I should be checking?

Thanks, John
 

dasdoing

Major Contributor
Joined
May 20, 2020
Messages
4,301
Likes
2,774
Location
Salvador-Bahia-Brasil
Maybe it can, I haven't tried that. My linux audio journey is still underway, I'm willing to try anything.

PS: my original goal was to get audio to play smoothly without distortion or glitches at all bit rates. That mission accomplished, but at the expense of high (200 ms) latency. I don't really need low latency since I'm not a gamer, but low latency is nice to have if the price (in complexity & performance) isn't too high. This could be possible with a different approach, running the kernel with the threadirqs parameter and increasing the IRQ priority of the sound card. I have not yet explored this.

just adding to this:

low latency is nice for movies, too...but there are video players where you can delay the video signal.
 

dasdoing

Major Contributor
Joined
May 20, 2020
Messages
4,301
Likes
2,774
Location
Salvador-Bahia-Brasil
my all freeware Linux DPS chains:
the above is headphones
below speakers
freewaredsp.png
 

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
Any reason why
Code:
avoid-resample = true
would not work ony my Manjaro Stable install?

FWIW, I have the T5 Pulse Audio Parametric Eq installed, which uses LADSPA, so I didn't know if this was interfering.

Here is my sink output
1631554396418.png
 

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
Any reason why
Code:
avoid-resample = true
would not work ony my Manjaro Stable install?
First, you spelled it wrong. It's this:
avoid-resampling = true
NOT this
avoid-resample = true

Second, this avoid-resampling option doesn't exist in older versions of Pulseaudio.
 

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
First, you spelled it wrong. It's this:
avoid-resampling = true
NOT this
avoid-resample = true

Second, this avoid-resampling option doesn't exist in older versions of Pulseaudio.
Thanks for the reply, I don't have my home PC in front of me (thus the typo), but I do know I'm on version 15.x of Pulse Audio, and I'm sure I had the coding correct in the .conf file. and it's still didn't work.
 

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
Another possibility: while "avoid-resampling" does exactly what it says (makes PulseAudio avoid resampling), they use the word "avoid" for good reason. Pulseaudio still has only a single sampling rate for all apps playing audio. And it cannot change the sampling rate while audio is playing.

For example: suppose you start playing an 88.2 kHz audio file. With this setting turned on, Pulseaudio will try to set the system rate to 88.2 to match your file, to avoid resampling. But if some other process is already playing audio, like maybe you have a browser tab open to YouTube which uses 48 kHz, then Pulseaudio can't change the rate. It can change the system sampling rate ONLY when nothing is already playing.

Here's a script I use. It automates cleanly killing, reconfiguring, restarting Pulseaudio with various settings. This has the beneficial side-effect of terminating any stale or zombie audio streams that might be locking the sample rate from changing. If the system wants you to be root in order to run this script, and you get tired of typing in your password, you can set the file permissions of "/etc/pulse/daemon.conf" accordingly. Like assign it to one of your user groups and set mode to 664.

Code:
#!/usr/bin/env bash
# Set Pulseaudio bit rates (and optionally bit depth)

if [ "$1" == "-h" ]
then
    echo "audioSet RATE1 RATE2 BITDEPTH FRAGCOUNT FRAGMSEC"
    echo "audioSet -f RATE"
    exit 1
fi

# Fixed rate mode, for forcing a single sampling rate
if [ "$1" == "-f" ]
then
    br1="$2"
    br2="$2"
    bd="float32le"
    fc="4"
    fm="50"
    ars="false"
else
    ars="true"
    if [ -z "$1" ]
    then
        br1="44100"
    else
        br1="$1"
    fi
    if [ -z "$2" ]
    then
        br2="48000"
    else
        br2="$2"
    fi
    if [ -z "$3" ]
    then
        bd="float32le"
    else
        bd="$3"
    fi
    if [ -z "$4" ]
    then
        fc="4"
    else
        fc="$4"
    fi
    if [ -z "$5" ]
    then
        fm="50"
    else
        fm="$5"
    fi
fi

echo "Audio set: rate 1 $br1, rate 2 $br2, avoid-rs $ars, bit depth $bd fragment count $fc fragment msec $fm"

sed -i "/^default-sample-rate/c\default-sample-rate = $br1" /etc/pulse/daemon.conf
sed -i "/^alternate-sample-rate/c\alternate-sample-rate = $br2" /etc/pulse/daemon.conf
sed -i "/^default-sample-format/c\default-sample-format = $bd" /etc/pulse/daemon.conf
sed -i "/^default-fragments/c\default-fragments = $fc" /etc/pulse/daemon.conf
sed -i "/^default-fragment-size-msec/c\default-fragment-size-msec = $fm" /etc/pulse/daemon.conf
sed -i "/^avoid-resampling/c\avoid-resampling = $ars" /etc/pulse/daemon.conf

# Kill pulseaudio; it will restart automatically
pulseaudio -k
 
Last edited:

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
Another possibility: while "avoid-resampling" does exactly what it says (makes PulseAudio avoid resampling), they use the word "avoid" for good reason. Pulseaudio still has only a single sampling rate for all apps playing audio. And it cannot change the sampling rate while audio is playing.

For example: suppose you start playing an 88.2 kHz audio file. With this setting turned on, Pulseaudio will try to set the system rate to 88.2 to match your file, to avoid resampling. But if some other process is already playing audio, like maybe you have a browser tab open to YouTube which uses 48 kHz, then Pulseaudio can't change the rate. It can change the system sampling rate ONLY when nothing is already playing.

Here's a script I use. It automates cleanly killing, reconfiguring, restarting Pulseaudio with various settings. This has the beneficial side-effect of terminating any stale or zombie audio streams that might be locking the sample rate from changing. If the system wants you to be root in order to run this script, and you get tired of typing in your password, you can set the file permissions of "/etc/pulse/daemon.conf" accordingly. Like assign it to one of your user groups and set mode to 664.

Code:
#!/usr/bin/env bash
# Set Pulseaudio bit rates (and optionally bit depth)

if [ "$1" == "-h" ]
then
    echo "audioSet RATE1 RATE2 BITDEPTH FRAGCOUNT FRAGMSEC"
    echo "audioSet -f RATE"
    exit 1
fi

# Fixed rate mode, for forcing a single sampling rate
if [ "$1" == "-f" ]
then
    br1="$2"
    br2="$2"
    bd="float32le"
    fc="4"
    fm="50"
    ars="false"
else
    ars="true"
    if [ -z "$1" ]
    then
        br1="44100"
    else
        br1="$1"
    fi
    if [ -z "$2" ]
    then
        br2="48000"
    else
        br2="$2"
    fi
    if [ -z "$3" ]
    then
        bd="float32le"
    else
        bd="$3"
    fi
    if [ -z "$4" ]
    then
        fc="4"
    else
        fc="$4"
    fi
    if [ -z "$5" ]
    then
        fm="50"
    else
        fm="$5"
    fi
fi

echo "Audio set: rate 1 $br1, rate 2 $br2, avoid-rs $ars, bit depth $bd fragment count $fc fragment msec $fm"

sed -i "/^default-sample-rate/c\default-sample-rate = $br1" /etc/pulse/daemon.conf
sed -i "/^alternate-sample-rate/c\alternate-sample-rate = $br2" /etc/pulse/daemon.conf
sed -i "/^default-sample-format/c\default-sample-format = $bd" /etc/pulse/daemon.conf
sed -i "/^default-fragments/c\default-fragments = $fc" /etc/pulse/daemon.conf
sed -i "/^default-fragment-size-msec/c\default-fragment-size-msec = $fm" /etc/pulse/daemon.conf
sed -i "/^avoid-resampling/c\avoid-resampling = $ars" /etc/pulse/daemon.conf

# Kill pulseaudio; it will restart automatically
pulseaudio -k
You know something else that is wonky, is I have my /etc/pulse/daemon.conf file properly modified to bit rate of s24le, yet in the hwparams and in the sink output it states floate32LE. In fact, I've never seen it report s24le from hwparams.

I'm wondering if the LADSPA eq is monkeying with things..
 

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
Well, s24le / s32le is not a bit rate, but a bit depth. So it doesn't matter as much, just set a value of at least 24 bits.

That said, I've seen the exact same thing. In years past, Pulseaudio used whatever I configured. But for the past year or two, it always uses s32le no matter what I configure. Per above, this is harmless. What's more important, avoid-reasampling does indeed work. But if it is going to resample, soxr-vhq is the best one to use.
 

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
Well, s24le / s32le is not a bit rate, but a bit depth. So it doesn't matter as much, just set a value of at least 24 bits.

That said, I've seen the exact same thing. In years past, Pulseaudio used whatever I configured. But for the past year or two, it always uses s32le no matter what I configure.
Good to know that you're experiencing the same thing in regards to bit depth. I won't waste time trying to chase that down.

When I get home, I'll try a couple things and circle back. As background, I would want all *playback from the pc routed as follows: Source (Audacious for local library, Spotify, or Audacity)> Bit perfect via Pulse or ALSA> USB DROP SDAC> Headphone Amp
 

Sal1950

Grand Contributor
The Chicago Crusher
Forum Donor
Joined
Mar 1, 2016
Messages
14,206
Likes
16,950
Location
Central Fl

danadam

Addicted to Fun and Learning
Joined
Jan 20, 2017
Messages
997
Likes
1,551
What's more important, avoid-reasampling does indeed work.
(sorry if that's getting too technical)
I'm afraid it might not be true when additional modules are involved. I don't know how it is with ladspa module, but with module-remap-sink, when it is loaded it creates a sink with sample rate and bitdepth the same as the master sink it is connected to. It also creates a sink-input (i.e. stream) between them. When you play something, a new sink-input is created and the pipeline is like this:
Code:
your stream --> remap sink --> remapped stream --> alsa sink
From the output of "pacmd list-sinks" and "pacmd list-sink-inputs":
Code:
sinks:
  * index: 0
        name: <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        state: RUNNING
        sample spec: s32le 2ch 44100Hz
    index: 6
        name: <Channels_Switcheroo>
        state: RUNNING
        sample spec: float32le 2ch 44100Hz

sink inputs:
    index: 32
        state: RUNNING
        sink: 0 <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        sample spec: float32le 2ch 44100Hz
                media.name = "Remapped Stream"
    index: 37
        state: RUNNING
        sink: 6 <Channels_Switcheroo>
        sample spec: s16le 2ch 96000Hz
                media.name = "sin_220.96.flac - mpv"
                application.name = "mpv Media Player"
When your sink-input is created it calls "pa_sink_reconfigure()" and passes there a sink it is connected to (see sink-input.c:432). Inside "pa_sink_reconfigure()" there is this (see sink.c:1481):
Code:
if (!s->reconfigure)
    return;
And here's the problem. This "reconfigure" is some kind of callback function and, AFAICT, only alsa sink sets it (see alsa-sink.c:2649). This means that if your sink-input is connected directly to alsa sink then the switching of the sample rate will work and if it is connected to some other sink then it won't.
 

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
... I'm afraid it might not be true [avoiding resampling] when additional modules are involved. ...
... if your sink-input is connected directly to alsa sink then the switching of the sample rate will work and if it is connected to some other sink then it won't.
I'm not surprised. Pulse can change the system sampling rate for a stream only when there is nothing playing on it. So if some other module gets in there it can lock the sampling rate.

This happens with PulseEffects. It's a great system, full of useful DSP like EQ, crossfed, etc. But it locks the system sampling rate, preventing the Pulse "avoid-resampling" from working. The developers have discussed this, saying it would be nice to make PulseEffects *not* lock the sampling rate, but saying that isn't very important since resampling is mostly transparent if you use a good algorithm and they are too busy with more important bugs & features.
 
Last edited:

danadam

Addicted to Fun and Learning
Joined
Jan 20, 2017
Messages
997
Likes
1,551
I'm not surprised. Pulse can change the system sampling rate for a stream only when there is nothing playing on it. So if some other module gets in there it can lock the sampling rate.
Ah, but that's not exactly what I meant :) Yes, if the module is staying active then it will lock the sample rate, but if I don't play anything then it should get suspended and release the lock. Here I play mpv through remap sink, alsa sink is locked to 44100:
Code:
sinks:
  * index: 0
        name: <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        state: RUNNING
        sample spec: s32le 2ch 44100Hz
    index: 1
        name: <Channels_Switcheroo>
        state: RUNNING
        sample spec: float32le 2ch 44100Hz

sink-inputs:
    index: 0
        state: RUNNING
        sink: 0 <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        sample spec: float32le 2ch 44100Hz
                media.name = "Remapped Stream"
    index: 3
        state: RUNNING
        sink: 1 <Channels_Switcheroo>
        sample spec: s16le 2ch 96000Hz
                media.name = "sin_220.96.flac - mpv"
                application.name = "mpv Media Player"
After I stop, the remapped stream gets corked and both sinks get suspended:
Code:
sinks:
  * index: 0
        name: <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        state: SUSPENDED
        sample spec: s32le 2ch 44100Hz
    index: 1
        name: <Channels_Switcheroo>
        state: SUSPENDED
        sample spec: float32le 2ch 44100Hz

sink-inputs:
    index: 0
        state: CORKED
        sink: 0 <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        sample spec: float32le 2ch 44100Hz
                media.name = "Remapped Stream"
And now I play 96 kHz file using paplay directly through alsa sink, the sampling rate changes:
Code:
sinks:
  * index: 0
        name: <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        state: RUNNING
        sample spec: s32le 2ch 96000Hz
    index: 1
        name: <Channels_Switcheroo>
        state: SUSPENDED
        sample spec: float32le 2ch 44100Hz

sink-inputs
    index: 0
        state: CORKED
        sink: 0 <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        sample spec: float32le 2ch 44100Hz
                media.name = "Remapped Stream"
    index: 4
        state: RUNNING
        sink: 0 <alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo>
        sample spec: s16le 2ch 96000Hz
                application.name = "paplay"
                media.name = "sin_220.96.flac"

What I meant was that one could have expected that "avoid-resampling" would work through a chain of sinks and sink-inputs. So if I played the 96 kHz file through remap sink, then remap sink would get reconfigured and send 96 kHz stream to alsa sink, which would reconfigure alsa sink. I certainly was slightly surprised when I found out it was not the case.
 

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
Thanks @danadam and @MRC01 your conversation and the output of my pacmd list-sink-inputs clued me in to look at the LADSPA module running at boot. In the end my problem was two fold.

1) I must have installed pulseaudio-equalizer at some point, which opened a LADSPA sink at login. I was able to remove this by commenting out the equalizer lines in the ~/.config/pulse/default.pa .

Code:
### BEGIN: Equalized audio configuration
### Generated from: pulseaudio-equalizer
#.nofail
#load-module module-ladspa-sink sink_name=ladspa_output.mbeq_1197.mbeq sink_master=alsa_output.pci-0000_00_1b.0.analog-stereo plugin=mbeq_1197 label=mbeq control=0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
#set-default-sink ladspa_output.mbeq_1197.mbeq
#set-sink-mute alsa_output.pci-0000_00_1b.0.analog-stereo 0
#.fail

Probably could just remove pulseaudio-equalizer as I don't use it anyway. (EDIT cannot remove due to dependency. Uncomment is only option)

2)Retested, but alas the problem persisted. Then I realized, I had told Pulse to set the default bit depth and sample rate to s24le and 96000. I commented those out in /etc/pulse/daemon.conf then ran pulseaudo -k. Voila! Now I was at least seeing the proper sample rate in watch -n1 cat /proc/asound/card2/pcm0p/sub0/hw_params. However, the bit depth was still returning s32le, but @MRC01 mentioned he had the same thing recently as well, so I'm thinking success..until I tried to record in 32bit Float and 96000 in Audacity, and well, back to 16/44.1 downsampling from watch -n1 cat /proc/asound/card0/pcm0c/sub0/hw_params . Back to the drawing board...

How can I record in 32/96 in Audacity and still have proper playback from Pulse in Audacity and Spotify/Google Chrome? Seems my options are to just uncomment the custom bit depth and sample rate to activate 32bit/96k when doing recordings..or leave them and use ALSA for Audacious a and upsample Spotify and Chrome constantly switching the configuration in Pulse Volume Control for SDAC output... Probably easier to do the former than the latter..

Unless there is a way to configure Google Chrome to output straight to ALSA as well. Then I could use ALSA for Audacious/Chrome (Spotify/Youtube)...

**Do you two know a way to have the custom bit depth and sample rate in daemon.conf, but have it only apply to recording from the internal soundcard? @MRC01 I assume your script could handle this?
 
Last edited:

MRC01

Major Contributor
Joined
Feb 5, 2019
Messages
3,489
Likes
4,113
Location
Pacific Northwest
Pulseaudio can have different sinks at different sample rates. And you can create your own named sinks and make apps use them instead of the default. I don't know whether that would work but it seems worth a try.

For example, I use this to capture bit-perfect audio that is playing. The first pactl command creates a named stream, the second parec command captures the raw audio data to a file on disk. Not exactly what you want to do, but the example commands might be helpful. You can do a lot with pactl and related commands.

Code:
# Create a Pulseaudio stream that "tees" the main audio stream, so we can record it without gaps
strnam="my.audio.stream"
pactl load-module module-combine-sink sink_name="$strnam" \
slaves=alsa_output.pci-0000_04_02.0.iec958-stereo \
sink_properties=device.description="$strnam"

# Start capturing the stream
parec -v -d "$strnam".monitor --fix-format --fix-rate --fix-channels "$filnam"
 

Lttlwing16

Active Member
Forum Donor
Joined
Feb 24, 2021
Messages
201
Likes
114
Pulseaudio can have different sinks at different sample rates. And you can create your own named sinks and make apps use them instead of the default. I don't know whether that would work but it seems worth a try.

For example, I use this to capture bit-perfect audio that is playing. The first pactl command creates a named stream, the second parec command captures the raw audio data to a file on disk. Not exactly what you want to do, but the example commands might be helpful. You can do a lot with pactl and related commands.

Code:
# Create a Pulseaudio stream that "tees" the main audio stream, so we can record it without gaps
strnam="my.audio.stream"
pactl load-module module-combine-sink sink_name="$strnam" \
slaves=alsa_output.pci-0000_04_02.0.iec958-stereo \
sink_properties=device.description="$strnam"

# Start capturing the stream
parec -v -d "$strnam".monitor --fix-format --fix-rate --fix-channels "$filnam"

Is there an easy way to get Google Chrome to output to ALSA? If so, then I'd need to set hw:2,0 - USB as the default playback device in ALSA, and could leave Pulse with the custom bit depth and sample rate for recording in Audacity.
 
Top Bottom