Skip site navigation (1)Skip section navigation (2)
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>