DSP policy for handling audio devices requiring filter chains
Scope
Addresses pipewire#2210
The issue should remain open for further improvements yet to come with 0.5 (next-rebased)
Description
For now, a DSP policy is added for automatically adding appropriate filter chains by rules from configuration.
Progress
-
Load filter chains on demand -
Unload filter chains when corresponding sink is unplugged (needs the fix from pipewire!1351 (merged)) -
A way to update profile -
Prevent profile policy from touching the profileUse device-profile to switch the DSP nodes
-
-
Hide sinks from the graph (might require PipeWire changes, but access policy should be enough) -
Hide intermediate streams -
Disable hiding in a config -
Check for validity (not conflicting with other policies) -
Disable the possibility of user switching the profile in pavucontrol or somewhere else -
Prevent streams from being transitionable. For now, EasyEffects could move the stream to its sink (This will be achieved when streams are hidden)
-
-
Support sources (microphone with DSP) -
Also filter by device constraints (if really useful)
Optional:
-
Better way to describe filter-chains (pipewire!1359 (closed)) -
Load JSON files from WP -
Populate target serial into the configuration
-
The remaining tasks to be moved to next-rebased
are now tracked back in the original issue: pipewire#2210 (comment 1518875)
Testing
This is written into my src/config/policy.lua.d/51-dsp-config.lua
(should really be somewhere in /usr/share
):
table.insert (dsp_policy.policy.rules,
{
matches = {
{
{ "media.class", "matches", "*/Sink" },
{ "node.name", "=", "alsa_output.pci-0000_03_00.6.analog-stereo" }
},
},
device_matches = {
{
{ "device.name", "=", "alsa_card.pci-0000_03_00.6" }
},
},
filter_chain = '{"media.name":"My DSP Speakers 2", "capture.props":{"node.virtual":false, "audio.channels":2, "audio.position":["FL", "FR"], "node.name":"audio_output.platform-audio.analog-stereo-laptop", "media.class":"Audio/Sink", "device.api":"dsp"}, "node.description":"My DSP Speakers 2", "filter.graph":{"outputs":["conv_l:Out", "conv_r:Out"], "links":[{"output":"mix:Out", "input":"copy_l:In"}, {"output":"mix:Out", "input":"copy_r:In"}, {"output":"copy_l:Out", "input":"conv_l:In"}, {"output":"copy_r:Out", "input":"conv_r:In"}], "nodes":[{"type":"builtin", "control":{"Gain 1":0.500000, "Gain 2":0.500000}, "label":"mixer", "name":"mix"}, {"type":"builtin", "label":"copy", "name":"copy_l"}, {"type":"builtin", "label":"copy", "name":"copy_r"}, {"type":"builtin", "name":"conv_l", "label":"convolver", "config":{"filename":"/tmp/firs_j314_tweeters.wav"}}, {"type":"builtin", "name":"conv_r", "label":"convolver", "config":{"filename":"/tmp/firs_j314_tweeters.wav"}}], "inputs":["mix:In 1", "mix:In 2"]}, "playback.props":{"audio.channels":2, "audio.position":["AUX0", "AUX1"], "target.object":"alsa_output.pci-0000_03_00.6.analog-stereo", "node.passive":true, "node.name": "dsp_output.platform-audio.analog-stereo-laptop"}}',
properties = {
profile = "output:analog-stereo+input:analog-stereo",
},
}
)
-- Used to hide streams
table.insert (dsp_policy.policy.rules,
{
matches = {
{
{ "node.name", "=", "dsp_output.platform-audio.analog-stereo-laptop" }
},
},
properties = {
hide = true,
},
}
)
table.insert (dsp_policy.policy.rules,
{
matches = {
{
{ "media.class", "matches", "*/Source" },
{ "node.name", "=", "alsa_input.pci-0000_03_00.6.analog-stereo" }
},
},
filter_chain = '{"media.name":"My DSP mic", "capture.props":{"audio.channels":2, "audio.position":["AUX0", "AUX1"], "target.object":"alsa_input.pci-0000_03_00.6.analog-stereo", "node.passive":true, "node.name": "dsp_input.platform-audio.mic"}, "node.description":"My DSP mic 2", "filter.graph":{"outputs":["conv_l:Out", "conv_r:Out"], "links":[{"output":"mix:Out", "input":"copy_l:In"}, {"output":"mix:Out", "input":"copy_r:In"}, {"output":"copy_l:Out", "input":"conv_l:In"}, {"output":"copy_r:Out", "input":"conv_r:In"}], "nodes":[{"type":"builtin", "control":{"Gain 1":0.500000, "Gain 2":0.500000}, "label":"mixer", "name":"mix"}, {"type":"builtin", "label":"copy", "name":"copy_l"}, {"type":"builtin", "label":"copy", "name":"copy_r"}, {"type":"builtin", "name":"conv_l", "label":"convolver", "config":{"filename":"/tmp/firs_j314_tweeters.wav"}}, {"type":"builtin", "name":"conv_r", "label":"convolver", "config":{"filename":"/tmp/firs_j314_tweeters.wav"}}], "inputs":["mix:In 1", "mix:In 2"]}, "playback.props":{"node.virtual":false, "audio.channels":2, "audio.position":["FL", "FR"], "node.name":"audio_input.platform-audio.mic", "media.class":"Audio/Source", "device.api":"dsp"}}',
properties = {
profile = "output:analog-stereo+input:analog-stereo",
},
}
)
table.insert (dsp_policy.policy.rules,
{
matches = {
{
{ "node.name", "=", "dsp_input.platform-audio.mic" }
},
},
properties = {
hide = true,
},
}
)
Edited by Dmitry Sharshakov