# Switch between audio devices in real time



## jsInspector (Sep 24, 2019)

Hello.
The task is to switch between sound output devices in real-time (on the fly).
Only sndio and/or oss can be used.

To /boot/loader.conf already added:

```
snd_driver_load="YES"
sound_load="YES"
cuse_load="YES"
```

Switching with `sysctl hw.snd.default_unit` only works the next time you play a sound (it doesn’t work on the fly).
`# cat /dev/sndstat`

```
pcm0: <ATI R6xx (HDMI)> (play)
pcm1: <Analog Devices AD1882 (Analog)> (play/rec) default
pcm2: <Analog Devices AD1882 (Front Analog Headphones)> (play)
pcm3: <USB audio> (play/rec)
```
`# uname -a`

```
FreeBSD testInstall 12.0-RELEASE-p10 FreeBSD 12.0-RELEASE-p10 GENERIC  amd64
```


----------



## SirDice (Sep 24, 2019)

It's not supposed to work "on the fly". I'm not even sure if that's technically possible. While you can change the default output while the system is running, the application needs to re-open the device in order to pick up the change.

If you have an application writing to a file, you can remove/rename that file while this happens. The application would continue to write to the original file descriptor and needs to be restarted before it would pick up the file change.


----------



## shkhln (Sep 24, 2019)

https://forums.freebsd.org/threads/switching-dsp-devices-on-the-fly.69773/#post-419290


----------



## jsInspector (Sep 25, 2019)

SirDice said:


> It's not supposed to work "on the fly". I'm not even sure if that's technically possible. While you can change the default output while the system is running, the application needs to re-open the device in order to pick up the change.
> 
> If you have an application writing to a file, you can remove/rename that file while this happens. The application would continue to write to the original file descriptor and needs to be restarted before it would pick up the file change.





shkhln said:


> https://forums.freebsd.org/threads/switching-dsp-devices-on-the-fly.69773/#post-419290



I have already done this with `pulseaudio` on Arch Linux and there it's easy, only switching between `sinks` with `pactl`.
But BSD has many utils to work with sound and MIDI devises (`sndiod`, `aucat`, `aucatctl`, `midicat`,`virtual-oss`,`virtual_oss_ctl`). I am guessing that there, must be the way to archive this.


----------



## SirDice (Sep 25, 2019)

jsInspector said:


> I have already done this with  pulseaudio on Arch Linux and there it's easy


That's a software layer that sits in between the actual audio driver and a 'consumer' (i.e. audio application). It's this layer that does the actual switching, keeping the same connection to the consumer.


----------



## shkhln (Sep 25, 2019)

jsInspector said:


> I have already done this with `pulseaudio` on Arch Linux and there it's easy, only switching between `sinks` with `pactl`.
> But BSD has many utils to work with sound and MIDI devises (`sndiod`, `aucat`, `aucatctl`, `midicat`,`virtual-oss`,`virtual_oss_ctl`).



