Update manpages respond to isaki-audio2 branch.

This commit is contained in:
isaki 2019-05-08 14:25:38 +00:00
parent 9beb52efed
commit b040836639
6 changed files with 341 additions and 649 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.2272 2019/04/27 23:04:31 kamil Exp $
# $NetBSD: mi,v 1.2273 2019/05/08 14:25:38 isaki Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
./etc/mtree/set.comp comp-sys-root
@ -10654,7 +10654,7 @@
./usr/share/man/cat9/arpresolve.0 comp-sys-catman .cat
./usr/share/man/cat9/atop.0 comp-sys-catman .cat
./usr/share/man/cat9/audio.0 comp-sys-catman .cat
./usr/share/man/cat9/audio_system.0 comp-sys-catman .cat
./usr/share/man/cat9/audio_system.0 comp-sys-catman obsolete
./usr/share/man/cat9/autoconf.0 comp-sys-catman .cat
./usr/share/man/cat9/bawrite.0 comp-sys-catman .cat
./usr/share/man/cat9/bcdtobin.0 comp-sys-catman .cat
@ -18591,7 +18591,7 @@
./usr/share/man/html9/arpresolve.html comp-sys-htmlman html
./usr/share/man/html9/atop.html comp-sys-htmlman html
./usr/share/man/html9/audio.html comp-sys-htmlman html
./usr/share/man/html9/audio_system.html comp-sys-htmlman html
./usr/share/man/html9/audio_system.html comp-sys-htmlman obsolete
./usr/share/man/html9/autoconf.html comp-sys-htmlman html
./usr/share/man/html9/bawrite.html comp-sys-htmlman html
./usr/share/man/html9/bcdtobin.html comp-sys-htmlman html
@ -26631,7 +26631,7 @@
./usr/share/man/man9/arpresolve.9 comp-sys-man .man
./usr/share/man/man9/atop.9 comp-sys-man .man
./usr/share/man/man9/audio.9 comp-sys-man .man
./usr/share/man/man9/audio_system.9 comp-sys-man .man
./usr/share/man/man9/audio_system.9 comp-sys-man obsolete
./usr/share/man/man9/autoconf.9 comp-sys-man .man
./usr/share/man/man9/bawrite.9 comp-sys-man .man
./usr/share/man/man9/bcdtobin.9 comp-sys-man .man

View File

