671 lines
20 KiB
Groff
671 lines
20 KiB
Groff
.\" $NetBSD: audio.9,v 1.56 2019/06/12 13:53:25 wiz Exp $
|
|
.\"
|
|
.\" Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Lennart Augustsson.
|
|
.\"
|
|
.\" 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 9, 2019
|
|
.Dt AUDIO 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm audio
|
|
.Nd interface between low and high level audio drivers
|
|
.Sh DESCRIPTION
|
|
The audio device driver is divided into a high level,
|
|
hardware independent layer, and a low level hardware
|
|
dependent layer.
|
|
The interface between these is the
|
|
.Va audio_hw_if
|
|
structure.
|
|
.Bd -literal
|
|
struct audio_hw_if {
|
|
int (*open)(void *, int);
|
|
void (*close)(void *);
|
|
|
|
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 *);
|
|
|
|
int (*init_output)(void *, void *, int);
|
|
int (*init_input)(void *, void *, int);
|
|
int (*start_output)(void *, void *, int, void (*)(void *),
|
|
void *);
|
|
int (*start_input)(void *, void *, int, void (*)(void *),
|
|
void *);
|
|
int (*halt_output)(void *);
|
|
int (*halt_input)(void *);
|
|
|
|
int (*speaker_ctl)(void *, int);
|
|
#define SPKR_ON 1
|
|
#define SPKR_OFF 0
|
|
|
|
int (*getdev)(void *, struct audio_device *);
|
|
|
|
int (*set_port)(void *, mixer_ctrl_t *);
|
|
int (*get_port)(void *, mixer_ctrl_t *);
|
|
|
|
int (*query_devinfo)(void *, mixer_devinfo_t *);
|
|
|
|
void *(*allocm)(void *, int, size_t);
|
|
void (*freem)(void *, void *, size_t);
|
|
size_t (*round_buffersize)(void *, int, size_t);
|
|
|
|
int (*get_props)(void *);
|
|
|
|
int (*trigger_output)(void *, void *, void *, int,
|
|
void (*)(void *), void *, const audio_params_t *);
|
|
int (*trigger_input)(void *, void *, void *, int,
|
|
void (*)(void *), void *, const audio_params_t *);
|
|
int (*dev_ioctl)(void *, u_long, void *, int, struct lwp *);
|
|
void (*get_locks)(void *, kmutex_t **, kmutex_t **);
|
|
};
|
|
|
|
typedef struct audio_params {
|
|
u_int sample_rate; /* sample rate */
|
|
u_int encoding; /* e.g. mu-law, linear, etc */
|
|
u_int precision; /* bits/subframe */
|
|
u_int validbits; /* valid bits in a subframe */
|
|
u_int channels; /* mono(1), stereo(2) */
|
|
} audio_params_t;
|
|
.Ed
|
|
.Pp
|
|
The high level audio driver attaches to the low level driver
|
|
when the latter calls
|
|
.Va audio_attach_mi .
|
|
This call should be
|
|
.Bd -literal
|
|
device_t
|
|
audio_attach_mi(const struct audio_hw_if *ahwp, void *hdl, device_t dev);
|
|
.Ed
|
|
.Pp
|
|
The
|
|
.Va audio_hw_if
|
|
struct is as shown above.
|
|
The
|
|
.Va hdl
|
|
argument is a handle to some low level data structure.
|
|
It is sent as the first argument to all the functions
|
|
in
|
|
.Va audio_hw_if
|
|
when the high level driver calls them.
|
|
.Va dev
|
|
is the device struct for the hardware device.
|
|
.Pp
|
|
The upper layer of the audio driver allocates one buffer for playing
|
|
and one for recording.
|
|
It handles the buffering of data from the user processes in these.
|
|
The data is presented to the lower level in smaller chunks, called blocks.
|
|
If, during playback, there is no data available from the user process when
|
|
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.
|
|
Some fields are optional and can be set to
|
|
.Dv NULL
|
|
if not needed.
|
|
.Bl -tag -width indent
|
|
.It Dv int open(void *hdl, int flags)
|
|
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 in the Closed phase.
|
|
.It Dv void close(void *hdl)
|
|
optional, is called when the last audio device combining
|
|
playback and recording is closed.
|
|
It is called in the 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
|
|
.Vt audio_format_t
|
|
structure according to given number
|
|
.Va afp->index .
|
|
If there is no format with given number, return
|
|
.Er 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
|
|
It is also used to determine the default format.
|
|
The upper layer chooses the most preferred one as default format by following:
|
|
.Bl -enum
|
|
.It
|
|
Higher priority is preferred (normally 0, the highest is 3, the lowest is 0).
|
|
.It
|
|
.Dv AUDIO_ENCODING_SLINEAR_NE:16
|
|
is preferred if exists.
|
|
.It
|
|
.Dv AUDIO_ENCODING_SLINEAR_OE:16
|
|
is preferred if exists.
|
|
.It
|
|
More channels is preferred.
|
|
.El
|
|
.Pp
|
|
If the driver supports
|
|
.Dv 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
|
|
.Dv SLINEAR_OE:16
|
|
and the upper layer chooses it,
|
|
the driver does not need to provide a conversion function.
|
|
Because the upper layer only supports conversion between
|
|
.Dv SLINEAR_NE:16
|
|
and
|
|
.Dv SLINEAR_OE:16
|
|
for convenience.
|
|
If the upper layer chooses another format,
|
|
the driver needs to provide a conversion function in
|
|
.Va set_format .
|
|
See also
|
|
.Va set_format .
|
|
If the driver can not provide the conversion from/to
|
|
.Dv 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 modes are to be set.
|
|
.Pp
|
|
The
|
|
.Va play
|
|
and
|
|
.Va rec
|
|
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.
|
|
The definition of
|
|
.Vt audio_filter_reg_t
|
|
and a related structure follow:
|
|
.Bd -literal
|
|
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
|
|
.Va codec
|
|
is a conversion function and
|
|
.Va context
|
|
is an optional opaque pointer passed to
|
|
.Va codec .
|
|
.Pp
|
|
When
|
|
.Va codec
|
|
is called, all parameters required by
|
|
.Va codec
|
|
are contained in
|
|
.Va arg .
|
|
.Va src
|
|
points to the input buffer block,
|
|
.Va srcfmt
|
|
contains the input encoding parameters,
|
|
.Va dst
|
|
points to the output buffer block and
|
|
.Va dstfmt
|
|
contains the output encoding parameters.
|
|
.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 .
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the Attach or Closed phases.
|
|
.It Dv int round_blocksize(void *hdl, int bs, int mode,
|
|
.Dv "const audio_params_t *param)"
|
|
.Pp
|
|
optional, is called with the block size,
|
|
.Va bs ,
|
|
that has been computed by the upper layer,
|
|
.Va mode ,
|
|
.Dv AUMODE_PLAY
|
|
or
|
|
.Dv AUMODE_RECORD ,
|
|
and
|
|
.Va param ,
|
|
encoding parameters for the hardware.
|
|
It should return a block size, possibly changed according to the needs
|
|
of the hardware driver.
|
|
It is called in the Attach or Closed phases.
|
|
.It Dv int commit_settings(void *hdl)
|
|
optional, is called after all calls to
|
|
.Va set_params ,
|
|
and
|
|
.Va set_port ,
|
|
are done.
|
|
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 in the Attach or Closed phases.
|
|
.It Dv int init_output(void *hdl, void *buffer, int size)
|
|
optional, is called before any output starts, but when the total
|
|
.Va size
|
|
of the output
|
|
.Va buffer
|
|
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 in the Attach or Closed phases.
|
|
.It Dv int init_input(void *hdl, void *buffer, int size)
|
|
optional, is called before any input starts, but when the total
|
|
.Va size
|
|
of the input
|
|
.Va buffer
|
|
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 in the Attach or Closed phases.
|
|
.It Dv int start_output(void *hdl, void *block, int blksize,
|
|
.Dv "void (*intr)(void*), void *intrarg)"
|
|
.Pp
|
|
is called to start the transfer of
|
|
.Va blksize
|
|
bytes from
|
|
.Va block
|
|
to the audio hardware.
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is ready to accept more samples the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg .
|
|
Calling
|
|
.Va intr
|
|
will normally initiate another call to
|
|
.Va start_output .
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the Opened phase.
|
|
.It Dv int start_input(void *hdl, void *block, int blksize,
|
|
.Dv "void (*intr)(void*), void *intrarg)"
|
|
.Pp
|
|
is called to start the transfer of
|
|
.Va blksize
|
|
bytes to
|
|
.Va block
|
|
from the audio hardware.
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is ready to deliver more samples the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg .
|
|
Calling
|
|
.Va intr
|
|
will normally initiate another call to
|
|
.Va start_input .
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the 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 in the 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 in the 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 in the 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 is called in the Opened phase.
|
|
.It Dv int set_port(void *hdl, mixer_ctrl_t *mc)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_WRITE
|
|
is used.
|
|
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 in the Opened or Closed phases.
|
|
.It Dv int get_port(void *hdl, mixer_ctrl_t *mc)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_READ
|
|
is used.
|
|
It should fill the
|
|
.Va mixer_ctrl_t
|
|
struct.
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the Opened or Closed phases.
|
|
.It Dv int query_devinfo(void *hdl, mixer_devinfo_t *di)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_DEVINFO
|
|
is used.
|
|
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
|
|
.Xr malloc 9
|
|
is used instead (with the same arguments but the first two).
|
|
The reason for using a device dependent routine instead of
|
|
.Xr malloc 9
|
|
is that some buses need special allocation to do DMA.
|
|
Returns the address of the buffer, or
|
|
.Dv NULL
|
|
on failure.
|
|
It is called in the Attached or Closed phases.
|
|
.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 in the Attached or Closed phases.
|
|
.It Dv size_t round_buffersize(void *hdl, int direction, size_t bufsize)
|
|
optional, is called at startup to determine the audio
|
|
buffer size.
|
|
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 is called in the Attached or Closed phases.
|
|
.It Dv int get_props(void *hdl)
|
|
Should return the device properties in a combination of following flags:
|
|
.Pp
|
|
.Bl -tag -width AUDIO_PROP_INDEPENDENT -compact
|
|
.It Dv AUDIO_PROP_PLAYBACK
|
|
the device is capable of audio playback.
|
|
.It Dv AUDIO_PROP_CAPTURE
|
|
the device is capable of audio capture.
|
|
.It Dv AUDIO_PROP_FULLDUPLEX
|
|
the device admits full duplex operation.
|
|
Don't set it if the device is unidirectional.
|
|
.It Dv AUDIO_PROP_INDEPENDENT
|
|
the device can set the playing and recording encoding parameters
|
|
independently.
|
|
Don't set it if the device is unidirectional.
|
|
.It Dv AUDIO_PROP_MMAP
|
|
is handled in the upper layer, so new drivers should not return this property.
|
|
.El
|
|
It is called in the Attach phase.
|
|
.It Dv int trigger_output(void *hdl, void *start, void *end,
|
|
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
|
|
.Pp
|
|
.Dv "const audio_params_t *param)"
|
|
.Pp
|
|
optional, is called to start the transfer of data from the circular buffer
|
|
delimited by
|
|
.Va start
|
|
and
|
|
.Va end
|
|
to the audio hardware, parameterized as in
|
|
.Va param .
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is finished transferring each
|
|
.Va blksize
|
|
sized block, the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg
|
|
(typically from the audio hardware interrupt service routine).
|
|
Once started the transfer may be stopped using
|
|
.Va halt_output .
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the Opened phase.
|
|
.It Dv int trigger_input(void *hdl, void *start, void *end,
|
|
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
|
|
.Pp
|
|
.Dv "const audio_params_t *param)"
|
|
.Pp
|
|
optional, is called to start the transfer of data from the audio hardware,
|
|
parameterized as in
|
|
.Va param ,
|
|
to the circular buffer delimited by
|
|
.Va start
|
|
and
|
|
.Va end .
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is finished transferring each
|
|
.Va blksize
|
|
sized block, the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg
|
|
(typically from the audio hardware interrupt service routine).
|
|
Once started the transfer may be stopped using
|
|
.Va halt_input .
|
|
Return 0 on success, otherwise an error code.
|
|
It is called in the Opened phase.
|
|
.It Dv int dev_ioctl(void *hdl, u_long cmd, void *addr,
|
|
.Pp
|
|
.Dv "int flag, struct lwp *l)"
|
|
.Pp
|
|
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 in the 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 in the Attach phase.
|
|
.El
|
|
.Pp
|
|
The
|
|
.Va query_devinfo
|
|
method should define certain mixer controls for
|
|
.Dv AUDIO_SETINFO
|
|
to be able to change the port and gain,
|
|
and
|
|
.Dv AUDIO_GETINFO
|
|
to read them, as follows.
|
|
.Pp
|
|
If the record mixer is capable of input from more than one source,
|
|
it should define
|
|
.Dv AudioNsource
|
|
in class
|
|
.Dv AudioCrecord .
|
|
This mixer control should be of type
|
|
.Dv AUDIO_MIXER_ENUM
|
|
or
|
|
.Dv AUDIO_MIXER_SET
|
|
and enumerate the possible input sources.
|
|
Each of the named sources for which the recording level can be set
|
|
should have a control in the
|
|
.Dv AudioCrecord
|
|
class of type
|
|
.Dv AUDIO_MIXER_VALUE ,
|
|
except the
|
|
.Qq mixerout
|
|
source is special,
|
|
and will never have its own control.
|
|
Its selection signifies,
|
|
rather,
|
|
that various sources in class
|
|
.Dv AudioCrecord
|
|
will be combined and presented to the single recording output
|
|
in the same fashion that the sources of class
|
|
.Dv AudioCinputs
|
|
are combined and presented to the playback output(s).
|
|
If the overall recording level can be changed,
|
|
regardless of the input source,
|
|
then this control should be named
|
|
.Dv AudioNmaster
|
|
and be of class
|
|
.Dv AudioCrecord .
|
|
.Pp
|
|
Controls for various sources that affect only the playback output,
|
|
as opposed to recording,
|
|
should be in the
|
|
.Dv AudioCinputs
|
|
class,
|
|
as of course should any controls that affect both playback and recording.
|
|
.Pp
|
|
If the play
|
|
mixer is capable of output to more than one destination,
|
|
it should define
|
|
.Dv AudioNselect
|
|
in class
|
|
.Dv AudioCoutputs .
|
|
This mixer control should be of type
|
|
.Dv AUDIO_MIXER_ENUM
|
|
or
|
|
.Dv AUDIO_MIXER_SET
|
|
and enumerate the possible destinations.
|
|
For each of the named destinations for which the output level can be set,
|
|
there should be
|
|
a control in the
|
|
.Dv AudioCoutputs
|
|
class of type
|
|
.Dv AUDIO_MIXER_VALUE .
|
|
If the overall output level can be changed,
|
|
which is invariably the case,
|
|
then this control should be named
|
|
.Dv AudioNmaster
|
|
and be of class
|
|
.Dv AudioCoutputs .
|
|
.Pp
|
|
There's one additional source recognized specially by
|
|
.Dv AUDIO_SETINFO
|
|
and
|
|
.Dv AUDIO_GETINFO ,
|
|
to be presented as monitor_gain,
|
|
and that is a control named
|
|
.Dv AudioNmonitor ,
|
|
of class
|
|
.Dv AudioCmonitor .
|
|
.Sh SEE ALSO
|
|
.Xr audio 4
|
|
.Sh HISTORY
|
|
This
|
|
.Nm
|
|
interface first appeared in
|
|
.Nx 1.3 .
|