Creating (and binding REAPER to) a virtual microphone using PipeWire

Throwing this one together real quickly, apologies for any typos or whatever. I make no promises that this is the correct way to do any of this, but hopefully it's helpful to anyone who needs it.
Environment
I'm running the latest version of EndeavourOS, which has pipewire configured out of the box. The only audio-related change I've made is to install lib32-pipewire-jack in addition to the pre-installed lib32-pipewire, which fixed mic static when Source 2 games (Counter-Strike 2, Deadlock) were attempting to access the virtual microphone.
Side note: For the love of god make sure you check your Steam voice settings and confirm that the correct input device is selected. In my case, I also disabled all post-processing options (especially auto-adjust gain) and fiddled with the volume knob here until my teammates said I was loud enough.
Notes
Basically, this boils down to: make sure REAPER is open; use pactl to create a virtual source using PulseAudio; use pw-link to unplug specific unwanted connections created automatically by the various audio systems and plug REAPER's output into the virtual source; and use pactl again to set the virtual source as the default input device.
It took a while to figure out the names of my different audio devices in pipewire, so know that pw-cli ls, pw-dump, and the pipewire patch bay software gpwgraph are your friends.
Source code
#!/usr/bin/env sh
source_name="DiscordInput"
mic_id=$(cat ~/.mic_id.txt)
channels=2
behringer="alsa_input.usb-BEHRINGER_UMC204HD_192k-00.Direct__Direct__source"
REAPER="REAPER" # yes this is stupid but if this changes for whatever reason I can change it in one place
speakers="FiiO K11"
mic="input.DiscordInput" # idk why the virtual source maps out this way
# echo "Setting up microphone..."
sleep 4 # This is mostly waiting out REAPER's autostart so that it doesn't produce a duplicate REAPER-1
# Confirm that REAPER is running
if pgrep -x "reaper" > /dev/null; then
# echo "REAPER is running. Moving to microphone configuration."
else
nohup reaper > /dev/null 2>&1 &
sleep 1
# echo "REAPER launching. Waiting before continuing."
sleep 4
fi
# Search for existing virtual source
search="$(pactl list modules short | grep "DiscordInput" | cut -c1-9)"
if [[ -n $search ]]; then
# echo "Existing virtual audio source found ($search). Deleting."
pactl unload-module $search
# echo "Existing virtual audio source deleted."
sleep 1
else
# echo "No existing virtual audio source detected. Creating."
sleep 1
fi
# Create virtual source, saving ID to text file
pactl load-module module-virtual-source source_name=$source_name channels=$channels > ~/.mic_id.txt
# echo "New virtual audio source $source_name created ($(cat ~/.mic_id.txt))"
sleep 2
# Disconnect Behringer interface from DiscordInput
pw-link -d "$behringer":capture_FL "$mic":input_FL
pw-link -d "$behringer":capture_FR "$mic":input_FR
sleep 1
# Disconnect REAPER from speaker output
pw-link -d "$REAPER":out1 "$speakers":playback_FL
pw-link -d "$REAPER":out2 "$speakers":playback_FR
sleep 1
# Connect REAPER to DiscordInput
pw-link "$REAPER":out1 "$mic":input_FL
pw-link "$REAPER":out2 "$mic":input_FR
sleep 1
# Set new source as default
pactl set-default-source output.$source_name
sleep 1
# echo "Set new virtual audio source as default."
If this was interesting or useful to you, my previous post was about my general migration process to EndeavourOS from Windows 11.
Previous |