PulseAudio

PulseAudio is the sound system used by most desktop Linux distributions. The goal of this guide is to teach you the basic knowledge you’ll need to be able to solve your own audio routing situations (e.g., routing an application’s sound and your microphone into Discord while still being able to hear the application).

If you already know the concepts, you can skip down to Routing Audio.

Important Concepts

pavucontrol

pavucontrol (PulseAudio Volume Control) is the best way to interact with PulseAudio because it doesn’t try to simplify or hide these concepts from you (like the volume widgets of many desktop environments do).

The first two tabs of pavucontrol let you adjust the connections and volumes of sink-inputs and source-outputs.

screenshot of pavucontrol’s Playback tab

Note that the sink-inputs and source-outputs correspond to applications, and pavucontrol lets you choose which sinks and sources they are attached to.

Device Naming

Each device has a name used internally by PulseAudio as well as a description which is meant to be human-readable.

pavucontrol shows the description, not the internal name.

pavucontrol showing a sink called “Sound Core3D [Sound Blaster Recon3D / Z-Series] (SB1570 SB Audigy Fx) Analog Stereo”

Sometimes the “human-readability” of the description is questionable.

Finding Device Names

Use the list-sinks or list-sources commands and search for the lines that contain name: or device.description =. Then find the name that matches the description.

$ pacmd list-sinks | grep -E 'name:|device\.description'
        name: <alsa_output.pci-0000_00_1f.3.analog-stereo>
                device.description = "Sound Core3D [Sound Blaster Recon3D / Z-Series] (SB1570 SB Audigy Fx) Analog Stereo"
        name: <bluez_sink.38_18_4C_7D_5C_08.a2dp_sink>
                device.description = "Headphones"

The name is the part between the <> brackets (i.e., the brackets are not part of the name).

Changing Device Descriptions

Use the update-sink-proplist or update-source-proplist commands to change the device.description property.

$ pacmd update-sink-proplist $speakers 'device.description="Laptop Speakers"'

pavucontrol showing a sink called “Laptop Speakers”

Now that’s what I call “human-readable”!

Useful Modules

Null Sink

A null sink is a virtual sink that discards audio sent to it. That’s not very useful by itself, but the monitor that comes with it can be very useful.

Use load-module module-null-sink to create a new null sink.

$ pacmd load-module module-null-sink \
    sink_name=null \
    sink_properties=\'device.description=\"Null Output\"\'

You can omit the sink_name and sink_properties arguments if you don’t care about the name and description (you’ll get the defaults, “null” and “Null Output”). But if this is part of a more complex setup, it’s worth it to set descriptive names from the beginning (see Application to Application for a practical example).

Use pavucontrol to route application audio to the null sink as desired.

Combined Sink

A combined sink is a virtual sink that forwards audio to multiple other sinks.

First, find the names of the sinks you want to combine, then use load-module module-combine-sink to create a new combined sink.

$ pacmd load-module module-combine-sink slaves=$speakers,$headphones

The combined sink will automatically have a readable description.

Loopback

A loopback forwards audio from a source to a sink.

Use load-module module-loopback to create a new loopback.

$ pacmd load-module module-loopback

Then use pavucontrol to choose which source and sink the loopback should use.

Routing Audio

Application to Application

Use a null sink to receive the audio from the source application, and configure the other application to read from the monitor of the null sink.

Let’s set things up to route the audio from Firefox to a Discord voice channel. First, create a null sink called “Discord Input”.

$ pacmd load-module module-null-sink \
    sink_name=discord \
    sink_properties=\'device.description=\"Discord Input\"\'

In pavucontrol’s Playback tab, route the audio from Firefox there.

selecting “Discord Input” in pavucontrol

In pavucontrol’s Recording tab, route the audio from the monitor to Discord.

selecting “Monitor of Discord Input” in pavucontrol

Voilà!

Application to Application+Speakers

Follow the previous instructions, then add a combined sink that forwards to the null sink and the speakers.

After following the previous example, set up the combined sink.

$ pacmd load-module module-combine-sink slaves=discord,$speakers

selecting “Simultaneous output to Discord Input, Laptop Speakers” in pavucontrol

Application to Application+Speakers and Microphone to Application

Follow the previous instructions, then add a loopback that forwards the microphone to the null sink.

After following the previous example, set up the loopback.

$ pacmd load-module module-loopback

In pavucontrol’s Recording tab, route the audio from the microphone to the loopback.

selecting “...” in pavucontrol

In pavucontrol’s Playback tab, route the audio from the loopback to the null sink.

selecting “...” in pavucontrol