JACK

From NixOS Wiki
Revision as of 13:30, 26 June 2019 by imported>Facundominguez (Comment on the need for JACK_PROMISCUOUS_SERVER)

When on nixos-unstable, one may use JACK module. It works both with and without PulseAudio. Enable it this way and reboot:

/etc/nixos/configuration.nix
  services.jack = {
    jackd.enable = true;
    # support ALSA only programs via ALSA JACK PCM plugin
    alsa.enable = false;
    # support ALSA only programs via loopback device (supports programs like Steam)
    loopback = {
      enable = true;
      # buffering parameters for dmix device to work with ALSA only semi-professional sound programs
      dmixConfig = ''
        period_size 2048
      '';
    };
  };

  users.extraUsers.YOURUSER.extraGroups = [ "jackaudio" ];

The Jack Audio Connection Kit is used by most of the serious audio applications on Linux. It provides real-time, low latency connections for both audio and MIDI data between applications that implement its API. NixOS uses the dbus version of JACK2 (jackdbus). This can be used together with pulseaudio with a little configuration. The result is that you don't have to manually hunt down applications which are using the sound device and kill them before starting JACK. You can also continue to use non-JACK aware applications (e.g. flash) at the same time as using JACK applications (e.g. Ardour).

  1. Load the sequencer and midi kernel modules
    boot.kernelModules = [ "snd-seq" "snd-rawmidi" ];
  2. Enable JACK support
    In your configuration file:
    hardware.pulseaudio.package = pkgs.pulseaudio.override { jackaudioSupport = true; };
    
  3. Ensure that the JACK enabled pulseaudio is being used
    ~/.config/pulse/client.conf
    daemon-binary=/var/run/current-system/sw/bin/pulseaudio
  4. Configure QjackCtl
    1. Enable jackdbus
      Setup -> Settings -> Server Path: jackdbus
      Setup -> Misc -> Enable D-Bus interface: check
    2. Load the jack modules for pulseaudio after starting jackdbus
      Setup -> Settings -> Options -> Execute script after Startup: check
      pactl load-module module-jack-sink channels=2; pactl load-module module-jack-source channels=2; pacmd set-default-sink jack_out
      Setup -> Settings -> Options -> Execute script on Shutdown: check
      pactl unload-module `pactl list|grep -A 3 jack-source|tail -1|awk '{ print $NF }'`;pactl unload-module `pactl list|grep -A 3 jack-sink|tail -1|awk '{ print $NF }'`

You should now be able to start JACK with QjackCtl, you will notice a new playback and capture device in your sound mixer along with your normal devices.

Troubleshooting JACK and PulseAudio

$ pactl load-module module-jack-sink channels=2
Failure: Module initalization failed

Check if you have previous settings in ~/.config/jack/conf.xml. Try renaming this file and running the pactl command again.

You might need this setting so JACK_PROMISCUOUS_SERVER is defined when pulseaudio is started.

/etc/nixos/configuration.nix
  systemd.user.services.pulseaudio.environment = {
    JACK_PROMISCUOUS_SERVER = "jackaudio";
  };

Otherwise, you may get further info by disabling PulseAudio respawning (see above) and starting it in verbose mode:

$ pulseaudio -vvv

System optimizations for low latency audio with JACK

Some of the following settings, documented in http://wiki.linuxmusicians.com/doku.php?id=system_configuration and https://wiki.archlinux.org/index.php/Pro_Audio can be very helpful to reduce xruns and improve responsiveness and are required for certain programs to run at all e.g. Ardour. The kernelPackages section was taken from https://github.com/rockfabrik/deployment/blob/master/modules/profiles/dj.nix#L32

An easy way of setting all of these, plus a true realtime kernel, is here: https://github.com/musnix/musnix

boot = {
  kernelModules = [ "snd-seq" "snd-rawmidi" ];
  kernel.sysctl = { "vm.swappiness" = 10; "fs.inotify.max_user_watches" = 524288; };
  kernelParams = [ "threadirq" ];
  kernelPackages = let 
    rtKernel = pkgs.linuxPackagesFor (pkgs.linux.override {
      extraConfig = ''
        PREEMPT_RT_FULL? y
        PREEMPT y
        IOSCHED_DEADLINE y
        DEFAULT_DEADLINE y
        DEFAULT_IOSCHED "deadline"
        HPET_TIMER y
        CPU_FREQ n
        TREE_RCU_TRACE n
      '';
    }) pkgs.linuxPackages;
  in rtKernel;

  postBootCommands = ''
    echo 2048 > /sys/class/rtc/rtc0/max_user_freq
    echo 2048 > /proc/sys/dev/hpet/max-user-freq
    setpci -v -d *:* latency_timer=b0
    setpci -v -s $00:1b.0 latency_timer=ff
  '';
  # The SOUND_CARD_PCI_ID can be obtained like so:
  # $ lspci ¦ grep -i audio
};

powerManagement.cpuFreqGovernor = "performance";

fileSystems."/" = { options = "noatime errors=remount-ro"; };

security.pam.loginLimits = [
  { domain = "@audio"; item = "memlock"; type = "-"; value = "unlimited"; }
  { domain = "@audio"; item = "rtprio"; type = "-"; value = "99"; }
  { domain = "@audio"; item = "nofile"; type = "soft"; value = "99999"; }
  { domain = "@audio"; item = "nofile"; type = "hard"; value = "99999"; }
];

services = {
  udev = {
    packages = [ pkgs.ffado ]; # If you have a FireWire audio interface
    extraRules = ''
      KERNEL=="rtc0", GROUP="audio"
      KERNEL=="hpet", GROUP="audio"
    '';
  };
  cron.enable =false;
};

shellInit = ''
  export VST_PATH=/nix/var/nix/profiles/default/lib/vst:/var/run/current-system/sw/lib/vst:~/.vst
  export LXVST_PATH=/nix/var/nix/profiles/default/lib/lxvst:/var/run/current-system/sw/lib/lxvst:~/.lxvst
  export LADSPA_PATH=/nix/var/nix/profiles/default/lib/ladspa:/var/run/current-system/sw/lib/ladspa:~/.ladspa
  export LV2_PATH=/nix/var/nix/profiles/default/lib/lv2:/var/run/current-system/sw/lib/lv2:~/.lv2
  export DSSI_PATH=/nix/var/nix/profiles/default/lib/dssi:/var/run/current-system/sw/lib/dssi:~/.dssi
'';

users = {
  extraUsers.yourname= {
   extraGroups = [ "wheel" "audio" ];
  };
};