Auto-switching PulseAudio profiles based on input(s) channel count

audiohdmipulseaudio

I'm running audio over HDMI to my receiver, which has a full 7.1 setup connected to it. However, most of the stuff that I listen to has far fewer channels—some is mono, most is stereo, a bit is 5.1. When the receiver is fed with the right number of channels, it has various DSP effects which work fairly well (e.g. in splitting out a center channel, in sending base to the subwoofer, auto-detecting Dolby matrix surround, etc.). This ceases working if you send it a full 7.1 signal with a bunch of silent channels.

The number of output channels in PulseAudio is configured, per-card/sink, by the profile assigned to the card. You can change the assigned profile with pacmd, pactl, and various GUI programs.

How can I set it up to automatically change the profile based on the channel usage in the input stream(s)? E.g., if the input streams are only using front-left and front-right, switch to the stereo profile. If they're using back-left and back-right as well, switch to quadrophonic, etc.

Best Answer

This is just a concept and no complete solution:

You may be able to do your own handling of events with patcl subscribe if you can assign configurations to pulsaudio clients (e.g., if the movie player connects, you switch to 7.1 configuration, otherwise you use the stereo configuratioin). You will get a constant stream of events from patcl subscribe, which you can handle by observing client connections. Then you can just call pactl/pacmd to change the profile.

Example output of pactl subscribe:

$ pactl subscribe 
Event 'change' on sink #0
Event 'remove' on sink-input #93
Event 'change' on sink #0
Event 'change' on source #0
Event 'change' on sink #0
Event 'change' on source #0
Event 'new' on sink-input #98
Event 'change' on sink-input #98

Please note, that you still have the problem to handle cases in which you have multiple clients with a different number of channels.

Furthermore, the above approach is rather limited. The per application settings are not sufficient to detect the real number of used channels of the application (e.g. vlc might play a 5.1 or 7.1 video). I have not found a way to get the number actually used channels of an pulseaudio client over pactl, but I might have missed some options here. Alternatively, you might be also able to hook into the video player application itself and get the missing bits form there.

Related Question