Switching audio devices on OpenBSD
Most of the time, I do not have to think about audio devices on
OpenBSD: They just work. But sometimes, I need more features, like
when I want to listen to music or other kinds of sound with a USB
headset. The good news is that my Sennheiser headset also just works,
but just plugging it in does not mean that sound comes out of it
instead of the laptop speakers.
In earlier versions of OpenBSD, I had to play with sndiod parameters
or set the AUDIODEVICE environment variable before starting the
programs that should output their sound to the headset. But on recent
versions (since 6.7, I think?), I can just use sndioctl to toggle my
output device.
This is not documented on the multimedia FAQ. I do not know if their
is a reason to prefer the old ways I just mentioned, so I give no
warranties of any kind if you do what I describe here. I just find
that it is both more comfortable and more versatile to use
sndioctl. For officially supported methods, please look at the FAQ.
Switching the output device via sndioctl(1)
You can simply call sndioctl (without needing root permissions) and it
will output all properties, which could look like this:
input.level=0.486 input.mute=0 output.level=0.714 output.mute=0 server.device=0 app/firefox0.level=1.000 app/mpg0.level=1.000
There are properties like *.level, which control the volume - both per
device and per individual application, if you want to do that. You can
also use sndioctl to mute or unmute audio input or output. But today,
we are here to talk about server.device, which points, in the example
output above, to the first audio device (rsnd/0).
If I plug my headset into my notebook, it would be a good guess to
assume that it might become the second audio device. Let's change our
output device to that via
sndioctl server.device=1
All sound currently playing and all sound that will be played from now
on should be output to my headset - it does not get any easier than
this!
Mono sound?
To be honest, I had a small problem at first: Only the left speaker on
my headset was working. What was that about?
Well, calling sndioctl again quickly pointed to the culprit:
input.level=0.188 input.mute=0 output[0].level=0.306 output[1].level=0.012 output.mute=0 server.device=1 app/firefox0.level=1.000 app/mpg0.level=1.000
I do not know why, but I had different volumes for both headset
speakers. This was quickly fixed with another call to sndioctl:
sndioctl output[1].level=0.306
After that, my sndioctl output was what I expected it to be in the
first place, and all audio could be heard with both ears.
input.level=0.188 input.mute=0 output.level=0.306 output.mute=0 server.device=1 app/firefox0.level=1.000 app/mpg0.level=1.000
Setting the server.device variable back to zero switches my audio back
to the internal speakers - and again, without any interrupts.
Also, should I ever desire to change the volume of one side of my
headset independently from the other side, I learned to just do so via
sndioctl output[1].level=0.1
I do not believe that I will ever need this, but you never know.