ALSA loopback caused a lot of pops, crackles, and clicks. It also produced soft xruns that were not reported by zita-ajbridge.
Today, I think I found the way to eliminate imperfections.
This setup withstands
- Repeated extreme stress tests via
Code: Select all
nice -n 19 stress-ng --iomix 8 --ionice-class idle --cpu 8 -t 5m
- Kernel compilations
- Gentoo package compilations
## Sound Quality
- Sample Format // S16LE (signed 16bit integer, little endian)
- Sampling Rate // 48000
- Channels // 2
- ALSA dmix resampler // samplerate_best from alsa-plugins
Code: Select all
PREEMPT_RT_FULL=y (from real-time linux kernel) for the machine that runs jackd netone backend
PREEMPT_RT_FULL=y or (PREEMPT=y and RT_GROUP_SCHED=y) for the machine that runs jack_netsource
IRQ_FORCED_THREADING=y
HZ_1000=y
# PERFORMANCE or POWERSAVE CPU frequency governor disables CPU frequency scaling which can cause xruns.
CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y or CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
Code: Select all
ALSA dmix (period_size 480, periods 3) -->
SPDIF out of Creative Sound Blaster X-Fi HD -->
SPDIF in of Creative Sound Blaster X-Fi HD -->
zita-a2j -j from_alsa -d spdif_in -p 144 -n 2 -r 48000 -->
1. jackd -P 90 -d netone -n 3 --(ethernet)-->
jack_netsource -n 3 -->
jackd -P 52 -d alsa -d speakers -p 192 -n 2 -r 48000 --> speakers
2. jackd -P 90 -d netone -n 3 -->
zita-j2a -j hdp -d hdp -p 144 -n 2 -r 48000 -->
headphone jack of Creative Sound Blaster X-Fi HD --> headphones
- Creative Sound Blaster X-Fi HD is connected to the machine that runs ALSA dmix.
- I switch between 1 and 2 by pressing a keyboard shortcut which executes small python programs that I wrote.
- The latency of every period is an integer multiple of 1 millisecond.
- "samplerate_best" rate converter for ALSA dmix protects you from re-sampling noise. I experienced a few pops with "speexrate_best" during the extreme stress tests.
- "-P 52" makes sure that the real-time process priority of jack_netsource is below that of ethernet interrupts. If jack_netsource has higher real-time process priority than ethernet interrupts, you are going to see a lot of underruns from jackd netone backend and its JACK clients because jack_netsource doesn't wait for ethernet interrupts and prematurely concludes that audio data didn't arrive in time. Interrupts have real-time process priority of 50 when PREEMPT_RT_FULL=y. If you still get underruns, replace "-P 52" with "-P 90", replace PREEMPT_RT_FULL with PREEMPT and RT_GROUP_SCHED, and apply the following cgroup setup.
- /etc/cgconfig.conf
Code: Select all
group rtaudio { perm { task { uid = root; gid = audio; } admin { uid = root; gid = root; } } cpu { cpu.rt_runtime_us = 950000; } }
- /etc/cgrules.conf
Code: Select all
@audio:jackd cpu rtaudio/ @audio:jack_netsource cpu rtaudio/
- Add the user that runs jackd and jack_netsource to audio group.
- /etc/cgconfig.conf
Code: Select all
defaults.pcm.rate_converter "samplerate_best"
pcm.spdif_out {
type hw
card HD
device 1
subdevice 0
format S16_LE
rate 48000
channels 2
}
pcm.smix {
type dmix
ipc_key 219348
hw_ptr_alignment "rounddown"
slave {
pcm "spdif_out"
period_size 480
periods 3
format S16_LE
rate 48000
channels 2
}
bindings {
0 0
1 1
}
}
pcm.spdif_in {
type hw
card HD
device 1
subdevice 0
format S16_LE
rate 48000
channels 2
}
pcm.hdp {
type hw
card HD
device 0
subdevice 0
format S16_LE
rate 48000
channels 2
}
ctl.hdp {
type hw
card HD
}
pcm.!default {
type plug
slave.pcm {
@func getenv
vars [ MY_ALSA_DEVICE ]
default "smix"
}
rate_converter "samplerate_best"
}
This allows real-time process priorities for any user in realtime group.
Add the user that runs jackd, jack_netsource, or zita-ajbridge to this group.
Code: Select all
# Start of 40-realtime-base.conf from realtime-base-0.1
@realtime - rtprio 99
@realtime - memlock unlimited
# End of 40-realtime-base.conf from realtime-base-0.1
Code: Select all
# This is for higher nice priorities of mpv and other media applications
user - nice -20