The best way to bridge ALSA and JACK that I found.

Optimize your system for ultimate performance.

Moderators: MattKingUSA, khz

Post Reply
crocket
Established Member
Posts: 68
Joined: Fri Mar 29, 2019 11:56 am

The best way to bridge ALSA and JACK that I found.

Post by crocket »

For months, I went through lots of trials and errors in order to remove pops, crackles, and clicks from the bridge between ALSA and JACK.
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
without xruns, pops, crackles, and clicks.

## Sound Quality
  • Sample Format // S16LE (signed 16bit integer, little endian)
  • Sampling Rate // 48000
  • Channels // 2
  • ALSA dmix resampler // samplerate_best from alsa-plugins
## Kernel Settings

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
## The bridge between ALSA and JACK

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.
## ~/.asoundrc

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"
}
## /etc/security/limits.d/40-realtime-base.conf

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
## /etc/security/limits.d/user.conf

Code: Select all

# This is for higher nice priorities of mpv and other media applications
user - nice -20
Post Reply