Date: Sun, 17 Dec 2023 19:30:53 +0100 From: Florian Walpen <dev@submerge.ch> To: freebsd-multimedia@freebsd.org, Christos Margiolis <christos@freebsd.org> Cc: Joseph Mingrone <jrm@freebsdfoundation.org> Subject: Re: RFC - Work on FreeBSD's Audio Stack Message-ID: <7097536.Jf4ITVjuem@z800> In-Reply-To: <ndpvdfmo5irttibdbqim2hxovqvzy7tmetesfpl5pg7yb4nd4w@o6te4lajcn5k> References: <86ttomxg11.fsf@phe.ftfl.ca> <6705256.qJWK8QVVMX@x230> <ndpvdfmo5irttibdbqim2hxovqvzy7tmetesfpl5pg7yb4nd4w@o6te4lajcn5k>
next in thread | previous in thread | raw e-mail | index | archive | help
Hello Christos, On Saturday, December 16, 2023 5:06:12 PM CET Christos Margiolis wrote: >=20 > 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. >=20 > 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. No need to replace OSS right now, I just think we should keep that in mind= =20 when we decide where to put our efforts. And yes, sndio is a candidate, but= is=20 missing mmap() and passthrough support AFAIK. > > > snd uaudio(4) fixes > > >=20 > > > 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 sh= ort > > > 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 bypas= sed > > > if > > > audio is routed to the USB device through virtual oss, this is still a > > > bug > > > that needs to be addressed. > >=20 > > 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? >=20 > 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. Ok, maybe these players recklessly stop and restart playback when seeking i= n=20 the track, and virtual_oss wouldn't communicate that further to the underly= ing=20 dsp device. Doesn't explain to me why these players would read(2) at all... Anyway, this is better discussed in a bug report with proper logs. > > > oss(3) > >=20 > > 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? > >=20 > > Beware that there's a great variety of operation strategies for differe= nt > > 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 a= nd > > strives to keep latency reproducible within +/- 1ms. The backend code is > > here: > >=20 > > https://github.com/0EVSG/sosso >=20 > 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=C4=87 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. This is gonna be difficult to get right. Feel free to contact me when you'r= e=20 down to concrete design decisions, hopefully I can remember some of the=20 pitfalls I ran into. > > > Hot-swapping > >=20 > > What you outline here is a complete sound server, but it doesn't tell h= ow > > you want to implement that. Extend the vchan infrastructure, autostart > > virtual_oss on all PCM devices, or something else? > >=20 > > 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? >=20 > Not really. We currently change the default unit by either doing >=20 > $ mixer -d<new_unit> >=20 > Or > # sysctl hw.snd.default_unit=3D<new_unit> >=20 > 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. No objection, this use case is a lot less invasive than I thought. Make sur= e=20 to sync the selected default unit between your tool and virtual_oss. > > > Testing > > >=20 > > > The audio driver will be tested by writing a test program to go throu= gh > > > 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 can= not > > > pass values that would break the driver. Exact cases will be consider= ed > > > further down the project. > >=20 > > You mean IOCTLs provided by the dsp devices? On a dummy driver? Because > > the > > hardware drivers are usually well separated in kernel modules, which me= ans > > they can be tested separately. >=20 > 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? Depends on what you want to test. For IOCTLs (the dsp device) and the vchan= =20 feeder stuff you could load a dummy audio driver kernel module, where you c= an=20 check the outcome. If you want to test hardware drivers, I'm not sure they = can=20 be tested meaningfully without listening to sound output. =46or automated tests of your oss(3) library you could strip down virtual_o= ss,=20 catching the IOCTLs on its cuse(3) devices. It has no mmap() though. > > 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. >=20 > More details would be appreciated. :) What kqueue / kevent support means is probably clear? Currently poll() is t= he=20 only method an application can use to wait for the sound buffer to reach it= s=20 low water mark. The latency / OSS buffer fragment / blocksize stuff is one of the bigger=20 blunders I know in our audio stack, and one that can be fixed without=20 compromising OSS API compatibility too much. There's an abstract latency setting through SNDCTL_DSP_POLICY ioctl, the=20 hw.snd.latency_profile and hw.snd.latency sysctl. It translates to a certai= n=20 buffer and fragment size, at 48kHz 16bit stereo. Different ones for recordi= ng=20 and playback. These sizes are then scaled according to the actual sample ra= te=20 and frame size, and rounded to a power of two. Which can be already far off= =20 from the intended latency per fragment. These buffer and fragment sizes are then further processed, limited and rou= nded=20 (power of two) again. They end up as the fragment size of the internal buff= ers.=20 =46unny enough, the fragment size is almost meaningless, apart from definin= g the=20 default low water mark. Less funny that it is also communicated as blocksiz= e=20 to the driver, to set a certain latency. At this point it's a bit of a lott= ery=20 because the driver has its own rounding requirements (e.g. milliseconds), a= nd=20 it depends on whether recording or playback blocksize has the final say.=20 Because drivers typically need the same blocksize for recording and playbac= k. Some of the drivers have dedicated tunables to get predictable blocksizes.= =20 Yes, that's what hw.usb.uaudio.buffer_ms is for. So at least it would be nice to get a consistent latency hint at the driver= =20 level. The effective fragment size for the front side buffers should be set= =20 according to what the driver uses, not the other way round. Bonus points if we find a way to set the buffer size from an application,=20 without the obsessive power-of-two-rounding. =46or a first glance, have a look at chn_resizebuf() and chn_calclatency() = in sys/dev/sound/pcm/channel.c Hope this helps. =46lorian
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?7097536.Jf4ITVjuem>