Setting up pipewire to get rid of cracks & noises

Hi,

I’m running NixOS unstable with Home Manager and Flakes. I’m using a RME Babyface Pro external audio interface plugged in via USB. It’s properly recognized and functional, except that there are regular cracks and hissing noises.

Here’s flake.nix

description = "Config NixOS";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    musnix.url = "github:musnix/musnix";
    home-manager = {
      url = "github:nix-community/home-manager/master";      
      inputs.nixpkgs.follows = "nixpkgs";
    };
    stylix = { url = "github:danth/stylix"; };
    plasma-manager = {
      url = "github:nix-community/plasma-manager";
      inputs.nixpkgs.follows = "nixpkgs";
      inputs.home-manager.follows = "home-manager";
    };
    audio = {
      url = "github:polygon/audio.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    inputs@{
        nixpkgs,
        home-manager,
        plasma-manager,
        sops-nix,
        ...
      }:
      {
        nixosConfigurations = {
          oslandell = nixpkgs.lib.nixosSystem {
            system = "x86_64-linux";
            modules = [
              ./configuration.nix
              home-manager.nixosModules.home-manager
              {
                home-manager.useGlobalPkgs = true;
                home-manager.backupFileExtension = "backup6";
                home-manager.useUserPackages = true;
                home-manager.sharedModules = [ plasma-manager.homeManagerModules.plasma-manager ];
                home-manager.users.jeremy = import ./home.nix;
              }
              inputs.musnix.nixosModules.musnix
              inputs.stylix.nixosModules.stylix
              sops-nix.nixosModules.sops
            ];
            specialArgs = { inherit inputs; };
          };
        };
      };
}

home.nix:

{ config, pkgs, lib, inputs, ... }:

{ imports = 
    ./programs/git.nix
    ./programs/kate.nix
    ./programs/neovim.nix
    ./programs/plasma.nix
    ./programs/zsh.nix
  ];
  
  home.username = "jeremy";
  home.homeDirectory = "/home/jeremy";
  home.packages = with pkgs; [

    ...

    # audio
    jack2
    vlc
    ardour
    mixxx
    yabridge
    yabridgectl
    vcv-rack
    bitwig-studio
    easyeffects
    
    # vst
    odin2
    surge-XT
    ladspaPlugins
    
  ];

  home.stateVersion = "24.05";
  programs.home-manager.enable = true;
}

and configuration.nix:



