helloSystem / ISO

helloSystem Live and installation ISO
https://github.com/helloSystem/
BSD 3-Clause "New" or "Revised" License
807 stars 58 forks source link

Automatically switch to last plugged in audio device w/o need for app restart #217

Open probonopd opened 3 years ago

probonopd commented 3 years ago

Automatically switch to last plugged in audio device w/o the need for app restart. Check out virtual_oss as suggested by d.ebdrup.

probonopd commented 3 years ago

Thanks for chiming in over at https://github.com/helloSystem/Utilities/issues/71 @mekanix. As you probably have already figured out we are trying to build an easy-to-use FreeBSD based desktop system, as part of which we are working on an easy (but sufficiently powerful) way for "mere mortals" a.k.a. non-technical users to configure audio.

Also, you might consider having virtual_oss by default

We are indeed considering to set up virtual_oss by default for helloSystem, this is what this ticket is about.

It seems that virtual_oss has quite a learning curve. We could definitely need a helping hand by someone who knows this stuff.

This is the GUI we currently have for selecting audio devices manually (to override the "last plugged in" one which gets automatically selected):

image

And this is to change the volume:

image

GUI-wise we don't want to make it much more complicated than that, but it would be nice if one could select different devices for playback and recording. Currently we are using "raw" OSS.

Do you think virtual_oss would be a good match?

mekanix commented 3 years ago
* Can `virtual_oss` be used to automatically switch to last plugged in audio device w/o need for app restart? E.g., I have the web browser open and am playing a YouTube video over HDMI, then I plug in a USB sound device, will it switch the sound _immediately_ to the newly plugged in device? (With stock OSS we have to restart the browser for the change to take effect.)

No. It has to be manual. I mean, maybe there can be something done with defs.rules or something, but virtual_oss alone can not do it.

* Can `virtual_oss` be set up in an operating-system wide way that is generic to different machines having different audio devices, and different numbers of audio devices? (E.g., HDMI via GPU PCI card, built-in motherboard sound, multiple USB sound devices etc.). The users of helloSystems are often non-technical and the least thing we want to require them doing is editing any configuration text files

Again, no, it has to be manual. I mean, it can not know what do you want. But maybe we can create some script/config to do it.

* Can `virtual_oss` be used to allow the user to select different devices for playback and recording?

For example: virtual_oss_cmd /dev/vdsp.ctl -f /dev/dsp1 will switch recording and playback device to /dev/dsp1. You can also use -P and -R options, too.

You might also want to check out virtual_oss_ctl -f /dev/vdsp.ctl. It is Qt based GUI which has some control over running virtual_oss.

probonopd commented 3 years ago

Again, no, it has to be manual. I mean, it can not know what do you want. But maybe we can create some script/config to do it.

What i mean is:

If helloSystem would use virtual_oss, would every user of helloSystem need to manually edit config files depending on how many and which audio devices the user has? Or can the system be configured in a generic "plug and play" way.

mekanix commented 3 years ago

When I say "it can not know what you want" I mean config for virtual_oss can be complex. For example, my mixer has 18ch, and virtual_oss "splits" it in two devices: one with 2 channels and one with 18. Also, virtual_oss can not know which sample rate and bit depth you want to use. If you could gather all that info somehow, running virtual_oss is not a problem (or reconfiguring it using virtual_oss_cmd).

probonopd commented 3 years ago

I am targeting "normal" users (as in: the guy who watches YouTube videos and hops on a Zoom call from time to time). Not professional audio studios with 18 channels (I'd assume those professionals know what they want and how to configure it).

If there was a way for me to have something like this

image

but for recording and playback separately it would already be an improvement over what we have now.

And if the change would take effect immediately rather than only after restarting the application which is playing the audio (e.g., web browser).

mekanix commented 3 years ago

I'm not sure what the question is precisely, so let me give you a possible scenario. Out of the box, there's no GUI to do what you're suggesting, but as virtual_oss exposes /dev/vdsp.ctl (and not just for vdsp), you can make an app that does the same as virtual_oss_cmd. You can even use the same code, just wrap it in GUI.

Effect of change is already immediate, so no problem there (I know switching it through sysctl hw.snd.default_unit requires app to reopen /dev/dsp, which usually means app has to be restarted).

If you decide to develop an app using .ctl files to connect to virtual_oss, you can also look at virtual_oss_ctl app as an example. Also, if you do decide to develop it, consider it being part of virtual_oss_ctl package. I mean, I would love to have such app in vanilla FreeBSD, for start.

mekanix commented 3 years ago

Sorry if this is wrong ticket to put this in, I don't know which is the proper one.

This file https://github.com/helloSystem/ISO/blob/experimental/overlays/uzip/furybsd-settings/files/etc/sysctl.conf

kern.timecounter.alloweddeviation=0
hw.usb.uaudio.buffer_ms=2
hw.snd.latency=0

This is for squeezing more real time out of FreeBSD while average user probably doesn't want that. First, kern.timecounter.alloweddeviation=0 will drain laptop battery a little bit more, hw.usb.uaudio.buffer_ms=2 is insanely low value for "just desktop" and default latency set with hw.snd.latency=0 is too low. For "normal" users I would leave those as default. Maybe comment it out with a comment "for users who want studio-grade latency" or something similar.

probonopd commented 3 years ago

Thanks @mekanix. I was hoping that these fixes would solve the following problem that has been plaguing me:

When I play a sound for the first time, the first ~200 ms or so are not playing. They are simply cut off. Very annoying. If I play the same sound repeatedly, it works (sometimes).

Do you know how to resolve that?

mekanix commented 3 years ago

I took some time to think about it and only thing that comes to my mind is app that is doing playback doing something funky. I know Hans likes VLC and I like mpv, so two of us test with those apps. Do they also miss first ~200ms? If yes, what's the setup? With or without virtual_oss (and if it's with, what options did you pass)? As you can see, at this point I need more info/questions than I have hypotheses on what could be wrong.

PS. Just the smallest nit ... comments of bitperfect has two '##' in a row. I know it's not important, but if you are obsessed with consistency like me ... :o)

probonopd commented 3 years ago

Do they also miss first ~200ms? If yes, what's the setup? With or without virtual_oss (and if it's with, what options did you pass)?

Without virtual_oss. USB sound "card" and sound over Nvidia HDMI. And yes, this is regardless of the player app. I noticed this for short sounds (e.g. "bing" notification sound) where it is especially noticeable.

PS. Just the smallest nit ... comments of bitperfect has two '##' in a row. I know it's not important, but if you are obsessed with consistency like me ... :o)

Great catch. Actually, that was intentional to show that this line had been commented out before already. With this line, I am extra unsure on whether it is wanted even in a "studio" setup.

mekanix commented 3 years ago

Great catch. Actually, that was intentional to show that this line had been commented out before already. With this line, I am extra unsure on whether it is wanted even in a "studio" setup.

That part really depends. For example, there are interfaces which have hardware resampler so it makes no sense for software to do resampling. What I'm trying to say is that it depends on the studio equipment.

mekanix commented 3 years ago

Regarding the first few ms of sound not playing: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=257082. Maybe it's the same problem.

mekanix commented 3 years ago

Previous bugzilla PR suggests sysctl machdep.idle=spin fixes the problem for them. Could you try the same?

probonopd commented 3 years ago

Hi @mekanix. Thanks for the hint but it does not solve the issue for me.

The first second(!) is missing. When I select one second of sound and click play, I hear nothing.

I have opened a separate ticket for this topic: https://github.com/helloSystem/ISO/issues/269