diff --git a/modules/desktop/audio.nix b/modules/desktop/audio.nix index ccc5abb8..71531680 100644 --- a/modules/desktop/audio.nix +++ b/modules/desktop/audio.nix @@ -4,12 +4,193 @@ lib, ... }: +with lib; let cfg = config.xyno.desktop.audio; + json = pkgs.formats.json { }; + toFloat = builtins.fromJSON; + readFilterTxt = + text: + let + lines = splitString "\n" text; + consumeLine = + line: + let + parts = splitString " " line; + content = foldl ( + props: str: + if props.lastNode == "Filter" then + props + // { + nr = toInt (removeSuffix ":" str); + lastNode = str; + } + else if props.lastNode == "Preamp:" then + props + // { + nr = 0; + gain = toFloat str; + label = "HSC"; + lastNode = str; + freq = 0; + q = 1.0; + } + else if props.lastNode == "ON" then + props + // { + label = str; + lastNode = str; + } + else if props.lastNode == "Fc" then + props + // { + freq = toInt str; + lastNode = str; + } + else if props.lastNode == "Gain" then + props + // { + gain = toFloat str; + lastNode = str; + } + else if props.lastNode == "Q" then + props + // { + q = toFloat str; + lastNode = str; + } + else + + props // { lastNode = str; } + ) { lastNode = null; } parts; + in + content; + in + filter (x: x ? nr) (map consumeLine lines); + genFilterGraph = filters: { + nodes = ( + map (filter: { + type = "builtin"; + name = "eq_band_${toString (filter.nr + 1)}"; + label = + if filter.label == "HSC" then + "bq_highshelf" + else if filter.label == "LSC" then + "bq_lowshelf" + else + "bq_peaking"; + control = { + Freq = filter.freq; + Q = filter.q; + Gain = filter.gain; + }; + + }) filters + ); + links = map (x: { + output = "eq_band_${toString x}:Out"; + input = "eq_band_${toString (x + 1)}:In"; + }) (range 1 ((builtins.length filters) - 1)); + }; + genfilterChain = + cfg': + json.generate "filter-chain.json" ( + recursiveUpdate { + "node.description" = cfg'.displayName; + "media.name" = cfg'.displayName; + "filter.graph" = genFilterGraph (readFilterTxt cfg'.filterText); + "audio.channels" = 2; + "audio.position" = [ + "FL" + "FR" + ]; + "capture.props" = { + "node.name" = "effect_input.${cfg'.internalName}"; + "media.class" = "Audio/Sink"; + }; + "playback.props" = { + "node.name" = "effect_output.${cfg'.internalName}"; + "node.passive" = true; + "target.object" = cfg'.hwAddr; + }; + } cfg'.extraConfig + ); + eqPkg = + cfg': + (pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/99-${cfg'.internalName}.conf" '' + node.software-dsp.rules = [ + { + matches = [{ node.name = "${cfg'.hwAddr}" }] + actions = { + create-filter = { + filter-path = "${genfilterChain cfg'}" + hide-parent = ${boolToString cfg'.hideParent} + } + } + } + ] + + wireplumber.profiles = { + main = { node.software-dsp = "required" } + } + '') + // { + passthru.requiredLv2Packages = with pkgs; [ + lsp-plugins + bankstown-lv2 + ]; + + }; + + eqSubmodule = + { name, ... }: + { + options = { + internalName = mkOption { + type = types.str; + default = name; + internal = true; + }; + displayName = mkOption { type = types.str; }; + hwAddr = mkOption { type = types.str; }; + filterText = mkOption { type = types.str; }; + hideParent = mkOption { + type = types.bool; + default = true; + }; + extraConfig = mkOption { + type = types.attrsOf types.anything; + default = { }; + }; + }; + }; + in { - options.xyno.desktop.audio.enable = lib.mkEnableOption "enable pipewire and stuff"; - config = lib.mkIf cfg.enable { + options.xyno.desktop.audio.enable = mkEnableOption "enable pipewire and stuff"; + options.xyno.desktop.audio.eq = mkOption { + type = types.attrsOf (types.submodule eqSubmodule); + default = { }; + }; + config = mkIf cfg.enable { + xyno.desktop.audio.eq.se215 = { + displayName = "Shure SE215"; + hwAddr = "alsa_output.usb-Synaptics_CX31993_384Khz_HIFI_AUDIO-00.analog-stereo"; + extraConfig."capture.props"."device.icon-name" = "audio-headphones"; + filterText = '' + Preamp: -5.7 dB + Filter 1: ON LSC Fc 105 Hz Gain 0.3 dB Q 0.70 + Filter 2: ON PK Fc 174 Hz Gain -4.6 dB Q 0.68 + Filter 3: ON PK Fc 811 Hz Gain 3.1 dB Q 1.42 + Filter 4: ON PK Fc 3430 Hz Gain 3.8 dB Q 4.37 + Filter 5: ON PK Fc 6943 Hz Gain 5.4 dB Q 2.76 + Filter 6: ON HSC Fc 10000 Hz Gain 3.8 dB Q 0.70 + Filter 7: ON PK Fc 5725 Hz Gain 8.1 dB Q 1.13 + Filter 8: ON PK Fc 5056 Hz Gain -10.9 dB Q 2.93 + Filter 9: ON PK Fc 7269 Hz Gain -6.3 dB Q 3.47 + Filter 10: ON PK Fc 2278 Hz Gain -2.1 dB Q 2.94 + ''; + }; services.pipewire = { enable = true; # raopOpenFirewall = true; # airplay @@ -20,7 +201,9 @@ in "default.clock.allowed-rates" = [ "44100" "48000" + "88200" "96000" + "176400" "192000" ]; }; @@ -44,6 +227,9 @@ in ]; }; }; + wireplumber.extraConfig."98-bluetooth"."wireplumber.settings"."bluetooth.autoswitch-to-headset-profile" = + false; + wireplumber.configPackages = mapAttrsToList (n: v: eqPkg v) cfg.eq; }; };