Arbitrary routing in PulseAudio
Recently, I needed to connect people chatting on Skype with another person that I connect to using trx, while keeping me (on the physical microphone and headphones) in the conversation. So we have a three-way chat problem here, with three pairs of input-output devices, where everyone wants to hear everyone else (but not themself).
Fortunately, Emma Joe Anderson wrote a fantastic guide on how to do arbitrary routing in PulseAudio in a very clear and systematic way.
Compared to Emma's excellent post, this blog post just adds a bit of convenience by setting up the virtual devices and the loopback arrows in one shell script, and by making the names of virtual devices visible in configuration tools. This means that the "internal plumbing" will be created completely automatically, and since the devices are now named, you don't have to worry about the order in which you create them.
You will still have to connect your applications to the internal
plumbing manually in pulsemixer
or
pavucontrol
. However, this should be easier now that you
can see the names of the virtual devices.
Follow Emma's guide
Follow Emma's guide, namely steps Draw the graph you want, Identify the devices, Replace non-devices with virtual sinks, Remove unnecessary virtual sinks.
Stop before Applying a solution.
My routing graph
Here's the graph I obtained by following Emma's procedure.

It contains two real devices (mic
and spk
),
four virtual devices (v1
.. v4
), four
applications (rx
, tx
, skype in
,
skype out
), and six edges between devices. Your graph will
be different but I include the picture to illustrate how it relates to
the shell script below.
The script
We'll start the configuration script by defining the functions that create virtual sinks and edges (loopbacks) between them:
#!/bin/sh
virt() {
pactl load-module module-null-sink \
sink_name="$1" \
sink_properties=device.description="$1"
}
edge() {
pactl load-module module-loopback \
source="$1" \
sink="$2"
}
Then we define the local microphone & headphone source and sink.
You can find yours by running pactl list sources
and
pactl list sinks
. Mine look like this:
mic="alsa_input.usb-0d8c_USB_Sound_Device-00.analog-stereo"
spk="alsa_output.usb-0d8c_USB_Sound_Device-00.analog-stereo"
That's the existing devices defined. Now we create the devices that do not exist yet:
virt v1
virt v2
virt v3
virt v4
Unlike in Emma's guide, you don't need to remember their numbers or ordering because you just give them names.
Finally, make connections between the devices. Microphones are sources, so you can draw an edge from them directly. Our virtual sinks are... well, sinks, so you need to draw edges from their monitors, as shown below:
edge v1.monitor v2
edge v1.monitor $spk
edge $mic v2
edge $mic v3
edge v4.monitor v3
edge v4.monitor $spk
And that's it for the shell script!
When you run it, it'll create all the plumbing. If you want to start over, just restart pulseaudio.
The manual bit
In pulsemixer
or pavucontrol
, move the
output of Skype to v4
, the input of Skype to (the monitor
of) v2
, the output of rx
to v1
,
and the input of tx
to (the monitor of)
v3
.
That's it!