Add pipewire/pulseaudio Profile-sets and Paths

Hey folks getting a bit stuck here in adding a some configuration for pipewire/pulseaudio.

I’ve an SteelSeries Arctis 7 and only the input is detected when I’m connecting it via USB.

Luckily the community(Github) as already fixed the problem some years ago and I’m trying to integrate into my NixOS configuration. Where I’m getting stuck and that’s due to my lack of knowledge on how Pipewire/Pulseaudio work internally, is adding those configurations.

I’ve tried different things so far via a runCommand

  environment.systemPackages = with pkgs; [
    (runCommand "steelseries-arctis-profiles"
      {
        nativeBuildInputs = [ coreutils ];
      }
      ''
        mkdir -p $out/usr/share/pulseaudio/alsa-mixer/paths
        mkdir -p $out/usr/share/pulseaudio/alsa-mixer/profile-sets

        # Copy the ALSA mixer paths
        cp ${inputs.steelseries-arctis}/steelseries-arctis-7-output-game.conf $out/usr/share/pulseaudio/alsa-mixer/paths/
        cp ${inputs.steelseries-arctis}/steelseries-arctis-7-output-chat.conf $out/usr/share/pulseaudio/alsa-mixer/paths/

        # Copy the ALSA profile set
        cp ${inputs.steelseries-arctis}/steelseries-arctis-7-usb-audio.conf $out/usr/share/pulseaudio/alsa-mixer/profile-sets/
      ''
    )
  ];

Or an ActivationScript

  system.activationScripts = {
    arctis-profiles = ''
      mkdir -p /usr/share/pulseaudio/alsa-mixer/paths
      mkdir -p /usr/share/pulseaudio/alsa-mixer/profile-sets

      # Copy the ALSA mixer paths
      cp ${inputs.steelseries-arctis}/steelseries-arctis-7-output-game.conf /usr/share/pulseaudio/alsa-mixer/paths/
      cp ${inputs.steelseries-arctis}/steelseries-arctis-7-output-chat.conf /usr/share/pulseaudio/alsa-mixer/paths/

      # Copy the ALSA profile set
      cp ${inputs.steelseries-arctis}/steelseries-arctis-7-usb-audio.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/
    '';
  };
];

But none of those two works so far.

I managed to add the udev rules like so:

    services.udev.packages = [
      (pkgs.writeTextFile {
        name = "91-pulseaudio-steelseries-arctis-7.rules";
        text = builtins.readFile "${inputs.steelseries-arctis}/91-pulseaudio-steelseries-arctis-7.rules";
        destination = "/lib/udev/rules.d/91-pulseaudio-steelseries-arctis-7.rules";
      })
    ];

Just to make sure I understand that I’m indeed running Pipewire this is my audio setup configuration

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

    # Enable sound with pipewire.
    pulseaudio.enable = false;
    pipewire = {
      enable = true;
      alsa.enable = true;
      alsa.support32Bit = true;
      pulse.enable = true;
      lowLatency = {
        enable = true;
        quantum = 64;
        rate = 48000;
      };
    };
  };

  # Make pipewire realtime-capable
  security.rtkit.enable = true;
};

Any help would be appreciated on how I could add those 3 files into the Pipewire/PulseAudio configuration!

That will not work on NixOS at all as we do not use those paths. It may work by accident though but that is more a bug than a feature.

Pipewire is not using those packages but those extra packages options found on https://search.nixos.org/options?channel=unstable&query=pipewire\*pack

Maybe something from my config as an example:

      configPackages =
        let
          # https://github.com/werman/noise-suppression-for-voice#pipewire
          mkFilterChain = { name, capture, playback }: {
            name = "libpipewire-module-filter-chain";
            args = {
              "node.description" = name;
              "media.name" = name;
              "filter.graph" = {
                nodes = [ {
                  type = "ladspa";
                  name = "rnnoise";
                  plugin = "${pkgs.rnnoise-plugin.ladspa}/lib/ladspa/librnnoise_ladspa.so";
                  label = "noise_suppressor_mono";
                  control = {
                    "VAD Threshold (%)" = 75.0;
                    "VAD Grace Period (ms)" = 200;
                    "Retroactive VAD Grace (ms)" = 100;
                  };
                } ];
              };
              "capture.props" = {
                "audio.rate" = 48000;
              } // capture;
              "playback.props" = {
                "audio.rate" = 48000;
              } // playback;
            };
          };
        in
        [
          (pkgs.writeTextDir "share/pipewire/pipewire.conf.d/99-input-denoising.conf" (builtins.toJSON {
            "context.modules" = [
              (mkFilterChain {
                name = "Noise Cancelling Source";
                capture = {
                  # > indicate that a link is passive and does not cause the graph to be runnable.
                  # https://docs.pipewire.org/group__pw__keys.html#gafcd3d133168b9353c89c1c5f2de6954e
                  "node.passive" = true;
                  "node.name" = "capture.rnnoise_source";
                };
                playback = {
                  "node.name" = "rnnoise_source";
                  "media.class" = "Audio/Source";
                };
              })

              (mkFilterChain {
                name = "Noise Cancelling Sink";
                capture = {
                  "node.name" = "capture.rnnoise_sink";
                  "media.class" = "Audio/Sink";
                };
                playback = {
                  "node.passive" = true;
                  "node.name" = "rnnoise_sink";
                  "media.class" = "Stream/Output/Audio";
                };
              })
            ];
          }))
        ];
      pulse.enable = true;
    };

1 Like

I see, I think the best way I found is to convert those alsa configuration to pipewire. Haven’t found an easy so far to do with PulseAudio. Thanks for the config i’ll use it as a starter!

1 Like