Tatsächlich ein sehr interessantes Thema, erstaunlich was pipewire ohne zusätzliche Software nur durch eine entsprechende Konfigurationsdatei leisten kann.
Ich war neugierig und habe eine RT-fähige 10-Band-EQ Konfiguration und eine RT-fähige 10-Band-EQ-virtual_5.1_sound Konfiguration erstellt.
pipewire.conf
# Daemon config file for PipeWire version "1.0.5" #
#
# Copy and edit this file in /etc/pipewire for system-wide changes
# or in ~/.config/pipewire for local changes.
#
# It is also possible to place a file with an updated section in
# /etc/pipewire/pipewire.conf.d/ for system-wide changes or in
# ~/.config/pipewire/pipewire.conf.d/ for local changes.
#
context.properties = {
## Configure properties in the system.
#library.name.system = support/libspa-support
#context.data-loop.library.name.system = support/libspa-support
#support.dbus = true
link.max-buffers = 64
#link.max-buffers = 16 # version < 3 clients can't handle more
#mem.warn-mlock = false
#mem.allow-mlock = true
#mem.mlock-all = false
clock.power-of-two-quantum = true
#log.level = 2
cpu.zero.denormals = true
core.daemon = true # listening for socket connections
core.name = pipewire-0 # core name and socket name
## Properties for the DSP configuration.
default.clock.rate = 48000
default.clock.allowed-rates = [ 44100 48000 ]
default.clock.quantum = 1024
default.clock.min-quantum = 1024
default.clock.max-quantum = 2048
default.clock.quantum-limit = 8192
default.clock.quantum-floor = 4
#
settings.check-quantum = true
settings.check-rate = true
#
# keys checked below to disable module loading
module.x11.bell = true
# enables autoloading of access module, when disabled an alternative
# access module needs to be loaded.
module.access = true
# enables autoloading of module-jackdbus-detect
module.jackdbus-detect = false
}
sink-eq10-wide.conf
context.modules = [
{ name = "libpipewire-module-rt"
# Aktiviert Echtzeit-(RT)-Unterstützung für niedrigere Audio-Latenz.
# Prüfen ob für pipewire eine Konfiguration in /etc/security/limits.d/25-pw-rlimits.conf existiert.
# Der Benutzer unter dem diese Konfiguration geladen wird muss Mitglied der gruppe "pipewire" sein,
# damit die RT-Priorität wirksam wird.
# Prüfen ob es in RT läuft mit: ps -mo pid,tid,rtprio,comm -C pipewire
args = {
rt.prio = 83
rt.time.soft = -1
rt.time.hard = -1
}
flags = [ ifexists nofail ]
}
{ name = "libpipewire-module-filter-chain"
args = {
# node.description und node.name kann nach eigenen Vorstellungen vergeben werden
node.description = "Vivobook Gold Standard Audio"
media.name = "Vivobook Gold Standard Audio"
# Sampling-Rate wird in der PipeWire-Daemon-Config gesetzt:
# (siehe /etc/pipewire/pipewire.conf.d/ oder ~/.config/pipewire/)
# Nicht hier überschreiben, um Konflikte mit globalen Einstellungen zu vermeiden.
# default.clock.rate = 48000
audio.channels = 2
audio.position = [ FL FR ]
filter.graph = {
nodes = [
# 1. Schutz & Klarheit: entfernt unhörbaren Tiefbass (<65Hz)
{ type = "builtin" name = "eq_hp" label = "bq_highpass" control = { Freq = 65.0 Q = 0.1 } }
# 2. Sub-Bass / Kick Peak (bringt Druck)
{ type = "builtin" name = "eq_band_1" label = "bq_peaking" control = { Freq = 80.0 Q = 1.5 Gain = 5.0 } }
# 3. Fundament (200Hz)
{ type = "builtin" name = "eq_band_2" label = "bq_lowshelf" control = { Freq = 200.0 Q = 1.0 Gain = 5.0 } }
# 4. Wärme (400Hz)
{ type = "builtin" name = "eq_band_3" label = "bq_peaking" control = { Freq = 400.0 Q = 0.5 Gain = 3.0 } }
# 5. Anti-Boxy (gegen Papp-Sound)
{ type = "builtin" name = "eq_band_4" label = "bq_peaking" control = { Freq = 600.0 Q = 1.2 Gain = -1.5 } }
# 6. Anti-Nasal (1000Hz)
{ type = "builtin" name = "eq_band_5" label = "bq_peaking" control = { Freq = 1000.0 Q = 1.2 Gain = -2.0 } }
# 7. Mitten-Präzision (Zwischenschritt)
{ type = "builtin" name = "eq_band_6" label = "bq_peaking" control = { Freq = 1500.0 Q = 1.5 Gain = -2.0 } }
# 8. Anti-Plastik (2000Hz)
{ type = "builtin" name = "eq_band_7" label = "bq_peaking" control = { Freq = 2000.0 Q = 1.5 Gain = -3.0 } }
# 9. Präsenz (4500Hz)
{ type = "builtin" name = "eq_band_8" label = "bq_peaking" control = { Freq = 4500.0 Q = 1.5 Gain = 1.5 } }
# 10. Brillanz (9000Hz)
{ type = "builtin" name = "eq_band_9" label = "bq_highshelf" control = { Freq = 9000.0 Q = 1.0 Gain = 2.0 } }
# 11. Air (für das Seidige)
{ type = "builtin" name = "eq_band_10" label = "bq_peaking" control = { Freq = 12000.0 Q = 1.0 Gain = 2.0 } }
# 12. finaler Gain (Lautstärke-Anpassung)
# Berechnung: Faktor = 10^(dB / 20)
# +1dB ≈ 1.12
# +2dB ≈ 1.26
# +3dB ≈ 1.41
# +4dB ≈ 1.58
# +6dB ≈ 2.00
# Faktor 1.15 für soliden Pegel ohne Clipping
{ type = "builtin" name = "final_gain" label = "copy" props = { ["copy.gain"] = 1.15 } }
]
links = [
{ output = "eq_hp:Out" input = "eq_band_1:In" }
{ output = "eq_band_1:Out" input = "eq_band_2:In" }
{ output = "eq_band_2:Out" input = "eq_band_3:In" }
{ output = "eq_band_3:Out" input = "eq_band_4:In" }
{ output = "eq_band_4:Out" input = "eq_band_5:In" }
{ output = "eq_band_5:Out" input = "eq_band_6:In" }
{ output = "eq_band_6:Out" input = "eq_band_7:In" }
{ output = "eq_band_7:Out" input = "eq_band_8:In" }
{ output = "eq_band_8:Out" input = "eq_band_9:In" }
{ output = "eq_band_9:Out" input = "eq_band_10:In" }
{ output = "eq_band_10:Out" input = "final_gain:In" }
]
inputs = [ "eq_hp:In" ]
outputs = [ "final_gain:Out" ]
}
capture.props = {
node.name = "effect_input.eq6"
node.pause-on-idle = true
node.passive = true
media.class = "Audio/Sink"
}
playback.props = {
node.name = "effect_output.eq6"
node.pause-on-idle = true
node.passive = true
channelmix.upmix = true
channelmix.upmix-method = "psd"
channelmix.stereo-widen = 0.35
# target.object: exakter PipeWire/Pulse-Sink-Name, z. B. "alsa_output...._sink"
# Ermitteln mit folgenden Schritten:
# 1) wpctl status
# -> suche die benötigte Sink und merke die ID (links, z. B. 56).
# 2) wpctl inspect <ID>
# -> in der Ausgabe nach "node.name" oder nach einem Eintrag mit "alsa_output" suchen.
# Beispiel: node.name = "alsa_output.pci-0000_03_00.6.HiFi__hw_Generic_1__sink"
# Verwende den gefundenen Namen 1:1 als target.object.
target.object = "alsa_output.pci-0000_03_00.6.HiFi__hw_Generic_1__sink"
}
}
}
]
sink-eq10-5.1.conf
context.modules = [
{ name = "libpipewire-module-rt"
# Aktiviert Echtzeit-(RT)-Unterstützung für niedrigere Audio-Latenz.
# Prüfen ob für pipewire eine Konfiguration in /etc/security/limits.d/25-pw-rlimits.conf existiert.
# Der Benutzer unter dem diese Konfiguration geladen wird muss Mitglied der gruppe "pipewire" sein,
# damit die RT-Priorität wirksam wird.
# Prüfen ob es in RT läuft mit: ps -mo pid,tid,rtprio,comm -C pipewire
args = {
rt.prio = 83
rt.time.soft = -1
rt.time.hard = -1
}
flags = [ ifexists nofail ]
}
{ name = libpipewire-module-filter-chain
flags = [ nofail ]
args = {
node.description = "Vivobook Gold (5.1) Audio"
media.name = "Vivobook Gold (5.1) Audio"
# Sampling-Rate wird in der PipeWire-Daemon-Config gesetzt:
# (siehe /etc/pipewire/pipewire.conf.d/ oder ~/.config/pipewire/)
# Nicht hier überschreiben, um Konflikte mit globalen Einstellungen zu vermeiden.
# default.clock.rate = 48000
filter.graph = {
nodes = [
# Inputs duplizieren (5.1: FL FR FC LFE SL SR)
{ type = builtin label = copy name = copyFL }
{ type = builtin label = copy name = copyFR }
{ type = builtin label = copy name = copyFC }
{ type = builtin label = copy name = copyLFE }
{ type = builtin label = copy name = copySL }
{ type = builtin label = copy name = copySR }
# HeSuVi WAV (Pfad / channel indices anpassen falls nötig)
{ type = builtin label = convolver name = convFL_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 0 } }
{ type = builtin label = convolver name = convFL_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 1 } }
{ type = builtin label = convolver name = convFR_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 8 } }
{ type = builtin label = convolver name = convFR_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 7 } }
{ type = builtin label = convolver name = convFC_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 6 } }
{ type = builtin label = convolver name = convFC_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 13 } }
{ type = builtin label = convolver name = convLFE_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 6 } }
{ type = builtin label = convolver name = convLFE_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 13 } }
{ type = builtin label = convolver name = convSL_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 2 } }
{ type = builtin label = convolver name = convSL_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 3 } }
{ type = builtin label = convolver name = convSR_L config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 10 } }
{ type = builtin label = convolver name = convSR_R config = { filename = "/home/user/.config/pipewire/wav/hesuvi.wav" channel = 9 } }
# Stereo Mixers (vor EQ)
{ type = builtin label = mixer name = mixL }
{ type = builtin label = mixer name = mixR }
# 10-Band EQ (linker Kanal, nach den Mixern)
{ type = "builtin" name = "eq_hp_L" label = "bq_highpass" control = { Freq = 65.0 Q = 0.1 } }
{ type = "builtin" name = "eq_band_1_L" label = "bq_peaking" control = { Freq = 80.0 Q = 1.5 Gain = 5.0 } }
{ type = "builtin" name = "eq_band_2_L" label = "bq_lowshelf" control = { Freq = 200.0 Q = 1.0 Gain = 5.0 } }
{ type = "builtin" name = "eq_band_3_L" label = "bq_peaking" control = { Freq = 400.0 Q = 0.5 Gain = 3.0 } }
{ type = "builtin" name = "eq_band_4_L" label = "bq_peaking" control = { Freq = 600.0 Q = 1.2 Gain = -1.5 } }
{ type = "builtin" name = "eq_band_5_L" label = "bq_peaking" control = { Freq = 1000.0 Q = 1.2 Gain = -2.0 } }
{ type = "builtin" name = "eq_band_6_L" label = "bq_peaking" control = { Freq = 1500.0 Q = 1.5 Gain = -2.0 } }
{ type = "builtin" name = "eq_band_7_L" label = "bq_peaking" control = { Freq = 2000.0 Q = 1.5 Gain = -3.0 } }
{ type = "builtin" name = "eq_band_8_L" label = "bq_peaking" control = { Freq = 4500.0 Q = 1.5 Gain = 1.5 } }
{ type = "builtin" name = "eq_band_9_L" label = "bq_highshelf" control = { Freq = 9000.0 Q = 1.0 Gain = 2.0 } }
{ type = "builtin" name = "eq_band_10_L" label = "bq_peaking" control = { Freq = 12000.0 Q = 1.0 Gain = 2.0 } }
# finaler Gain (Lautstärke-Anpassung)
# Berechnung: Faktor = 10^(dB / 20)
# +1dB ≈ 1.12
# +2dB ≈ 1.26
# +3dB ≈ 1.41
# +4dB ≈ 1.58
# +6dB ≈ 2.00
# Faktor 1.15 für soliden Pegel ohne Clipping
{ type = "builtin" name = "final_gain_L" label = "copy" props = { ["copy.gain"] = 1.15 } }
# 10-Band EQ (rechter Kanal, nach den Mixern)
{ type = "builtin" name = "eq_hp_R" label = "bq_highpass" control = { Freq = 65.0 Q = 0.1 } }
{ type = "builtin" name = "eq_band_1_R" label = "bq_peaking" control = { Freq = 80.0 Q = 1.5 Gain = 5.0 } }
{ type = "builtin" name = "eq_band_2_R" label = "bq_lowshelf" control = { Freq = 200.0 Q = 1.0 Gain = 5.0 } }
{ type = "builtin" name = "eq_band_3_R" label = "bq_peaking" control = { Freq = 400.0 Q = 0.5 Gain = 3.0 } }
{ type = "builtin" name = "eq_band_4_R" label = "bq_peaking" control = { Freq = 600.0 Q = 1.2 Gain = -1.5 } }
{ type = "builtin" name = "eq_band_5_R" label = "bq_peaking" control = { Freq = 1000.0 Q = 1.2 Gain = -2.0 } }
{ type = "builtin" name = "eq_band_6_R" label = "bq_peaking" control = { Freq = 1500.0 Q = 1.5 Gain = -2.0 } }
{ type = "builtin" name = "eq_band_7_R" label = "bq_peaking" control = { Freq = 2000.0 Q = 1.5 Gain = -3.0 } }
{ type = "builtin" name = "eq_band_8_R" label = "bq_peaking" control = { Freq = 4500.0 Q = 1.5 Gain = 1.5 } }
{ type = "builtin" name = "eq_band_9_R" label = "bq_highshelf" control = { Freq = 9000.0 Q = 1.0 Gain = 2.0 } }
{ type = "builtin" name = "eq_band_10_R" label = "bq_peaking" control = { Freq = 12000.0 Q = 1.0 Gain = 2.0 } }
# finaler Gain (Lautstärke-Anpassung)
# Berechnung: Faktor = 10^(dB / 20)
# +1dB ≈ 1.12
# +2dB ≈ 1.26
# +3dB ≈ 1.41
# +4dB ≈ 1.58
# +6dB ≈ 2.00
# Faktor 1.15 für soliden Pegel ohne Clipping
{ type = "builtin" name = "final_gain_R" label = "copy" props = { ["copy.gain"] = 1.15 } }
]
links = [
# input -> convolver routing (5.1)
{ output = "copyFL:Out" input="convFL_L:In" }
{ output = "copyFL:Out" input="convFL_R:In" }
{ output = "copyFR:Out" input="convFR_L:In" }
{ output = "copyFR:Out" input="convFR_R:In" }
{ output = "copyFC:Out" input="convFC_L:In" }
{ output = "copyFC:Out" input="convFC_R:In" }
{ output = "copyLFE:Out" input="convLFE_L:In" }
{ output = "copyLFE:Out" input="convLFE_R:In" }
{ output = "copySL:Out" input="convSL_L:In" }
{ output = "copySL:Out" input="convSL_R:In" }
{ output = "copySR:Out" input="convSR_L:In" }
{ output = "copySR:Out" input="convSR_R:In" }
# convolver -> final stereo mixers (Downmix/HRIR -> stereo)
{ output = "convFL_L:Out" input="mixL:In 1" }
{ output = "convFL_R:Out" input="mixR:In 1" }
{ output = "convFR_L:Out" input="mixL:In 2" }
{ output = "convFR_R:Out" input="mixR:In 2" }
{ output = "convFC_L:Out" input="mixL:In 3" }
{ output = "convFC_R:Out" input="mixR:In 3" }
{ output = "convLFE_L:Out" input="mixL:In 4" }
{ output = "convLFE_R:Out" input="mixR:In 4" }
{ output = "convSL_L:Out" input="mixL:In 5" }
{ output = "convSL_R:Out" input="mixR:In 5" }
{ output = "convSR_L:Out" input="mixL:In 6" }
{ output = "convSR_R:Out" input="mixR:In 6" }
# mixers -> 10-Band EQ (je Kanal getrennt)
{ output = "mixL:Out" input = "eq_hp_L:In" }
{ output = "eq_hp_L:Out" input = "eq_band_1_L:In" }
{ output = "eq_band_1_L:Out" input = "eq_band_2_L:In" }
{ output = "eq_band_2_L:Out" input = "eq_band_3_L:In" }
{ output = "eq_band_3_L:Out" input = "eq_band_4_L:In" }
{ output = "eq_band_4_L:Out" input = "eq_band_5_L:In" }
{ output = "eq_band_5_L:Out" input = "eq_band_6_L:In" }
{ output = "eq_band_6_L:Out" input = "eq_band_7_L:In" }
{ output = "eq_band_7_L:Out" input = "eq_band_8_L:In" }
{ output = "eq_band_8_L:Out" input = "eq_band_9_L:In" }
{ output = "eq_band_9_L:Out" input = "eq_band_10_L:In" }
{ output = "eq_band_10_L:Out" input = "final_gain_L:In" }
{ output = "mixR:Out" input = "eq_hp_R:In" }
{ output = "eq_hp_R:Out" input = "eq_band_1_R:In" }
{ output = "eq_band_1_R:Out" input = "eq_band_2_R:In" }
{ output = "eq_band_2_R:Out" input = "eq_band_3_R:In" }
{ output = "eq_band_3_R:Out" input = "eq_band_4_R:In" }
{ output = "eq_band_4_R:Out" input = "eq_band_5_R:In" }
{ output = "eq_band_5_R:Out" input = "eq_band_6_R:In" }
{ output = "eq_band_6_R:Out" input = "eq_band_7_R:In" }
{ output = "eq_band_7_R:Out" input = "eq_band_8_R:In" }
{ output = "eq_band_8_R:Out" input = "eq_band_9_R:In" }
{ output = "eq_band_9_R:Out" input = "eq_band_10_R:In" }
{ output = "eq_band_10_R:Out" input = "final_gain_R:In" }
]
# Graph-Eingang sind die duplicate input nodes (5.1)
inputs = [ "copyFL:In" "copyFR:In" "copyFC:In" "copyLFE:In" "copySL:In" "copySR:In" ]
# Graph-Ausgang sind die finalen EQ-Ausgänge (stereo)
outputs = [ "final_gain_L:Out" "final_gain_R:Out" ]
}
capture.props = {
node.name = "effect_input.hesuvi_5.1"
media.class = Audio/Sink
audio.channels = 6
audio.position = [ FL FR FC LFE SL SR ]
}
playback.props = {
node.name = "effect_output.hesuvi_5.1"
node.passive = true
audio.channels = 2
audio.position = [ FL FR ]
# target.object: exakter PipeWire/Pulse-Sink-Name, z. B. "alsa_output...._sink"
# Ermitteln mit folgenden Schritten:
# 1) wpctl status
# -> suche die benötigte Sink und merke die ID (links, z. B. 56).
# 2) wpctl inspect <ID>
# -> in der Ausgabe nach "node.name" oder nach einem Eintrag mit "alsa_output" suchen.
# Beispiel: node.name = "alsa_output.pci-0000_03_00.6.HiFi__hw_Generic_1__sink"
# Verwende den gefundenen Namen 1:1 als target.object.
target.object = "alsa_output.pci-0000_03_00.6.HiFi__hw_Generic_1__sink"
}
}
}
]
Dateien nach ~/.config/pipewire/pipewire.conf.d/ kopieren, target.object ermitteln und eintragen, für RT den Benutzer zur Gruppe "pipewire" hinzufügen, für den 5.1 Virtual Surround benötigt ihr noch eine HeSuVi-Datei HRTF Database, diese im Pfad ablegen und in der config den Benutzernamen im Pfad anpassen, neu starten, in den Audio-Einstellungen entsprechendes Ausgabe-Gerät wählen.
Viel Spaß damit