Split output on sound card (PulseAudio)
I have a surround sound card in my system, currently an old Soundblaster Live connected over PCI. It has 3 line outputs, and 1 input.
By default, if set to Stereo Duplex in PulseAudio, it only uses the main audio output, the green front headphone/line output.
I wanted to be able to plug in both my headphones and speakers in separately, without having to use a splitter that adds extra noise.
Solution 1: Just set the configuration in PulseAudio to 4.0 Surround + Stereo Input. This will enable 4 channel sound, so it will use the green front output for the front 2 channels, and the black rear speaker out for the rear 2 channels. PulseAudio will detect the incoming stream as Stereo, and upmix it to all 4 channels. Then plugging in your headphones to the front output (still on the back of your computer on the sound card, it's just labelled the front output, it's the green one), and the speakers into the rear output (again, in the sound card, it's the black one usually) you can get sound from both of them.
Now, while this works, all programs get upmixed to both outputs. You do get control over volume by setting the output channels separately in either PulseAudio, or preferrably in alsamixer.
We can do better. An option is to make 2 dummy outputs, say called "Headphones" and "Speakers" that programs can output to in pulse, and then map those 2 virtual sinks into the front and rear channels of the 4.0 output.
First, get the alsqa name for your sound card. It's the one labelled alsa_output.pci-0000 so on in my example below. You can get it by just looking at the PulseAudio sink list.
pactl list sinks
Right under the sink number, it will be the one labelled "Name:". Copy this value, to add to PulseAudio configuration.
sudo vim /etc/pulse/default.pa
And add the 2 following lines in the bottom of the file, based on your configuration. You can also do this with pactl load-module module-remap-sink to test it. Adding it do default.pa will run it each time PulseAudio starts.
### Split sound card load-module module-remap-sink sink_name=speakers sink_properties="device.description='Speakers'" remix=no master=alsa_output.pci-0000_09_03.0.analog-surround-40 channels=2 master_channel_map=front-left,front-right channel_map=front-left,front-right load-module module-remap-sink sink_name=headphones sink_properties="device.description='Headphones'" remix=no master=alsa_output.pci-0000_09_03.0.analog-surround-40 channels=2 master_channel_map=rear-left,rear-right channel_map=front-left,front-right
This will create 2 sinks called speakers and headphones (the name is internal, it doesn't matter, the description is what you see). We then disable remixing, and give it the sound card as the output. We want each output to send 2 channels to the sound card, in this case, we want to map the front-left and front-right from our speakers virtual sink to the front-left and front-right on the sound card.
Similarly, we want to map the front-right and front-left of our headphones virtual sink (the virtual sinks are only 2 channels as mentioned) to the rear-left and rear-right on the sound card, which corresponds to the 2nd output on the card as decribed earlier. master_channel_map is the sound card output, channel_map is the virtual sink output.
Make sure you change the sound card name for your card!
You can do the same think with a 3rd virtual sink to set the card in 5.1 mode and use the 3rd output if you need to as well.
Now, when you open pavucontrol, just set programs to use the "Headphones" or "Speakers" sink to correspond to that output. This basically makes your sound card behave as 2 outputs. If you want a program to play on both speakers and headphones, send it to the sound card sink instead of the virtual sinks. By using 2 new sinks, we also get independant volume control over both (though both are capped by the volume on the main sound card sink).
By the way, this same thing can work backwards. You can create a 7.1 surround sound virtual sink (8 channels), and map the individual channel to MULTIPLE sound cards. In this case, your master will be the sound card you want to send those 2 channels, then set the master map to front-left and front-right of the card, and channel map to the channel from the virtual sink to map, eg side-left and side-right.
This really makes me miss how simple it was to reroute audio in JACK... I guess this will have to do with PulseAudio for now.
If you're recording something and want to be able to hear something, then you can load the pulseaudio loopback module.
To load the module and start loopback:
pactl load-module module-loopback latency_msec=1
To unload and stop playback:
pactl unload-module module-loopback
If it's looping the wrong device, you can change it using the 'pavucontrol' program.
Microphone noise reduction
You can use the echo-cancel module to some success. RMNoise from XiphMont is better
pactl load-module module-echo-cancel
Pipewire is great. Instead of all the above, you can use either any PulseAudio or Jack method for both splitting outputs and microphone loopback.
To split the output, just use Pipewire's "Pro Audio" mode. This will let you send a different stream to all the outputs individually.
Instead of using Pavucontrol to map and manage the outputs, you can use a Jack controller, which can more easily route any output to any input.
An example of this is to use QJackControl with Pipewire Jack instead of Jack2
From there, you can map any program to output or input. It's so much more flexible then Pulseaudio if you want to run filters and whatnot, or you have a DAW like Ardour that you want to map multiple inputs and outputs to. For example, if you have an audio interface with 4 inputs, you can map it to record 4 tracks simultaneously in Ardour (or more or less, depending on what you want to accomplish).
Microphone loopback is also a lot easier, just connect the input device directly to the output device in Jack, and you'll get monitoring with less latency then Pulseaudio.
Now, you do pay with extra CPU cycles and memory usage, and I still find the audio starts glitching sporadically if I run both pulse and jack applications at the same time with different sampling rates, but it's neat.
Oh, also Bluetooth is buggier - as in, sometimes it just doesn't send the audio even though it's selected as an output when first turning on, and you need to mess with settings.
Seriously though, give it a try!