@ -1,4 +1,4 @@
.\" $NetBSD: audio.4,v 1.87 2019/02/16 06:50:14 isaki Exp $
.\" $NetBSD: audio.4,v 1.88 2019/05/08 14:25:39 isaki Exp $
.\"
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -66,137 +66,40 @@ accepts the same
operations as
.Pa /dev/sound ,
but no other operations.
It can be opened at any time and can be used to manipulate the
audio device while it is in use.
.Pp
.Pa /dev/sound
and
.Pa /dev/audio
can be opened at
.Em any
time and audio sources of different precision and playback
parameters i.e frequency will be mixed and played back simultaneously.
.Pp
.Pa /dev/audioctl
can be used to manipulate the audio device
while it is in use.
.Sh SAMPLING DEVICES
When
.Pa /dev/audio
is opened, it automatically directs the underlying driver to manipulate
monaural 8-bit mu-law samples.
In addition, if it is opened read-only
(write-only) the device is set to half-duplex record (play) mode with
recording (playing) unpaused and playing (recording) paused.
is opened, it automatically sets the track to manipulate
monaural 8-bit mu-law 8000Hz.
When
.Pa /dev/sound
is opened, it maintains the previous audio sample mode and
record/playback mode most recently set on
.Pa /dev/sound
by any open channel.
is opened, it maintains the audio format and pause/unpause
state of the most recently opened track.
In all other respects
.Pa /dev/audio
and
.Pa /dev/sound
are identical.
.Sh VIRTUAL CHANNELS
Any process may open a sampling device at a given time.
Any number of devices per process and file descriptors may be shared between
processes.
.Pp
Virtual channels are converted to a common format, signed linear encoding,
frequency channels and precision.
These can be modified to taste by the following
.Xr sysctl 8
variables:
.Bl -tag -width "hw.driverN.precision" -compact -offset indent
.It Li hw. Ns Ar driverN Ns Li .precision
.It Li hw. Ns Ar driverN Ns Li .frequency
.It Li hw. Ns Ar driverN Ns Li .channels
.It Li hw. Ns Ar driverN Ns Li .latency
.It Li hw. Ns Ar driverN Ns Li .multiuser
.El
.Pp
Where
.Ar driverN
corresponds to the underlying audio device driver and device number.
E.g. in the case of an
.\" XXX: there's no hdafg(4) to xref to
.Xr hdaudio 4
supported device the variables would be:
.Li hw.hdafg0.channels ,
.Li hw.hdafg0.precision ,
.Li hw.hdafg0.frequency .
.Pp
For best results, values close to the underlying hardware should be chosen.
These variables may only be changed when the sampling device is not in use.
.Pp
The
.Li hw. Ns Ar driverN Ns Li .latency
.Xr sysctl 8
variable controls the latency of the in-kernel mixer by varying the hardware
blocksize.
It accepts a value in milliseconds(ms), fractional values are not allowed.
A value of zero will default to 150ms.
.Pp
If a static blocksize is enforced by the underlying hardware driver this value
cannot be changed.
.Pp
For audio applications that do not specify a preferred blocksize when configuring
the audio device, this will be the latency these applications have.
.Pp
For audio applications that
.Xr mmap 2
the audio device for play back the resultant latency is a third (1/3) of the value
of the
.Li hw. Ns Ar driverN Ns Li .latency
variable.
.Pp
The
.Li hw. Ns Ar driverN Ns Li .multiuser
.Xr sysctl 8
variable determines if multiple users are allowed to access the sampling
device.
.Pp
By default it is set to false.
This means that the sampling device may be only used by
.Em one
user at a time.
Other users (except root) attempting to open the sampling device will be
denied.
.Pp
If set to true, all users may access the sampling device at any time.
.Pp
Each virtual channel has a corresponding mixer:
.Bl -tag -width "vchan.dacN" -compact -offset indent
.It Li vchan.dac Ns Ar N
Output volume
.It Li vchan.mic Ns Ar N
Recording volume
.El
.Pp
Where
.Ar N
is the virtual channel number.
E.g.\&
.Li vchan.dac0
controlling playback volume and
.Li vchan.mic0
controlling recording volume for the first virtual channel.
.Pp
On a half-duplex device, writes while recording is in progress will be
immediately discarded.
Similarly, reads while playback is in progress
will be filled with silence but delayed to return at the current
sampling rate.
If both playback and recording are requested on a half-duplex
device, playback mode takes precedence and recordings will get silence.
.Pp
On a full-duplex device, reads and writes may operate
concurrently without interference.
On a full-duplex device, reads and writes may operate concurrently
without interference.
If a full-duplex capable audio device is opened for both reading and writing
it will start in half-duplex play mode; full-duplex mode has to be set
explicitly.
it will start in play mode but not start in record mode.
.Pp
On either type of device, if the playback mode is paused then silence is
On a half-duplex device, if there are any recording descriptors already,
opening with write mode will fail.
Similarly, if there are any playback descriptors already,
opening with read mode will fail.
If both playback and recording are requested on a half-duplex device,
it will be treated as playback mode.
.Pp
On either type of device, opening with write mode will start in playback mode,
opening with read mode will start in recording mode.
.Pp
If the playback mode is paused then silence is
played instead of the provided samples, and if recording is paused then
the process blocks in
.Xr read 2
@ -206,46 +109,55 @@ If a writing process does not call
.Xr write 2
frequently enough to provide samples at the pace the hardware
consumes them silence is inserted.
If the
.Dv AUMODE_PLAY_ALL
mode is not set the writing process must
provide enough data via
subsequent write calls to
.Dq catch up
in time to the current audio
block before any more process-provided samples will be played.
If a reading process does not call
.Xr read 2
frequently enough, it will simply miss samples.
.Pp
The audio driver supports track multiplexing.
All sampling devices can be opened at any time without interference.
For playback, all tracks opened simultaneously are mixed,
even if thier specified format is different.
For recording, recorded data is distributed to all opened tracks,
even if thier specified format is different.
To achieve this, the audio driver has an small efficient encoding converter,
a channel mixer, and a frequency conveter.
The frequency conversion adapts the simplest way
(interpolation method for upward, and simple thinning method for downward)
due to restriction in kernel resources and processing time.
It will work well in most case but don't expect excessively for its quality.
.Pp
The audio device is normally accessed with
.Xr read 2
or
.Xr write 2
calls, but it can also be mapped into user memory with
.Xr mmap 2
.Xr mmap 2 .
Once the device has been mapped it can no longer be accessed
by read or write; all access is by reading and writing to
the mapped memory.
The device appears as a block of memory
of size
The mmap'ped buffer appears as a block of memory of size
.Va buffersize
(as available via
.Dv AUDIO_GETINFO
or
.Dv AUDIO_GETBUFINFO ) .
The device driver will continuously move data from this buffer
from/to the audio hardware, wrapping around at the end of the buffer.
The audio driver will continuously move data from this buffer
from/to the mixing buffer, wrapping around at the end of the buffer.
To find out where the hardware is currently accessing data in the buffer the
.Dv AUDIO_GETIOFFS
and
.Dv AUDIO_GETOOFFS
calls can be used.
The playing and recording buffers are distinct and must be
mapped separately if both are to be used.
Only encodings that are not emulated (i.e. where
Note that
.Xr mmap 2
no longer maps hardware buffer directly.
Now it is achieved by emulation so don't expect any improvements excessively
rather than normal
.Xr write 2 .
For historical reasons, only encodings that are not set
.Dv AUDIO_ENCODINGFLAG_EMULATED
is not set) work properly for a mapped device.
is able to
.Xr mmap 2 .
.Pp
The audio device, like most devices, can be used in
.Xr select 2 ,
@ -262,26 +174,23 @@ The following
.Xr ioctl 2
commands are supported on the sample devices:
.Bl -tag -width indent
.It Dv AUDIO_GETCHAN (int)
This command will return the audio channel in use.
.It Dv AUDIO_SETCHAN (int)
This command will select the audio channel for subsequent ioctl calls.
.It Dv AUDIO_FLUSH
This command stops all playback and recording, clears all queued
buffers, resets error counters, and restarts recording and playback as
buffers, resets error counters on this track,
and restarts recording and playback as
appropriate for the current sampling mode.
.It Dv AUDIO_PERROR (int)
.It Dv AUDIO_RERROR (int)
This command fetches the count of dropped output (input)
samples into its integer argument.
bytes into its integer argument.
There is no information regarding when in the sample stream
they were dropped.
.It Dv AUDIO_WSEEK (u_long)
This command fetches the count of samples that are queued ahead of the
This command fetches the count of bytes that are queued ahead of the
first sample in the most recent sample block written into its integer argument.
.It Dv AUDIO_DRAIN
This command suspends the calling process until all queued playback
samples have been played by the hardware.
samples have been played.
.It Dv AUDIO_GETDEV (audio_device_t)
This command fetches the current hardware device information into the
.Vt audio_device_t
@ -296,6 +205,8 @@ typedef struct audio_device {
.It Dv AUDIO_GETENC (audio_encoding_t)
This command is used iteratively to fetch sample encoding names and
format ids into the input/output audio_encoding_t argument.
The encoding returned by the command is user accessible encoding and
is not hardware supported encoding.
.Bd -literal
typedef struct audio_encoding {
int index; /* input: nth encoding */
@ -312,13 +223,9 @@ all the supported encodings, start with an index field of 0 and
continue with successive encodings (1, 2, ...) until the command returns
an error.
.It Dv AUDIO_GETFD (int)
The command returns the current setting of the full duplex mode.
This command is obsoleted.
.It Dv AUDIO_SETFD (int)
This command sets the device into full-duplex operation if its integer
argument has a non-zero value, or into half-duplex operation if it
contains a zero value.
If the device does not support full-duplex
operation, attempting to set full-duplex mode returns an error.
This command is obsoleted.
.It Dv AUDIO_GETPROPS (int)
This command gets a bit set of hardware properties.
If the hardware
@ -342,7 +249,7 @@ the device is capable of audio capture.
.It Dv AUDIO_GETIOFFS (audio_offset_t)
.It Dv AUDIO_GETOOFFS (audio_offset_t)
This command fetches the current offset in the input(output) buffer where
the audio hardware's DMA engine will be putting(getting) data.
the track mixer will be putting(getting) data.
It mostly useful when the device
buffer is available in user space via the
.Xr mmap 2
@ -361,20 +268,22 @@ typedef struct audio_offset {
.It Dv AUDIO_GETBUFINFO (audio_info_t)
.It Dv AUDIO_SETINFO (audio_info_t)
Get or set audio information as encoded in the audio_info structure.
For historical reasons, the audio_info structure has three different
layer's parameters: track, track mixer and hardware rich mixer.
.Bd -literal
typedef struct audio_info {
struct audio_prinfo play; /* info for play (output) side */
struct audio_prinfo record; /* info for record (input) side */
u_int monitor_gain; /* input to output mix */
u_int monitor_gain; /* input to output mix [HWmixer] */
/* BSD extensions */
u_int blocksize; /* H/W read/write block size */
u_int hiwat; /* output high water mark */
u_int lowat; /* output low water mark */
u_int blocksize; /* read/write block size [track] */
u_int hiwat; /* output high water mark [track] */
u_int lowat; /* output low water mark [track] */
u_int _ispare1;
u_int mode; /* current device mode */
u_int mode; /* current operation mode [track] */
#define AUMODE_PLAY 0x01
#define AUMODE_RECORD 0x02
#define AUMODE_PLAY_ALL 0x04 /* do not do real-time correction */
#define AUMODE_PLAY_ALL 0x04 /* Not used anymore */
} audio_info_t;
.Ed
.Pp
@ -392,13 +301,14 @@ first.
.Pp
The
.Va mode
field should be set to
.Dv AUMODE_PLAY ,
.Dv AUMODE_RECORD ,
.Dv AUMODE_PLAY_ALL ,
or a bitwise OR combination of the three.
Only full-duplex audio devices support
simultaneous record and playback.
field indicates current operation mode, either one of
.Dv AUMODE_PLAY
or
.Dv AUMODE_RECORD .
These two flags can not be changed once this descriptor is opened.
On playback mode, obsoleted
.Dv AUMODE_PLAY_ALL
can be set but has no effect.
.Pp
.Va hiwat
and
@ -423,41 +333,40 @@ sets the current audio blocksize.
The generic audio driver layer and the hardware driver have the
opportunity to adjust this block size to get it within
implementation-required limits.
Upon return from an
.Dv AUDIO_SETINFO
call, the actual blocksize set is returned in this field.
Normally the
.Va blocksize
is calculated to correspond to 50ms of sound and it is recalculated
when the encoding parameter changes, but if the
is calculated to correspond to 40ms
(For some hardware, this value may be different due to
the hardware restrictions)
of sound and it is recalculated
when the encoding parameter changes.
If the descriptor is opened for read only,
.Va blocksize
is set explicitly this value becomes sticky, i.e. it remains
even when the encoding is changed.
The stickiness can be cleared by reopening the device or setting the
indicates the blocksize on recording track.
Otherwise,
.Va blocksize
to 0.
indicates the blocksize on playback track.
.Bd -literal
struct audio_prinfo {
u_int sample_rate; /* sample rate in samples/s */
u_int channels; /* number of channels, usually 1 or 2 */
u_int precision; /* number of bits/sample */
u_int encoding; /* data encoding (AUDIO_ENCODING_* below) */
u_int gain; /* volume level */
u_int port; /* selected I/O port */
u_long seek; /* BSD extension */
u_int avail_ports; /* available I/O ports */
u_int buffer_size; /* total size audio buffer */
u_int sample_rate; /* sample rate in samples/s [track] */
u_int channels; /* number of channels, usually 1 or 2 [track] */
u_int precision; /* number of bits/sample [track] */
u_int encoding; /* data encoding (AUDIO_ENCODING_* below) [track] */
u_int gain; /* volume level [HWmixer] */
u_int port; /* selected I/O port [HWmixer] */
u_long seek; /* BSD extension [track] */
u_int avail_ports; /* available I/O ports [HWmixer] */
u_int buffer_size; /* total size audio buffer [track] */
u_int _ispare[1];
/* Current state of device: */
u_int samples; /* number of samples */
u_int eof; /* End Of File (zero-size writes) counter */
u_char pause; /* non-zero if paused, zero to resume */
u_char error; /* non-zero if underflow/overflow occurred */
u_char waiting; /* non-zero if another process hangs in open */
u_char balance; /* stereo channel balance */
u_int samples; /* number of samples [track] */
u_int eof; /* End Of File (zero-size writes) counter [track] */
u_char pause; /* non-zero if paused, zero to resume [track] */
u_char error; /* non-zero if underflow/overflow occurred [track] */
u_char waiting; /* non-zero if another process hangs in open [track] */
u_char balance; /* stereo channel balance [HWmixer] */
u_char cspare[2];
u_char open; /* non-zero if currently open */
u_char active; /* non-zero if I/O is currently active */
u_char open; /* non-zero if currently open [trackmixer] */
u_char active; /* non-zero if I/O is currently active [trackmixer] */
};
.Ed
.Pp
@ -494,6 +403,13 @@ unsigned linear encoding with big endian byte order
Dolby Digital AC3
.El
.Pp
Regardless of format supported by underlying driver,
audio driver accepts following formats.
encoding and precision is one of those obtained by
.Dv AUDIO_GETENC .
channels ranges from 1 to 12.
frequency ranges from 1000Hz to 192000Hz.
.Pp
The
.Va gain ,
.Va port
@ -556,7 +472,7 @@ and
.Dv AUDIO_GETBUFINFO .
.Va seek
represents the count of
samples pending;
bytes pending;
.Va samples
represents the total number of bytes recorded or played, less those
that were dropped due to inadequate consumption/production rates.
@ -567,6 +483,54 @@ For
.Dv AUDIO_SETINFO ,
if the pause value is specified it will either pause
or unpause the particular direction.
.It Dv AUDIO_QUERYFORMAT (audio_format_query_t)
This command enumerates formats supported by the hardware.
Similarly to
.Dv AUDIO_GETENC ,
to query all the supported formats,
start with an index field of 0 and continue with successive formats
(1, 2, ...) until the command returns an error.
.Bd -literal
typedef struct audio_format_query {
u_int index;
struct audio_format fmt;
} audio_format_query_t;
.Ed
.It Dv AUDIO_GETFORMAT (audio_info_t)
This command fetches the current hardware format.
Only following members in audio_info_t are used.
Members which is not listed here or belong in invalid direction are
filled by -1.
.\" XXX I want something like <ul> on HTML...
.Bd -literal
mode
play.encoding
play.precision
play.channels
play.sample_rate
record.encoding
record.precision
record.channels
record.sample_rate
.Ed
.Pp
.Va mode
indicates which direction is valid.
.It Dv AUDIO_SETFORMAT (audio_info_t)
This command sets the hardware format.
It will fail if there are any opened descriptors.
So obviously, it must be issued on
.Pa /dev/audioctl .
Similarly to
.Dv AUDIO_GETFORMAT ,
only above members in audio_info_t are used.
Members which is not listed or belong in invalid direction are ignored.
The parameters can be chosen from the choices obtained by
.Dv AUDIO_QUERYFORMAT .
.It Dv AUDIO_GETCHAN (int)
This command is obsoleted.
.It Dv AUDIO_SETCHAN (int)
This command is obsoleted.
.El
.Sh MIXER DEVICE
The mixer device,
@ -773,13 +737,13 @@ string values.
.It Pa /dev/mixer
.El
.Sh SEE ALSO
.Xr audiocfg 1 ,
.Xr audioctl 1 ,
.Xr mixerctl 1 ,
.Xr ioctl 2 ,
.Xr ossaudio 3 ,
.Xr midi 4 ,
.Xr radio 4 ,
.Xr sysctl 8
.Ss ISA bus
.Xr aria 4 ,
.Xr ess 4 ,
@ -812,8 +776,10 @@ string values.
.Xr bba 4
.Ss USB
.Xr uaudio 4
.Ss The NetBSD audio specification
.Xr audio_system 9
.Sh HISTORY
Support for virtual channels and mixing first appeared in
.Nx 8.0 .
.Sh BUGS
If the device is used in
.Xr mmap 2
it is currently always mapped for writing (playing) due to VM system weirdness.

View File

@ -1,9 +1,9 @@
# $NetBSD: Makefile,v 1.436 2019/04/06 03:06:24 thorpej Exp $
# $NetBSD: Makefile,v 1.437 2019/05/08 14:25:39 isaki Exp $
# Makefile for section 9 (kernel function and variable) manual pages.
MAN= accept_filter.9 accf_data.9 accf_http.9 \
altq.9 arp.9 audio.9 audio_system.9 autoconf.9 \
altq.9 arp.9 audio.9 autoconf.9 \
bcdtobin.9 bcmp.9 bcopy.9 bintime_add.9 bluetooth.9 boothowto.9 bpf.9 \
buffercache.9 bufferio.9 bufq.9 bus_dma.9 bus_space.9 byteorder.9 \
bzero.9 \

View File

@ -1,4 +1,4 @@
.\" $NetBSD: audio.9,v 1.51 2019/02/16 07:00:56 wiz Exp $
.\" $NetBSD: audio.9,v 1.52 2019/05/08 14:25:39 isaki Exp $
.\"
.\" Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -44,12 +44,11 @@ structure.
struct audio_hw_if {
int (*open)(void *, int);
void (*close)(void *);
int (*drain)(void *);
int (*query_encoding)(void *, struct audio_encoding *);
int (*set_params)(void *, int, int,
audio_params_t *, audio_params_t *,
stream_filter_list_t *, stream_filter_list_t *);
int (*query_format)(void *, audio_format_query_t *);
int (*set_format)(void *, int,
const audio_params_t *, const audio_params_t *,
audio_filter_reg_t *, audio_filter_reg_t *);
int (*round_blocksize)(void *, int, int, const audio_params_t *);
int (*commit_settings)(void *);
@ -68,7 +67,6 @@ struct audio_hw_if {
#define SPKR_OFF 0
int (*getdev)(void *, struct audio_device *);
int (*setfd)(void *, int);
int (*set_port)(void *, mixer_ctrl_t *);
int (*get_port)(void *, mixer_ctrl_t *);
@ -78,7 +76,6 @@ struct audio_hw_if {
void *(*allocm)(void *, int, size_t);
void (*freem)(void *, void *, size_t);
size_t (*round_buffersize)(void *, int, size_t);
paddr_t (*mappage)(void *, void *, off_t, int);
int (*get_props)(void *);
@ -130,6 +127,15 @@ the hardware request another block a block of silence will be used instead.
Furthermore, if the user process does not read data quickly enough during
recording data will be thrown away.
.Pp
The phase that these functions are called is classified into three.
Attach phase, Closed phase and Opened phase.
Attach phase is during device attach and
it transits to the Closed phase when the attach succeeded.
Closed phase is when no sampling device is opened and
it transits to the Opened phase when open succeeded.
Opened phase is when any sampling device is opened and
it transits to the Closed phase when close succeeded.
.Pp
The fields of
.Va audio_hw_if
are described in some more detail below.
@ -138,147 +144,173 @@ Some fields are optional and can be set to
if not needed.
.Bl -tag -width indent
.It Dv int open(void *hdl, int flags)
optional, is called when the audio device is opened.
It should initialize the hardware for I/O.
optional, is called when the first device combining playback and recording
is opened.
On a full duplex hardware,
.Dv (FREAD | FWRITE)
is passed to flags.
On a half duplex hardware,
.Dv FWRITE
is passed for playback, or
.Dv FREAD
for recording.
Every successful call to
.Va open
is matched by a call to
.Va close .
Return 0 on success, otherwise an error code.
It is called at Closed phase.
.It Dv void close(void *hdl)
optional, is called when the audio device is closed.
.It Dv int drain(void *hdl)
optional, is called before the device is closed or when
.Dv AUDIO_DRAIN
is called.
It should make sure that no samples remain in to be played that could
be lost when
.Va close
is called.
Return 0 on success, otherwise an error code.
.It Dv int query_encoding(void *hdl, struct audio_encoding *ae)
is used when
.Dv AUDIO_GETENC
is called.
It should fill the
.Va audio_encoding
structure and return 0 or, if there is no encoding with the
given number, return EINVAL.
.It Dv int set_params(void *hdl, int setmode, int usemode,
.Dv "audio_params_t *play, audio_params_t *rec,"
optional, is called when the last audio device combining
playback and recording is closed.
It is called at Opened phase.
.It Dv int query_format(void *hdl, audio_format_query_t *afp)
is called to enumerate formats supported by the hardware.
It should fill the audio_format_t structure according to given number
afp->index.
If there is no format with given number, return EINVAL.
It is called at any time.
.Bd -literal
typedef struct audio_format_query {
u_int index;
struct audio_format fmt;
} audio_format_query_t;
.Ed
.Pp
.Dv "stream_filter_list_t *pfil, stream_filter_list_t *rfil)"
It is also used to determine the default format.
The upper layer chooses the most preferred one as default format by following:
.\" XXX I don't know syntax to represent <OL> in html
1. Higher priority is preferred (normally 0, the highest is 3, the lowest is 0).
2. AUDIO_ENCODING_SLINEAR_NE:16 is preferred if exists.
3. AUDIO_ENCODING_SLINEAR_OE:16 is preferred if exists.
4. More channels is preferred.
.Pp
Called to set the audio encoding mode.
If the driver supports SLINEAR_NE:16 and the upper layer chooses it,
the driver does not need to provide conversion function in
.Va set_format .
Similarly, if the driver supports SLINEAR_OE:16 and the upper layer chooses it,
the driver does not need to provide conversion function.
Because the upper layer only supports conversion between
SLINEAR_NE:16 and SLINEAR_OE:16 for convenience.
If the upper layer chooses other format,
the driver needs to provide conversion function in
.Va set_format .
See also
.Va set_format .
If the driver can not provide the conversion from/to SLINEAR_NE:16,
set priority to -1.
It means that the hardware supports this format but the driver does not
(e.g. AC3), and it will never be chosen.
.It Dv int set_foramt(void *hdl, int setmode,
.Dv "const audio_params_t *play, const audio_params_t *rec,"
.Dv "audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)"
.Pp
is called to set specified format to the hardware,
when the device is attached or the hardware format is changed.
.Va setmode
is a combination of the
.Dv AUMODE_RECORD
and
.Dv AUMODE_PLAY
flags to indicate which mode(s) are to be set.
.Va usemode
is also a combination of these flags, but indicates the current
mode of the device (i.e., the value of
.Va mode
in the
.Va audio_info
struct).
flags to indicate which modes are to be set.
.Pp
The
.Va play
and
.Va rec
structures contain the encoding parameters that should be set.
The values of the structures may also be modified if the hardware
cannot be set to exactly the requested mode (e.g., if the requested
sampling rate is not supported, but one close enough is).
.Pp
If the hardware requires software assistance with some encoding
(e.g., it might be lacking mu-law support) it should fill the
structures contain the encoding parameters that should be set to the hardware.
If the driver has query_format interface,
all parameters on
.Va play
and/or
.Va rec
are chosen from formats returned by query_format.
Therefore
.Va play
and/or
.Va rec
are always settable.
If the driver does not have query_format interface,
the driver has to validate the format.
If the hardware does not support
.Dv AUDIO_ENCODING_SLINEAR_{NE,OE}:16 ,
conversion information should be filled the
.Va pfil
for playing or
.Va rfil
for recording with conversion information.
For example, if
.Va play
requests [8000Hz, mu-law, 8/8bit, 1ch] and the hardware does not
support 8bit mu-law, but 16bit slinear_le, the driver should call
.Dv pfil->append()
with
.Va pfil ,
.Va mulaw_to_linear16 ,
and audio_params_t representing [8000Hz, slinear_le, 16/16bit, 2ch].
If the driver needs multiple conversions, a conversion nearest to the
hardware should be set to the head of
.Va pfil
or
.Va rfil .
The definition of
.Dv stream_filter_list_t
follows:
for recording.
The definition of audio_filter_reg_t and related structure follow:
.Bd -literal
typedef struct stream_filter_list {
void (*append)(struct stream_filter_list *,
stream_filter_factory_t,
const audio_params_t *);
void (*prepend)(struct stream_filter_list *,
stream_filter_factory_t,
const audio_params_t *);
void (*set)(struct stream_filter_list *, int,
stream_filter_factory_t,
const audio_params_t *);
int req_size;
struct stream_filter_req {
stream_filter_factory_t *factory;
audio_params_t param; /* from-param for recording,
to-param for playing */
} filters[AUDIO_MAX_FILTERS];
} stream_filter_list_t;
typedef struct {
const void *src;
const audio_format2_t *srcfmt;
void *dst;
const audio_format2_t *dstfmt;
int count;
void *context;
} audio_filter_arg_t;
typedef void(*audio_filter_t)(audio_filter_arg_t *arg);
typedef struct {
audio_filter_t codec;
void *context;
} audio_filter_reg_t;
.Ed
.Pp
For playing,
.Va pfil
constructs conversions as follows:
.Bd -literal
(play) == write(2) input
| pfil->filters[pfil->req_size-1].factory
(pfil->filters[pfil->req_size-1].param)
| pfil->filters[pfil->req_size-2].factory
:
| pfil->filters[1].factory
(pfil->filters[1].param)
| pfil->filters[0].factory
(pfil->filters[0].param) == hardware input
.Ed
.Va codec
is conversion function and
.Va context
is optional opaque pointer passed to
.Va codec .
.Pp
For recording,
.Va rfil
constructs conversions as follows:
.Bd -literal
(rfil->filters[0].param) == hardware output
| rfil->filters[0].factory
(rfil->filters[1].param)
| rfil->filters[1].factory
:
| rfil->filters[rfil->req_size-2].factory
(rfil->filters[rfil->req_size-1].param)
| rfil->filters[rfil->req_size-1].factory
(rec) == read(2) output
.Ed
When
.Va codec
is called, all parameters required by
.Va codec
are contained in
.Va arg .
.Va src
points input buffer block,
.Va srcfmt
contains input encoding parameter,
.Va dst
points output buffer block and
.Va dstfmt
contains output encoding parameter.
.Va count
represents the number of frames to process on this call.
.Va src
and
.Va dst
are guaranteed to be able to consecutively access number of frames
specified by
.Va count.
.Va codec
must fill entire
.Va dst .
For example, let count = 100, srcfmt is { precision = 16, channels = 3 },
dstfmt is { precision = 8, channels = 4 },
in this case,
src block length = 2(bytes) * 3(channels) * 100(frames) = 600 bytes,
The length to be written to
.Va dst
block is 1(byte) * 4(channels) * 100(frames) = 400 bytes.
.Va codec
cannot abort the conversion halfway and there is no error reporting mechanism.
.Va context
is a opaque pointer that can be used by
.Va codec
if necessary.
.Pp
If the device does not have the
.Dv AUDIO_PROP_INDEPENDENT
property the same value is passed in both
.Va play
and
.Va rec
and the encoding parameters from
.Va play
is copied into
.Va rec
after the call to
.Va set_params .
.Va rec .
Return 0 on success, otherwise an error code.
It is called at Attach or Closed phase.
.It Dv int round_blocksize(void *hdl, int bs, int mode,
.Dv "const audio_params_t *param)"
.Pp
@ -294,6 +326,7 @@ and
encoding parameters for the hardware.
It should return a block size, possibly changed according to the needs
of the hardware driver.
It is called at Attach or Closed phase.
.It Dv int commit_settings(void *hdl)
optional, is called after all calls to
.Va set_params ,
@ -304,6 +337,7 @@ A hardware driver that needs to get the hardware in and out of command
mode for each change can save all the changes during previous calls and
do them all here.
Return 0 on success, otherwise an error code.
It is called at Attach or Closed phase.
.It Dv int init_output(void *hdl, void *buffer, int size)
optional, is called before any output starts, but when the total
.Va size
@ -312,6 +346,7 @@ of the output
has been determined.
It can be used to initialize looping DMA for hardware that needs that.
Return 0 on success, otherwise an error code.
It is called at Attach or Closed phase.
.It Dv int init_input(void *hdl, void *buffer, int size)
optional, is called before any input starts, but when the total
.Va size
@ -320,6 +355,7 @@ of the input
has been determined.
It can be used to initialize looping DMA for hardware that needs that.
Return 0 on success, otherwise an error code.
It is called at Attach or Closed phase.
.It Dv int start_output(void *hdl, void *block, int blksize,
.Dv "void (*intr)(void*), void *intrarg)"
.Pp
@ -339,6 +375,7 @@ Calling
will normally initiate another call to
.Va start_output .
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int start_input(void *hdl, void *block, int blksize,
.Dv "void (*intr)(void*), void *intrarg)"
.Pp
@ -358,32 +395,32 @@ Calling
will normally initiate another call to
.Va start_input .
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int halt_output(void *hdl)
is called to abort the output transfer (started by
.Va start_output )
in progress.
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int halt_input(void *hdl)
is called to abort the input transfer (started by
.Va start_input )
in progress.
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int speaker_ctl(void *hdl, int on)
optional, is called when a half duplex device changes between
playing and recording.
It can, e.g., be used to turn on
and off the speaker.
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int getdev(void *hdl, struct audio_device *ret)
Should fill the
.Va audio_device
struct with relevant information about the driver.
Return 0 on success, otherwise an error code.
.It Dv int setfd(void *hdl, int fd)
optional, is called when
.Dv AUDIO_SETFD
is used, but only if the device has AUDIO_PROP_FULLDUPLEX set.
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int set_port(void *hdl, mixer_ctrl_t *mc)
is called in when
.Dv AUDIO_MIXER_WRITE
@ -392,6 +429,7 @@ It should take data from the
.Va mixer_ctrl_t
struct at set the corresponding mixer values.
Return 0 on success, otherwise an error code.
It is called at Opened or Closed phase.
.It Dv int get_port(void *hdl, mixer_ctrl_t *mc)
is called in when
.Dv AUDIO_MIXER_READ
@ -400,6 +438,7 @@ It should fill the
.Va mixer_ctrl_t
struct.
Return 0 on success, otherwise an error code.
It is called at Opened or Closed phase.
.It Dv int query_devinfo(void *hdl, mixer_devinfo_t *di)
is called in when
.Dv AUDIO_MIXER_DEVINFO
@ -408,6 +447,7 @@ It should fill the
.Va mixer_devinfo_t
struct.
Return 0 on success, otherwise an error code.
It is called at any time.
.It Dv "void *allocm(void *hdl, int direction, size_t size)"
optional, is called to allocate the device buffers.
If not present
@ -419,12 +459,14 @@ is that some buses need special allocation to do DMA.
Returns the address of the buffer, or
.Dv NULL
on failure.
It is called at Attached or Closed phase.
.It Dv void freem(void *hdl, void *addr, size_t size)
optional, is called to free memory allocated by
.Va allocm .
If not supplied
.Xr free 9
is used.
It is called at Attached or Closed phase.
.It Dv size_t round_buffersize(void *hdl, int direction, size_t bufsize)
optional, is called at startup to determine the audio
buffer size.
@ -432,21 +474,14 @@ The upper layer supplies the suggested size in
.Va bufsize ,
which the hardware driver can then change if needed.
E.g., DMA on the ISA bus cannot exceed 65536 bytes.
.It Dv "paddr_t mappage(void *hdl, void *addr, off_t offs, int prot)"
.Pp
optional, is called for
.Xr mmap 2 .
Should return the map value for the page at offset
.Va offs
from address
.Va addr
mapped with protection
.Va prot .
Returns -1 on failure, or a machine dependent opaque value
on success.
It is called at Attached or Closed phase.
.It Dv int get_props(void *hdl)
Should return the device properties; i.e., a combination of
AUDIO_PROP_xxx.
It is called at any time.
.Pp
.Dv AUDIO_PROP_MMAP
is acceptable but obsoleted, so new drivers should not return this property.
.It Dv int trigger_output(void *hdl, void *start, void *end,
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
.Pp
@ -471,6 +506,7 @@ should be called with the argument
Once started the transfer may be stopped using
.Va halt_output .
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int trigger_input(void *hdl, void *start, void *end,
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
.Pp
@ -495,6 +531,7 @@ should be called with the argument
Once started the transfer may be stopped using
.Va halt_input .
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv int dev_ioctl(void *hdl, u_long cmd, void *addr,
.Pp
.Dv "int flag, struct lwp *l)"
@ -503,8 +540,10 @@ optional, is called when an
.Xr ioctl 2
is not recognized by the generic audio driver.
Return 0 on success, otherwise an error code.
It is called at Opened phase.
.It Dv void get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
Returns the interrupt and thread locks to the common audio layer.
It is called at Attach phase.
.El
.Pp
The
@ -591,8 +630,7 @@ and that is a control named
of class
.Dv AudioCmonitor .
.Sh SEE ALSO
.Xr audio 4 ,
.Xr audio_system 9
.Xr audio 4
.Sh HISTORY
This
.Nm

View File

@ -1,307 +0,0 @@
.\" $NetBSD: audio_system.9,v 1.1 2018/05/28 00:18:06 nat Exp $
.\"
.\" Copyright (c) 2016 - 2018 Nathanial Sloss <nathanialsloss@yahoo.com.au>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 28, 2018
.Dt AUDIO_SYSTEM 9
.Os
.Sh NAME
.Nm audio_system
.Nd the
.Nx
in-kernel audio mixer specification
.Sh INTRODUCTION
This document aims to describe all aspects of the in-kernel audio mixer
included with
.Nx 8
and onwards, describing its current behavior as of 2018.
.Sh VIRTUAL CHANNEL (VCHAN)
This is the most fundamental element to the mixer.
The vchan has all of the properties of the traditional single open
.Nx
audio channel.
It consists of playback and record rings along with
.Vt audio_info
structures.
.Pp
Upon opening of
.Pa /dev/audio
or
.Pa /dev/sound ,
a new vchan and mixerctl structure is created.
In the case of
.Pa /dev/sound ,
.Vt audio_info
structures are inherited from the last open of
.Pa /dev/audio
or
.Pa /dev/sound .
.Pp
All vchans are up or down sampled into the mix ring (intermediate) format
before being sent to hardware.
.Pp
It is described in the following diagram:
.Bd -literal
VCHAN1---------\\
\\ VCHAN0
VCHAN2-------------MIX RING ---- HARDWARE
... /
VCHANn---------/
.Ed
.Pp
In the case of
.Xr sysctl 8
.Dv usemixer=0
(see below), there is only one vchan whose play
and record rings are the hardware play/record rings.
.Pp
User accessible vchans are numbered starting at one (1).
Vchan 0 is used internally by the mixer for the mix ring and its ring buffers
are not user accessible.
.Pp
The only limit to the number of open vchans is the speed of the computer and the
number of free file descriptors.
.Sh BLOCK - SIZE / LATENCY
A block of audio data is the basic unit for audio data.
Audio applications will not commence playback until three (3) blocks have been
written - this is the source of latency in the mixer along with the size of the
audio data block.
.Pp
For normal uses of audio read/write there will be three blocks of audio data before
playback commences one in the vchan, one in the mix ring and one in the
hardware ring.
.Pp
The size of the audio data block is dependent on the audio format configured
by the application the latency
.Xr sysctl 8
and the underlying audio hardware.
.Pp
Some audio hardware devices only support a static block size, as such the
overall latency of the mixer for these devices cannot be changed.
Other devices such as those supported by
.Xr hdaudio 4
allow the hardware block size
to be changed, allowing the latency of the mixer to change from 4
milliseconds (ms) to 128 ms with the mixer intermediate format being 16 bit,
stereo, 48 kHz.
.Pp
With regard to mmapped audio, blocks are played back immediately so the latency
presented to applications is one third of the latency
.Xr sysctl 8
value.
.Pp
Latency can be calculated by the following formula:
.Bd -literal
Latency (ms) = blocksize(bytes) * num blocks * 1000
--------------------------------------
freq(Hz) * bytes per sample * channels
.Ed
.Pp
Latency in the mixer and latency presented to audio applications is consistent,
it will be the same regardless of the audio format requested by the audio
application.
.Pp
The default latency configured at boot time is 150ms and is subject to the above
constraints.
.Sh ADDED IOCTLS
Two new ioctls have been added to accommodate mixing of multiple vchans:
.Bl -tag -width indent
.It Dv AUDIO_SETCHAN :
Allows setting the target vchan to operate on for subsequent
.Xr ioctl 2
calls.
.It Dv AUDIO_GETCHAN :
Returns the current vchan number.
.El
.Pp
These ioctls were necessary as some audio applications like to open an
.Xr audio 4
device and an
.Xr audioctl 4
device so to check on buffer usage and samples played etc.
.Pp
As opening an
.Xr audioctl 4
device would represent vchan 0 (the mix ring), these
ioctls allow setting the target vchan and
.Vt audio_info
structure to that of an existing vchan.
.Sh MIXERCTL INTERFACE / SOFTWARE VOLUME
Mixerctl structures are allocated when a new vchan is created.
The mixer control structure allows for setting the software volume for playback -
.Li vchan.dacN
or recording -
.Li vchan.adcN .
These are 8 bit values and the this value is applied during mixing into the mix
ring.
.Pp
The software volume is applied to all channels (1, 2, 4 etc.) in the vchan and at
present (2018-05-04) there are no balance controls for user accessible vchans.
.Pp
The first vchan corresponds to the
.Li vchan.dac1/adc1
mixer controls.
.Pp
All vchan mixer controls only have effect upon its own volume and writing to
.Li outputs.master
(or equivalent) control is required to change the volume of the hardware.
.Pp
Mixer controls are only present whilst the chan is in use and numbering starts
at one (1).
Mixer control numbers i.e.
.Li dac/adc1
correspond to their vchan number.
.Sh AUDIOCTL / AUDIO_INFO INTERFACE
Audioctl allows access to the
.Vt audio_info
structure of a given device.
Due to the audio mixer a
.Fl p
flag was added to allow access to a given vchan's
.Vt audio_info
structure.
The values for
.Fl p
are numbered starting at zero (0).
.Pp
Not specifying
.Fl p
is the same as specifying
.Fl p Ar 0
and will result in working with vchan 0 (the mix ring).
This will display the audio parameters of the mix ring and allow
setting the hardware gain and balance.
.Pp
This is for compatibility with existing applications and shell scripts
that are unaware of the
.Fl p
switch.
.Pp
The parameters for playback and recording only effect the particular vchan
being operated on (gain, sample rate, channels, encoding etc), except
.Fl p Ar 0
(the mix ring).
.Sh ADDED SYSCTLS
With the introduction of the audio mixer the following
.Xr sysctl 7 Ns s
have been added:
.Bl -tag -width indent
.It Li hw.driverN.frequency :
.It Li hw.driverN.precision :
.It Li hw.driverN.channels :
Intermediate mixing format.
(see below)
.It Li hw.driverN.latency :
Expressed in milliseconds.
(see above)
.It Li hw.driverN.multiuser :
Off/On (0/1), defaults to off.
This
.Xr sysctl 7
determines if multiple users are allowed to access the sound hardware.
The root user is always allowed access (i.e., for wsbell).
The first user to open the audio device has full control of the audio device
if this sysctl is set to off.
There currently is an outstanding PR about affecting a privileged process -
PR/52627.
.Pp
Ideally if root intervenes with the audio device, it should do so unaffected.
.Pp
If this control is set to on, then all users' audio data are mixed and all users
have access to the audio hardware.
.It Li hw.driverN.usemixer :
Off/On (0/1), defaults to on.
This
.Xr sysctl 7
enables or disables the audio mixer.
When set to off, the audio device can support only one vchan.
This vchan's play and record ring buffers are the hardware ring buffers.
.Pp
This option was added to aid older/slower systems where the extra overhead of
the audio mixer might pose a problem.
.El
.Sh INTERMEDIATE / MIXING FORMAT
The initial concept was to handle incoming audio data similarly to that of a
superheterodyne radio receiver:
.Pp
.Dl RF -> IF -> AF
.Pp
So the corresponding mixing concept is:
.Pp
.Dl vchan -> mixing format -> hardware
.Pp
The
.Xr sysctl 7 Ns s
described above determine the format for mixing.
All vchans are up or down sampled to this format before mixing takes place.
.Pp
On most systems this defaults to 16 bit stereo 48kHz.
The
.Xr sysctl 7 Ns s
governing the mixing format may only be changed when there are no
vchans in use.
.Pp
On faster systems the precision (8, 16, 32 bits) may be changed along with the
sample rate and number of channels (mono, stereo, 4 etc.).
.Pp
On older/slower systems utilizing audio mixing, it may be required to lower the
quality of this format to ease the amount of data processing whilst mixing.
.Pp
All possible audio formats (mulaw, alaw, slinear, ulinear, 8, 16, and 32 bit
precision) are converted for use by the audio mixer.
.Sh MEMORY MAPPED PLAYBACK
It is possible to use mmap for audio playback, achieving reduced latency.
However the audio applications selected format must match the
mixing/intermediate format (see above).
.Pp
It is possible to obtain the
.Vt audio_info
for vchan0 which contains the
intermediate/mixing format to ease applications configuring for mmapped audio.
.Pp
At present most applications don't use the mix ring's
.Vt audio_info
structure to obtain the requiredplay back parameters and some user
intervention is required to set the audio format for the application.
.Sh HARDWARE DRIVER REQUIREMENTS
Audio mixing requires signed linear support in the host's endianness.
Driver authors should support slinear_le and slinear_be formats.
.Pp
If the audio hardware is intended to be used with the mixer disabled, mulaw 1ch
8000 hz needs to be supported also.
.Pp
This is easily achievable with the auconv framework/filters.
All new drivers should consider the use of auconv where possible.
.Sh SEE ALSO
.Xr audioctl 1 ,
.Xr mixerctl 1 ,
.Xr audio 4 ,
.Xr audio 9
.Sh AUTHORS
.An Nathanial Sloss
.Sh SPECIAL THANKS
Great appreciation goes to Onno van der Linden, isaki@, maya@, jmcneill@,
pgoyette@, mrg@, riastradh@ and christos@ \(em without their input, this code would
not be what it is currently.

View File

@ -1,4 +1,4 @@
.\" $NetBSD: intro.9,v 1.23 2018/07/15 05:16:41 maxv Exp $
.\" $NetBSD: intro.9,v 1.24 2019/05/08 14:25:39 isaki Exp $
.\"
.\" Copyright (c) 1997, 2007 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -435,11 +435,6 @@ Interface between low and high level audio drivers.
See
.Xr audio 9 .
.Pp
The
.Nx audio specification.
See
.Xr audio_system 9 .
.Pp
Bluetooth Device/Protocol API.
See
.Xr bluetooth 9 .