OSS is a relatively dumb sound system, with notable exception of the software mixer (which isn't a part of initial OSS design, by the way) you pretty much talk directly to the kernel driver. That is why there is no native MIDI or routing capabilities. Good latency, though 

That said, multiplexing and loopback devices would be a very appropriate addition to FreeBSD OSS, but so far nobody bothered to do it. virtual_oss is the closest thing in existence and even that program is relatively new (< 10 years old).



jsInspector said:


> I am guessing that there, must be the way to archive this.



Achieve what exactly?


----------



## jsInspector (Sep 25, 2019)

shkhln said:


> Achieve what exactly?



Achieve replicating what I can do with Pulseaudio on Linux using Sndio on FreeBSD instead.


----------



## SirDice (Sep 25, 2019)

Erh, maybe just installing audio/pulseaudio then?


----------



## JBR (Sep 25, 2019)

jsInspector said:


> Achieve replicating what I can do with Pulseaudio on Linux using Sndio on FreeBSD instead.





SirDice said:


> Erh, maybe just installing audio/pulseaudio then?



Wouldn't audio/sndio provide the same type of intermediate software layer (sound server) that audio/pulseaudio provides? Perhaps OP is looking to use something like `sndiod -f rsnd/0` or `sndiod -f rsnd/0 -s snd/0` as a toggle in a script...


----------



## jsInspector (Sep 26, 2019)

JBR said:


> Wouldn't audio/sndio provide the same type of intermediate software layer (sound server) that audio/pulseaudio provides? Perhaps OP is looking to use something like `sndiod -f rsnd/0` or `sndiod -f rsnd/0 -s snd/0` as a toggle in a script...



So I have already tried to create sub-device with sndio. But still don't understand how connect to them and in `cat /dev/sndstat` also can't see anything new. Maybe there must be some configuration in some file to to this.


----------



## SirDice (Sep 26, 2019)

The /dev/sndstat is part of the FreeBSD audio framework, sndio is a separate software layer that sits on top of that. It doesn't become part of the FreeBSD audio framework.


----------



## JBR (Sep 26, 2019)

jsInspector said:


> Maybe there must be some configuration in some file to to this.



The man page sndio() states device files are at /dev/audioN. I wonder if this is accurate for FreeBSD.

There's *no* config file listed in pkg-plist at audio/sndio.


----------



## jsInspector (Sep 26, 2019)

JBR said:


> The man page sndio() states device files are at /dev/audioN. I wonder if this is accurate for FreeBSD.
> 
> There's *no* config file listed in pkg-plist at audio/sndio.




```
# ls -l /dev/audio*
ls: /dev/audio*: No such file or directory
```


----------



## jsInspector (Oct 1, 2019)

Developer sndio *Alexandre Ratchov* _alex@caoua.org_.

Replied that the ability to quickly switch sound devices is missing in sndio, only the fallback option.



> Hi,
> 
> There's no utility to switch between devices, sorry.
> 
> ...



The question is closed, hello pulseaudio.


----------



## joplass (Oct 6, 2019)

I am not even sure if pulseaudio works the same way on Freebsd as in Linux.  Pavucontrol on Linux can switch on the fly.  So far I like OSS but I am very tempted to hit the ground with pulseaudio because of HDMI connection to the entertainment receiver.


----------



## jsInspector (Oct 6, 2019)

joplass said:


> I am not even sure if pulseaudio works the same way on Freebsd as in Linux. Pavucontrol on Linux can switch on the fly. So far I like OSS but I am very tempted to hit the ground with pulseaudio because of HDMI connection to the entertainment receiver.


With `pulseaudio` it's easy, there special command for this `pactl move-sink-inputs`, `sink-input` become when some app what to make sound. But unfortunately `OSS` doesn't give information to `pulseaudio` about sound cards and when I want connect new device (for example usb headset), I must relaunch `pulseaudio`, because it using `udev` to detect new devices.


----------



## jsInspector (Oct 18, 2019)

So, there some way to archive switching with `virtual_oss`.
I started with creating link to physical device `/dev/dsp2.0`
`virtual_oss -T /dev/sndstat -b 16 -c 2 -r 48000 -s 1024 -d dsp.first -O /dev/dsp2.0 -R /dev/null -t dsp.first.ctl &`
Than creating second virtual device attached to first virtual one.
`virtual_oss -T /dev/sndstat -b 16 -c 2 -r 48000 -s 1024 -d dsp.second -O /dev/dsp.first -R /dev/null -t dsp.second.ctl &`
And than I trying to play for example music `mpg123 -a /dev/dsp.second some.mp3`.
Next step is to relaunch first `virtual_oss` with different `-O /dev/dsp*` option, but it cause pause in playing about 2 seconds.
And also I can't make `virtual_oss` device as default with `sysctl hw.snd.default_unit`.


----------



## JBR (Oct 18, 2019)

jsInspector said:


> virtual_oss -T /dev/sndstat -b 16 -c 2 -r 48000 -s 1024 -d dsp.first -O /dev/dsp2.0 -R /dev/null -t dsp.first.ctl &



What is the use case for `-O` here, instead of `-P`?


----------