{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
#       <home-manager/nixos>
    ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # https://nixos.wiki/wiki/Laptop
  services.thermald.enable = true;
  services.tlp.enable = false;
  services.auto-cpufreq.enable = false;

  boot.initrd.luks.devices."luks-c96b55bc-dc39-4583-9936-9cf0835bd9a3".device = "/dev/disk/by-uuid/c96b55bc-dc39-4583-9936-9cf0835bd9a3";

  networking.hostName = "oslandell";
  networking.networkmanager.enable = true;

  # Bluetooth
  hardware.bluetooth.enable = true;
  hardware.bluetooth.powerOnBoot = true;
  
  hardware.graphics = {
    enable = true;
  };  

  # NVIDIA CONFIG - see https://nixos.wiki/wiki/Nvidia
  # --------------------------------------------------

  # Load nvidia driver for Xorg and Wayland
  services.xserver.videoDrivers = ["nvidia"];

  hardware.nvidia = {

    # Modesetting is required.
    modesetting.enable = true;

    # Nvidia power management. Experimental, and can cause sleep/suspend to fail.
    # Enable this if you have graphical corruption issues or application crashes after waking
    # up from sleep. This fixes it by saving the entire VRAM memory to /tmp/ instead
    # of just the bare essentials.
    powerManagement.enable = false;

    # Fine-grained power management. Turns off GPU when not in use.
    # Experimental and only works on modern Nvidia GPUs (Turing or newer).
    powerManagement.finegrained = true;

    # Use the NVidia open source kernel module (not to be confused with the
    # independent third-party "nouveau" open source driver).
    # Support is limited to the Turing and later architectures. Full list of
    # supported GPUs is at:
    # https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus
    # Only available from driver 515.43.04+
    # Currently alpha-quality/buggy, so false is currently the recommended setting.
    open = false;

    # Enable the Nvidia settings menu,
    # accessible via `nvidia-settings`.
    nvidiaSettings = true;

    # Optionally, you may need to select the appropriate driver version for your specific GPU.
    package = config.boot.kernelPackages.nvidiaPackages.stable;

    prime = {

      # Sync or Offload can't be activated at the same time. See doc on NixOS wiki.

      # sync.enable = true;

      offload = {
        enable = true;
        enableOffloadCmd = true;
      };

      intelBusId = "PCI:0:2:0";
      nvidiaBusId = "PCI:1:0:0";
    };

  };

  # --------------------------------------------------

  time.timeZone = "Europe/Paris";
  i18n.defaultLocale = "fr_FR.UTF-8";
  i18n.extraLocaleSettings = {
    LC_ADDRESS = "fr_FR.UTF-8";
    LC_IDENTIFICATION = "fr_FR.UTF-8";
    LC_MEASUREMENT = "fr_FR.UTF-8";
    LC_MONETARY = "fr_FR.UTF-8";
    LC_NAME = "fr_FR.UTF-8";
    LC_NUMERIC = "fr_FR.UTF-8";
    LC_PAPER = "fr_FR.UTF-8";
    LC_TELEPHONE = "fr_FR.UTF-8";
    LC_TIME = "fr_FR.UTF-8";
  };

  # You can disable this if you're only using the Wayland session.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager.sddm.enable = true;
  services.desktopManager.plasma6.enable = true;

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "fr";
    variant = "azerty";
  };

  # Configure console keymap
  console.keyMap = "fr";

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable autodiscovery of network printers
  services.avahi = {
    enable = true;
    nssmdns4 = true;
    openFirewall = true;
  };

  # Enable sound with pipewire
  hardware.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    jack.enable = true;
    # https://nixos.wiki/wiki/PipeWire#Advanced_Configuration
    extraConfig.pipewire."92-low-latency" = {
      "context.properties" = {
        "default.clock.rate" = 48000;
        "default.clock.quantum" = 512;
        "default.clock.min-quantum" = 128;
        "default.clock.max-quantum" = 2048;
        };
     };
    # "As a general rule, the values in pipewire-pulse should not 
    # be lower than the ones in pipewire."
    extraConfig.pipewire-pulse."92-low-latency" = {
      context.modules = [
        {
          name = "libpipewire-module-protocol-pulse";
          args = {
            pulse.min.req = "512/48000";
            pulse.default.req = "512/48000";
            pulse.max.req = "512/48000";
            pulse.min.quantum = "128/48000";
            pulse.max.quantum = "2048/48000";
          };
        }
      ];
      stream.properties = {
        node.latency = "512/48000";
        resample.quality = 1;
      };
    };

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.jeremy = {
    isNormalUser = true;
    description = "Jérémy Garniaux";
    extraGroups = [ "networkmanager" "wheel" ];
    shell = pkgs.zsh;
  };

  # automatic periodic optimisation of the nix store
  nix.optimise.automatic = true;
  nix.optimise.dates = [ "03:45" ];

  # Enable the Flakes feature and the accompanying new nix command-line tool
  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  # Avoid authorisation error while launching devenv as user jeremy
  nix.extraOptions = ''
    trusted-users = root jeremy
    '';
  
  environment.systemPackages = with pkgs; [

    # Flakes clones its dependencies through the git command,
    # so git must be installed first (nb: not if home manager is activated)

    glibc
    gnupg
    lshw
    firewalld
    wayland-utils
    vulkan-tools
    powertop
    clinfo
    glxinfo
    fprintd
    postgresql
    postgresql15Packages.postgis
    libpqxx
    firefox
    thunderbird
    autoPatchelfHook
    mangohud
    steam-run
    
    # Wine
    wineWowPackages.waylandFull
    
    # Nix language server for LSP: https://github.com/oxalica/nil
    nil
    
  ];
  
  fonts.packages = with pkgs; [
    nerdfonts
  ];

  programs = {
    ...
    };

  };

  services.getty.autologinUser = "jeremy";
  environment = {
    loginShellInit = ''
      [[ "$(tty)" = "/dev/tty1" ]] && ./gs.sh
    '';
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # Allow Electron to run (Logseq)
  nixpkgs.config.permittedInsecurePackages = [
    "electron-27.3.11"
  ];

  services.openssh.enable = true;
  services.fprintd.enable = true;
  services.davfs2.enable = true;
  system.stateVersion = "24.05";

}

As you can see, I tried to add a dedicated section in the config to set up pipewire:

    # https://nixos.wiki/wiki/PipeWire#Advanced_Configuration
    extraConfig.pipewire."92-low-latency" = {
      "context.properties" = {
        "default.clock.rate" = 48000;
        "default.clock.quantum" = 512;
        "default.clock.min-quantum" = 128;
        "default.clock.max-quantum" = 2048;
        };
     };
    # "As a general rule, the values in pipewire-pulse should not 
    # be lower than the ones in pipewire."
    extraConfig.pipewire-pulse."92-low-latency" = {
      context.modules = [
        {
          name = "libpipewire-module-protocol-pulse";
          args = {
            pulse.min.req = "512/48000";
            pulse.default.req = "512/48000";
            pulse.max.req = "512/48000";
            pulse.min.quantum = "128/48000";
            pulse.max.quantum = "2048/48000";
          };
        }
      ];
      stream.properties = {
        node.latency = "512/48000";
        resample.quality = 1;
      };
    };

But what I’ve tried so far didn’t change anything to the noises.

Any suggestion would be welcome, thanks!

1 Like

I had similar issues with my USB DAC, and I tried a lot of the stuff you have here to little effect.
The one thing that made the biggest difference on my system was setting
boot.kernelParams = [ "preempt=full" ];. It still isn’t perfect on my system when it’s loaded, like during a compile or something, but it’s much better than it was.

1 Like

Thanks, I’ve added the setting. Firsts tests are rather conclusive, let’s see how it does through time!

So the situation is globally better, but cracks and noises came back a few days after having apparently disappeared. Now, sometimes I can listen for a couple of hours without noises, but they always end up coming back.

I’m not sure about the way I’ve set up pipewire, in particular regarding clock.rate, clock.quantum, min-quantum and max-quantum. And is the pipewire.pulse section even needed?

Any feedback about pipewire configuration would be greatly appreciated!

AFAIK you have to transform all of the keys with a dot as a string to make them render correctly in the config - like it is done in your pipewire low-latency config. In particular, you need to write "context.modules", "stream.properties", "pulse.min.req" and so on.

2 Likes