Re: RFC - Work on FreeBSD's Audio Stack

From: Christos Margiolis <christos_at_freebsd.org>
Date: Sat, 16 Dec 2023 16:06:12 UTC
Hello Florian,

Florian Walpen wrote:
> Let's be realistic here. The OSS API is a dead end in the middle to long term. 
> It's neither widely used nor particularly well suited for modern hardware. And 
> it's conceptually broken on many levels, including parameter negotiation, 
> consistency of parameters, buffer and latency management, error handling.
> 
> Fixes and usability improvements are a good thing. But we have to think about 
> what to replace the OSS API with and how much time we still want to invest 
> into the OSS ecosystem.

This is something I have been thinking about even before the proposal,
but replacing OSS with an existing sound system (sndio maybe?), or
rolling our own one, is probably too large of an endeavour, considering
the amount of infrastructure built around OSS.

That being said, I am also in favour of replacing OSS at some point, and
very much willing to work on this, but it might be wiser, for now, to
improve what we currently have and provide a better user-experience than
leave it as-is until we decide whether we'll get rid of OSS or not.

> > snd uaudio(4) fixes
> > 
> > The project will also address bugs in the USB audio driver, snd uaudio(4),
> > which I have been able to reproduce using my Focusrite Scarlett USB sound
> > card, with the most prominent and consistent one being noise produced
> > during the first 12 seconds of playback and when moving along a
> > track/video. If the user tries to move forward multiple times in a short
> > time window, the audio device most of the time becomes unusable (i.e no
> > audio) and it has to be replugged. Though this issue is largely bypassed if
> > audio is routed to the USB device through virtual oss, this is still a bug
> > that needs to be addressed.
> 
> From the description here this sounds more like an issue with the player or 
> the vchan feeders, given that virtual_oss doesn't produce noise. Did you file 
> a bug report?

I really doubt it's the player, as this happens with pretty much any
player (mpv, ncmpcpp, firefox, ...) I have tried. virtual_oss does
produce noise, but only when the device is opened.

> > Initially I am going to test whether the open() and read() routines cause
> > this issue, as DTrace suggests that this happens around the same time
> > open(2) or the first read(2) is called. As mentioned in the previous
> > paragraph, virtual oss partially fixes this issue, so I would like to
> > investigate and understand why, and maybe find the root cause that way.
> > Another source of information will be Linux’s Scarlett and USB audio
> > drivers which, as far as I know, do not have this issue.
> 
> Most problems I've seen are about bad vchan constellations. A good 
> troubleshooting checklist would be of great help for bug reports, something 
> along the lines of
> 
> # sysctl hw.snd.verbose=2
> # cat /dev/sndstat
> # ...
> 
> and some more user friendly output from /dev/sndstat etc.

Making the verbose output of /dev/sndstat less cryptic could be a nice
improvement, IMO.

> > oss(3)
> 
> What's the scope of this library? Main PCM devices, virtual PCM
> devices, hardware devices? Settings and state only, or also playback
> and recording operation?
>
> Beware that there's a great variety of operation strategies for different use 
> cases. With a simple poll() based read() / write() at one end of the spectrum, 
> and something like my new Jack OSS backend on the other end. It's timer based, 
> preferably mmap()ed, uses its own buffer management and strives to keep 
> latency reproducible within +/- 1ms. The backend code is here:
> 
> https://github.com/0EVSG/sosso

It's going to have both mmap'd and non-mmap'd buffer-management
(reading, writing, splitting, merging), as well as state setting. Goran
Mekić had brought up your library when we discussed this during
EuroBSDCon 2023, and I think oss(3) could re-use some of the ideas
implemented there, especially the low-latency mechanisms.

> > audio(8)
> > 
> > FreeBSD lacks an easy-to-use audio device handling utility similar to
> > mixer(8), but for the device-side of OSS, like OpenBSD’s audioctl(8). Such
> > a utility will make use of the new oss(3) library, and offer a cleaner and
> > user-friendlier interface, concentrating all useful - but scattered -
> > information currently provided by /dev/sndstat, hw.snd, dev.pcm and
> > hw.usb.uaudio, the OSS API into the output of a single application.
> 
> Many of the sysctls mentioned here are not dynamic and only apply on playback 
> / recording restart or device attach. That could limit this tool's usefulness.

I am aware of this, however, it's still useful to have "everything"
concertrated in one place. Sound settings on FreeBSD are really
scattered IMHO.

> For reference, this part of my Jack on FreeBSD notes should give you an 
> overview of knobs that are beneficial for music production:
> 
> https://github.com/0EVSG/freebsd_jack_notes#system-settings

Interesting, thank you.

> > Hot-swapping
> > 
> What you outline here is a complete sound server, but it doesn't tell how you 
> want to implement that. Extend the vchan infrastructure, autostart virtual_oss 
> on all PCM devices, or something else?
> 
> In many use cases this just duplicates the sound server that sits on top of 
> the dsp device. At worst it compromises quality and latency because of 
> conversions and routing buffers. As a provocative question, wouldn't the 
> average user be served better if we just implemented full pipewire support, 
> going forward?

Not really. We currently change the default unit by either doing
	
	$ mixer -d<new_unit>

Or
	# sysctl hw.snd.default_unit=<new_unit>

Which requires a track restart for the change to take effect. All that
would change with my proposed solution is simply detect if virtual_oss
is present, and in that case, change both the default unit through the
sysctl AND switch to the wanted unit through the virtual_oss IOCTL
interface so that the change takes effect immediately if we have
virtual_oss running.

> > Testing
> > 
> > The audio driver will be tested by writing a test program to go through most
> > of the IOCTLs provided to by the driver, to both confirm that the
> > information returned is correct, and also to make sure that users cannot
> > pass values that would break the driver. Exact cases will be considered
> > further down the project.
> 
> You mean IOCTLs provided by the dsp devices? On a dummy driver? Because the 
> hardware drivers are usually well separated in kernel modules, which means 
> they can be tested separately.

Honestly, I am still thinking about this, so I am not exactly sure yet.
Do you think there it's possible to create a reliable test case using a
virtual dummy device?

> Again, OSSv4 compatibility won't help much, it's basically abandoned by audio 
> software developers. Apart from open bug reports there's also missing kevent 
> support (instead of poll() being the only option), or the buffer / blocksize 
> based latency setting which is conceptually broken. I can give more details on 
> these topics if there's interest.

More details would be appreciated. :)

> Sorry to sound a bit negative here, but some of the objectives look rather 
> vague to me and I think another iteration of problem analysis and scope 
> definition would increase chances of success.

Feedback is always welcome! From what I understand, your main sentiment
is that you are against investing significant amounts of time getting
more in-sync with OSSv4, as there's not enough demand for it. I do not
really have any objection to this if you think there are more pressing
issues that could replace this goal, so I am open to suggestions!

Christos