Skip to content

Instantly share code, notes, and snippets.

@Ethorbit
Last active November 1, 2022 12:34
Show Gist options
  • Save Ethorbit/aa1d93370d7e82b4c1998b9d8bc258aa to your computer and use it in GitHub Desktop.
Save Ethorbit/aa1d93370d7e82b4c1998b9d8bc258aa to your computer and use it in GitHub Desktop.
Personal PulseAudio microphone script which also creates a loopback from host to VM guest, giving me great flexibility
#!/bin/bash
# Personal PulseAudio microphone toggle script
# Allows me to mute/unmute mic as well as send/stop sending microphone output to a virtual machine for
# maximum flexibility (e.g simultaneously using discord on linux, game voice chat on windows) and only needing to configure one mic ever
source_microphone="alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo" # Main microphone
source_we_wanna_send_to_vm="PulseEffects_mic.monitor" # This is PulseEffects mic output (since it improves the quality of the Main microphone)
sink_wired_to_vm_sound="alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo" # A soundcard that is quite literally wired to another soundcard which is passed in a Virtual Machine. Lmao. Hey, it works..
pid_file="/tmp/pa_mic_loopback.pid" # Where the last pactl module ID will be saved to.
# Arguments
enable_mic=0
force_mic=0
disable_mic=0
toggle_mic=0
is_mic_muted()
{
if [[ $(pactl get-source-mute "$source_microphone" | grep "Mute: yes") ]]; then
echo 1
else
echo 0
fi
}
while [ $# -gt 0 ]; do
case $1 in
--enable)
enable_mic=1
;;
--force)
force_mic=1
;;
--disable)
disable_mic=1
;;
--toggle)
toggle_mic=1
;;
--muted) # just prints whether or not mic is muted. Can be useful for GUI buttons and stuff.. \o/
is_mic_muted
exit
;;
esac
shift
done
unload_vm_loopback()
{
if [ -s "$pid_file" ]; then
pactl unload-module $(cat $pid_file)
fi
}
# My wacky setup uses 2 identical USB soundcards, which unfortunately means pulseaudio gets confused and we need to tell it to pick whatever is available on the host (not passed in a VM)
choose_vm_sink()
{
sound_cards=$(pactl list sinks short | grep "$sink_wired_to_vm_sound")
if [ "$force_mic" -ne 1 ] && [ $(echo "$sound_cards" | wc -l) -gt 1 ]; then
unload_vm_loopback
echo "More than 1 sound card is present. Is a VM running? Did you pass one to it?"
exit 1
fi
sink_wired_to_vm_sound=$(echo "$sound_cards" | awk 'NR==1 { print $2 }')
echo "Found soundcard wired to VM sink: $sink_wired_to_vm_sound"
}
load_vm_loopback()
{
choose_vm_sink
pactl load-module module-loopback source="$source_we_wanna_send_to_vm" sink="$sink_wired_to_vm_sound" source_dont_move="true" sink_dont_move="true" > "$pid_file"
}
mute_mic()
{
pactl set-source-mute "$source_microphone" 1
}
unmute_mic()
{
pactl set-source-mute "$source_microphone" 0
}
enable_mic()
{
unmute_mic
# so we don't accidentally start several identical loopback streams
unload_vm_loopback
load_vm_loopback
}
disable_mic()
{
unload_vm_loopback
mute_mic
}
if [[ "$enable_mic" -eq 0 && "$disable_mic" -eq 0 && "$toggle_mic" -eq 0 ]]; then
echo "You need to pass --enable, --disable, or --toggle"
exit 1
fi
if [[ "$enable_mic" -eq 1 && "$disable_mic" -eq 1 ]]; then
echo "You can only enable or disable, not both."
exit 1
fi
if [[ ! $(pidof pulseeffects) ]]; then
unload_module
echo "PulseEffects is not running."
exit 1
fi
if [ "$enable_mic" -eq 1 ]; then
enable_mic
fi
if [ "$disable_mic" -eq 1 ]; then
disable_mic
fi
if [ "$toggle_mic" -eq 1 ]; then
if [[ $(is_mic_muted) -eq 1 ]]; then
enable_mic
else
disable_mic
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment