Ioctl Requests mixer(7I)
NAME
mixer - audio mixer audio personality module interface
SYNOPSIS
#include
OVERVIEW
The audio mixer extends the audio(7I) interface, allowing
more then one process to play or record audio at the same
time. Understanding the audio(7I) interface thoroughly is a
prerequisite to understanding the mixer(7I) interface.
Backward Compatibility
It is possible to disable the mixing function and return to
100% backward compatibility with the audio(7I) interface.
These two modes of operation are referred to as the mixer
mode and the compatible mode. This is done by using either
the mixerctl(1) or sdtaudiocontrol(1) applications, or by
editing the audio driver's .conf file and then unloading and
reloading the audio driver.
Multi-Stream Codecs
The audio mixer supports multi-stream Codecs. Examples of
these Codecs are the Crystal Semiconductor 4410/4422 and the
Aureal 8820/8830. These devices have DSP engines that pro-
vide sample rate conversion and other features. Each
play/record channel is mapped to an individual channel
straight into the Codec. The audio mixer does not perform
sample rate or encoding conversion. (See below). However,
the programming interfaces remain the same and applications
cannot distinguish between multi-stream Codec and tradi-
tional Codec.
Buffer Size
An application can use the audio information structure to
set the size of the play/record buffers. As with the
audio(7I) interface, the audio mixer does not support chang-
ing of the play buffer size. Instead, the audio driver takes
sound samples as it can handle them, regardless of how many
are delivered to the driver with each write.
The audio mixer supports changing of the record buffer size.
When captured by the audio driver, buffer size bytes are
sent to the application for reading.
AUDIO FORMATS
See the audio(7I) manual page for a brief discussion of
audio formats. To mix the various audio streams, the audio
mixer must convert all audio formats to a common format. The
following describes how the audio mixer deals with these
SunOS 5.11 Last change: 31 Dec 2001 1
Ioctl Requests mixer(7I)
different components.
Sample Rate
When /dev/audio is opened, the initial sample rate is 8KHz,
as defined in audio(7I).
In mixer mode, the audio mixer always configures the Codec
for the highest possible sample rate for both play and
record. This ensures that none of the audio streams require
compute-intensive low pass filtering. The result is that
high sample rate audio streams are not degraded by filter-
ing.
Sample rate conversion can be a compute-intensive operation,
depending on the number of channels and a device's sample
rate. For example, an 8KHz signal can be easily converted to
48KHz, requiring a low cost up sampling by 6. However, con-
verting from 44.1KHz to 48KHz is compute intensive because
it must be up sampled by 160 and then down sampled by 147.
(This is only done using integer multipliers.)
Applications can greatly reduce the impact of sample rate
conversion by carefully picking the sample rate. Applica-
tions should always use the highest sample rate the device
supports. An application can also do its own sample rate
conversion (to take advantage of floating point and
accelerated instruction) or use small integers for up and
down sampling.
In compatible mode, the audio mixer programs the Codec to
the sample rate set by the application to avoid incurring
any sample rate conversion overhead. If the Codec cannot
support different play and record sample rates, the
AUDIOSETINFO ioctl(2) fails.
Encodings and Precision
When /dev/audio is opened, initial encoding and precision is
8-bit ,u-Law (as in the Greek letter mu) . (As defined in
audio(7I)
In mixer mode, the audio mixer supports formats in the fol-
lowing precisions:
SunOS 5.11 Last change: 31 Dec 2001 2
Ioctl Requests mixer(7I)
Encoding Precision Channels
Signed Linear PCM 16-bit Mono or Stereo
Signed Linear PCM 8-bit Mono or Stereo
,u-Law 8-bit Mono or Stereo
A-Law 8-bit Mono or Stereo
The audio mixer converts all audio streams to 16-bit Linear
PCM before mixing. After mixing, conversion is made to the
best possible Codec format. The conversion process is not
compute intensive and audio applications can choose the
encoding format that best meets its needs.
In compatibility mode, the audio mixer sets the Codec to the
encoding and precision set by the application. If the Codec
cannot support different play and record encodings or preci-
sions, the AUDIOSETINFO ioctl(2) call fails.
Channels
When /dev/audio is opened, the number of initial channels
is 1, left channel mono. (As defined in audio(7I)). Most
Codecs play or record mono audio on the left channel.
In mixer mode, the audio mixer sets the Codec to the maximum
number of channels supported. If a mono signal is played or
recorded, it is mixed on the first (usually the left) chan-
nel only. Silence is mixed on the remaining channels.
In compatible mode, the audio mixer sets the Codec to the
number of channels set by the application. If the Codec can-
not support a different number of play and record channels,
the AUDIOSETINFO ioctl(2) call fails.
DESCRIPTION
The device /dev/audio is a device driver that dispatches
audio requests to the appropriate underlying audio personal-
ity module. The audio driver is implemented as a STREAMS
driver. To record audio input, applications open(2) the
/dev/audio device and read data from it using the read(2)
system call. Similarly, sound data is queued to the audio
output port by using the write(2) system call. Device confi-
guration is performed using the ioctl(2) interface.
Opening the Audio Device
In mixer mode, the audio device is no longer treated as an
exclusive resource. Each process may open the audio device
SunOS 5.11 Last change: 31 Dec 2001 3
Ioctl Requests mixer(7I)
once unless the process has made an
AUDIOMIXERMULTIPLEOPEN ioctl(2) call. See below for
details.
Each open() will complete as long as there are channels
available to be allocated. If no channels are available to
be allocated:
o if either the ONDELAY or ONONBLOCK flags are set
in the open() oflag argument, -1 is immediately
returned, with errno set to EBUSY.
o if neither the ONDELAY nor the ONONBLOCK flags
are set, then open() hangs until a channel becomes
available or a signal is delivered to the process.
In the latter case, a -1 is returned with errno set
to EINTR.
Upon the initial open() of the audio channel, the audio
mixer sets the data format of the audio channel to the
default state of 8-bit, 8Khz, mono ,u-Law data. If the audio
device does not support this configuration, it informs the
audio mixer of the initial configuration. Audio applications
should explicitly set the encoding characteristics to match
the audio data requirements, and not depend on the default
configuration. See the audio(7I) manual page for details on
how the audio mixer behaves when in compatible mode.
Recording Audio Data
The read(2) system call copies data from the system buffers
to the application. Ordinarily, read() blocks until the user
buffer is filled. The INREAD ioctl (see streamio(7I)) may
be used to determine the amount of data that may be read
without blocking. The device may also be set to a non-
blocking mode, where read() completes immediately but may
return fewer bytes than requested. See the read(2) manual
page for a complete description of this behavior.
When the audio device is opened with read access, the device
driver immediately starts buffering audio input data.
Because this consumes system resources, processes that do
not record audio data should open the device write-only
(OWRONLY).
The transfer of input data to STREAMS buffers may be paused
(or resumed) by using the AUDIOSETINFO ioctl to set (or
clear) the record.pause flag in the audio information struc-
ture. (See audio(7I).) All unread input data in the STREAMS
SunOS 5.11 Last change: 31 Dec 2001 4
Ioctl Requests mixer(7I)
queue may be discarded by using the IFLUSH STREAMS ioctl
(see streamio(7I)). When changing record parameters, the
input stream should first be paused and flushed before the
change. Otherwise, subsequent reads may return samples in
the old format, followed by samples in the new format.
Input data accumulates in STREAMS buffers rapidly. For 8-
bit, 8 KHz, mono ,u-Law data, it accumulates at 8000 bytes
per second. If a device is configured for 16-bit linear or
higher sample rates, it accumulates even faster. If the
application that consumes the data is unable to meet the
input data rate, the STREAMS queue may become full. When
this happens, the record.error flag is set in the audio
information structure and input sampling ceases until there
is room for additional data, resulting in a data stream
discontinuity. To prevent this, audio recording applications
should open the audio device when they are ready to begin
reading data and not at the start of extensive initializa-
tion.
Playing Audio Data
The write(2) system call copies data from an application's
buffer to the STREAMS output queue. Ordinarily, write()
blocks until the entire user buffer is transferred. The dev-
ice may alternatively be set to a non-blocking mode, in
which case write() completes immediately, but may transfer
fewer bytes than requested. (See the write(2) manual page
for a complete description of this behavior).
Although write() returns when the data is successfully
queued, the actual completion of audio output may take con-
siderably longer. The AUDIODRAIN ioctl may be issued to
allow an application to block until all of the queued output
data has been played. Alternatively, a process may request
asynchronous notification of output completion by writing a
zero-length buffer (end-of-file record) to the output
stream. When such a buffer has been processed, the play.eof
flag in the audio information structure (see below) is
incremented.
The final close(2) of the audio device file descriptor hangs
until all of the process' remaining audio output has
drained. If a signal interrupts the close() or if the pro-
cess exits without closing the audio device, any remaining
data queued for audio output is flushed and the audio device
is closed immediately.
SunOS 5.11 Last change: 31 Dec 2001 5
Ioctl Requests mixer(7I)
The conversion of output data may be paused (or resumed) by
using the AUDIOSETINFO ioctl to set (or clear) the
play.pause flag in the audio information structure. Queued
output data may be discarded by using the IFLUSH STREAMS
ioctl. (See streamio(7I).)
Output data is played from the STREAMS buffers at a default
rate of 8000 bytes per second for ,u-Law, A-Law, or 8-bit PCM
data, or at a faster rate for 16-bit linear data or higher
sampling rates. If the output queue becomes empty, the
play.error flag is set in the audio information structure
and output is stopped until additional data is queued. If an
application attempts to write a number of bytes that is not
a multiple of the current sample frame size, an error is
generated and the bad data is thrown away. Additional writes
are allowed.
Asynchronous I/O
The ISETSIG STREAMS ioctl (see streamio(7I)) enables asyn-
chronous notification through the SIGPOL signal of input
and output ready conditions. The ONONBLOCK flag may be set
using the FSETFL fcntl(2) to enable non-blocking read() and
write() requests. This is normally sufficient for applica-
tions to maintain a background audio stream.
Audio Control Pseudo-Device
The /dev/audioctl pseudo-device enables an application to
modify characteristics of the audio device while it is being
used by an unrelated process. Any number of processes may
open the /dev/audioctl pseudo device simultaneously.
/dev/audioctl ignores read() and write() system calls.
Note -
The audio control device name is constructed by appending
the letters "ctl" to the path name of the audio device.
Audio Status Change Notification
Applications that open the audio control pseudo-device may
request asynchronous notification of changes in the state of
the audio device by setting the SMSG flag in an ISETSIG
STREAMS ioctl. (See streamio(7I)). Such processes receive a
SIGPOL signal when any of the following events occur:
o AUDIOSETINFO, AUDIOMIXERCTLSETINFO,
AUDIOMIXERCTLSETCHINFO, or
AUDIOMIXERCTLSETMODE ioctl () has altered the
device state.
o Input overflow or output underflow has occurred.
SunOS 5.11 Last change: 31 Dec 2001 6
Ioctl Requests mixer(7I)
o End-of-file record (zero-length buffer) has been
processed on output.
o open() or close() of /dev/audio has altered the
device state.
o An external event (such as speakerbox's volume con-
trol) has altered the device state.
IOCTLS
The audio mixer implements all the ioctl()s defined in
audio(7I) and uses the audioprinfot, audioinfot, and
audiodevicet structures. See the audio(7I) manual page for
details on these ioctl()s and structures. The audio mixer
also uses the data structures described below.
Audio Mixer Control Structure
The state of the audio device may be polled or modified
using the AUDIOMIXERCTLGETINFO and AUDIOMIXERCTLSETINFO
ioctl commands.
struct amcontrol {
audioinfot devinfo; /* the audio device's state */
int8t chopen[1]; /* variable sized array of */
/* of open channels */
};
typedef struct amcontrolt;
See CODE EXAMPLES for sample code on how to use this struc-
ture and the related macro
AUDIOMIXERCTLSTRUCTSIZE(numch).
Audio Mixer Sample Rates Structure
The following structure is used by the
AUDIOMIXERGETSAMPLERATES ioctl to get a list of all the
supported sample rates.
struct amsamplerates {
uintt type; /* play or capture */
uintt flags;
uintt numsamprates; /* number of elements */
/* in samprates[] */
uintt samprates[1]; /*variable sized array */
/* of sample rates */
};
typedef struct amsamplerates amsampleratest;
#define AUDIOPLAY 1 /* output */
#define AUDIORECORD 2 /* input */
SunOS 5.11 Last change: 31 Dec 2001 7
Ioctl Requests mixer(7I)
#define MIXERSRLIMITS 0x00000001/* sample rates */
/* set limits */
See CODE EXAMPLES for example code on how to use this
structure and the related macro
AUDIOMIXERSAMPRATESTRUCTSIZE(numsrs).
Audio Info Structure
When in mixer mode, the AMIXER bit in the audioinfot
structure's swfeaturesenabled field is set. When in compa-
tibility mode, that bit is clear.
The defines for the swfeatures and the swfeaturesenabled
fields are:
#define AMIXER 0x00000001 /* mixer is present/enabled */
Streamio IOCTLS
All streamio(7I) ioctl commands may be issued for the
/dev/audio and /dev/audioctl devices. ISETSIG ioctl may be
issued for /dev/audioctl to enable the notification of audio
status changes as described above.
Audio Mixer IOCTLS
Except for AUDIOMIXERGETSAMPLERATE,
AUDIOMIXERCTLGETMODE, and AUDIOMIXERCTLSETMODE, these
ioctl()s are valid only in mixer mode. Using them in compa-
tible mode returns an EINVAL error.
AUDIOMIXERMULTIPLEOPEN
This command allows an individual process to open
/dev/audio more than once for play or record. The argu-
ment is ignored. This feature is useful for mixing
panels that may control multiple audio streams.
AUDIOMIXERSINGLEOPEN
This command gets a list of supported sample rates for
either play or record for the audio mixer's current
mode. The argument is ignored. This command returns
/dev/audio back to an exclusive access device on per
process basis after an AUDIOMIXERMULTIPLEOPEN ioctl()
is executed. This ioctl() fails if the process has more
than one play or record stream open.
SunOS 5.11 Last change: 31 Dec 2001 8
Ioctl Requests mixer(7I)
AUDIOMIXERGETSAMPLERATES
This command retrieves sample rates. The argument is a
pointer to an amsamplesratest structure. It is legal
for the supported sample rates to be different for mixer
mode vs. compatible mode. The type field must be set to
either AUDIOPLAY or AUDIORECORD to get a list of
either play or record sample rates, respectively. Set-
ting to both or neither is an error. The numsamprates
field is set to the number of sample rates that the
samprates[] array may hold. When the ioctl returns,
numsamprates is set either to the number of sample
rates in the array samprates[], or the total number of
sample rates available if there are more than the array
can hold. In the former case, there are numsamprates
valid sample rates in the array. In the latter case, all
the elements of the array have valid sample rates, but
there are more available. The size of the array should
be increased to get all available sample rates. If the
flags field has the MIXERSRLIMITS flag set, the
returned sample rates are the lowest and the highest
rates possible, with all sample rates in-between being
legal. Some Codecs that have DSP engines on them have
this capability.
AUDIOMIXERCTLGETINFO
This command gets device and channel state information.
The argument is a pointer to an amcontrolt structure.
The devinfo field contains the state of the hardware
device. It provides a convenient way to determine the
hardware's state. The chopen array is used to specify
which channels are open and which are closed. Open chan-
nels have non-zero values, closed channels are set to
zero, The channel number corresponds to the array index.
The number of elements in the chopen array may change
over time and a macro is provided to allocate the
correct amount of space. The MACROS section below pro-
vides more information.
AUDIOMIXERCTLSETINFO
This command sets the device state but cannot modify any
channel's state. (Use AUDIOMIXERCTLSETCHINFO (below)
to modify a channel's state.) The argument is a pointer
to an amcontrolt structure. The devinfo field sets
the device state. The devinfo field is used to set the
device state. However, there are several limitations.
Only the gain, balance, port and pause fields for play
and record, monitorgain and outputmuted fields may be
SunOS 5.11 Last change: 31 Dec 2001 9
Ioctl Requests mixer(7I)
modified. (Modifying other fields would interfere with
how the audio mixer programs the audio device.) The
chopen array is not used when setting the audio device
and may be set to a size of one.
AUDIOMIXERCTLGETCHINFO
This command gets a channel's state information. The
argument is a pointer to an audiochannelt structure.
This command gets a channel's state information. To
enable the audio mixer to determine channel informa-
tion, set the chnumber field before making the ioctl()
call. The infosize field must be set to the size of the
audioinfot structure. The *info field must point to an
audioinfot structure. When the ioctl() returns, the
pid field should be checked. If it is set to 0, the
remaining data in the audiochannelt structure is
invalid because the channel has not been allocated. The
devtype field describes the type of channel; the *info
pointer points to a buffer where the audioinfot struc-
ture for the audio channel is populated.
AUDIOMIXERCTLSETCHINFO
This command sets a channel's state information. The
argument is a pointer to an audiochannelt structure.
Prior to issuing the ioctl call, specify the channel to
be set in the argument's chnumber field, set *info to
point to an audioinfot structure containing info used
to program the state of the channel, and set the
infosize field to the size of an audioinfot struc-
ture. When the ioctl() returns, the pid field contains
the process ID of the process that has the channel open,
and devtype contains the type of the device. If pid is
0 (zero), the channel is not open.
AUDIOMIXERCTLGETMODE
This command retrieves the mode of the audio mixer. The
argument is a pointer to an integer that contains the
audio mixer's mode upon return. It is set to either
AMIXERMODE for mixer mode or AMCOMPATMODE for com-
patible mode.
AUDIOMIXERCTLSETMODE
This command sets the mode of the audio mixer. The argu-
ment is a pointer to an integer that contains the audio
SunOS 5.11 Last change: 31 Dec 2001 10
Ioctl Requests mixer(7I)
mixer mode to be set. It must be set to either
AMIXERMODE or AMCOMPATMODE. The audio mixer may be
set to mixer mode at any time, but can only be set to
compatible mode when there is a single read/write open
within one process, or a single read process and a sin-
gle write process. Otherwise the ioctl() will fail.
Because the Codec is being reprogrammed to a different
data format, there may be brief pause or burst of noise
when the mode changes. This can be eliminated by pausing
the input and output or by closing all streams before
changing modes. The sdtaudiocontrol(1) or mixerctl(1)
commands may be used to change the audio mixer's mode.
MACROS
The following macro is used to determine how large an
amcontrolt structure is when it points to an audioinfot
structure.
AUDIOMIXERCTLSTRUCTSIZE(numch)
Where numch is the number of channels the device supports.
The number of channels can be determined using the
AUDIOGETNUMCHS ioctl().
This macro is used when allocating an amsampleratest
structure.
AUDIOMIXERSAMPRATESTRUCTSIZE(numsrs)
Where numsrs is the number of samples rates requested.
CODE EXAMPLES
The following examples illustrate how these new data struc-
tures and ioctls can be used.
Example 1
The following code demonstrates how to use the audio support
and the audio mixer ioctl()s to get state information on
/dev/audio.
audiochannelt ch;
audioinfot info;
amcontrolt *ctl;
int num;
err = ioctl(audiofd, AUDIOGETNUMCHS, &num);
SunOS 5.11 Last change: 31 Dec 2001 11
Ioctl Requests mixer(7I)
ctl = (amcontrolt *)malloc(AUDIOMIXERCTLSTRUCTSIZE(num));
err = ioctl(audiofd, AUDIOMIXERCTLGETINFO, ctl);
ch.info = &info;
ch.infosize = sizeof (audioinfot);
for (i = 0; i < num; i]) {
if (ctl->chopen[i] != 0) {
ch.chnumber = i;
if (ioctl(audiofd, AUDIOMIXERCTLGETCHINFO, &ch) < 0) {
printf("Channel # %d isn't an audio/audioctl device0, i);
} else {
printf("Ch# %d, PID = %d, Type = %d0,
i, ch.pid, ch.devtype);
}
}
}
Example 2
The following code demonstrates how to use the
AUDIOMIXERGETSAMPLERATES ioctl to get the number of sup-
ported play sample rates. It also shows how to deal with
allocating a samprates[] array that is too small.
#define LARGENUMBER 10000;
amsampleratest *sr;
int num;
for (num = 4; num < LARGENUMBER; num ]= 2) {
sr = (amsampleratest *)
malloc(AUDIOMIXERSAMPRATESTRUCTSIZE(num));
sr->numsamprates = num;
sr->type = AUDIOPLAY;
err = ioctl(audiofd, AUDIOMIXERGETSAMPLERATES, sr);
if (sr->numsamprates <= num) {
break;
}
free(sr);
}
(void) printf("Supported play sample rates:0);
for (i = 0; i < sr->numsamprates; i]) {
(void) printf(" %d0, sr->samprates[i]);
}
SunOS 5.11 Last change: 31 Dec 2001 12
Ioctl Requests mixer(7I)
ERORS
An open() fails if:
EBUSY The requested play or record access is busy and
either the ONDELAY or ONONBLOCK flag was set in
the open() request.
ENOMEM Memory was not available to be allocated for the
channel.
EINTR The requested play or record access is busy and a
signal interrupted the open() request.
EIO There has been an error opening the device. An
error message is printed on the console explain-
ing the failure.
An ioctl() will fail if:
EBUSY The parameter changes requested in the
AUDIOSETINFO ioctl could not be made because
another process has the device open and is using
a different format.
EINTR The ioctl() was interrupted by a signal.
EINVAL The parameter changes requested in the
AUDIOSETINFO ioctl are invalid or are not sup-
ported by the device, or the audio mixer is in
compatible mode and a mixer-mode-only audio mixer
ioctl was issued.
EIO There has been an error with the ioctl(). An
error message is printed on the console explain-
ing the failure.
ENOMEM The ioctl() failed because memory couldn't be
allocated.
FILES
The physical audio device names are system dependent and are
rarely used by programmers. The programmer should use the
SunOS 5.11 Last change: 31 Dec 2001 13
Ioctl Requests mixer(7I)
generic device names listed below.
/dev/audio symbolic link to the system's primary
audio device
/dev/audioctl symbolic link to the control device for
/dev/audio
/dev/sound/0 first audio device in the system
/dev/sound/0ctl audio control device for /dev/sound/0
/dev/sound/x additional audio devices
/dev/sound/xctl audio control device for /dev/sound/x
ATRIBUTES
See attributes(5) for a description of the following attri-
butes:
ATRIBUTE TYPE ATRIBUTE VALUE
Architecture SPARC, x86
Availability SUNWaudd, SUNWauddx, SUNWaudh, SUNWauda
Stability Level Evolving
SEE ALSO
mixerctl(1), sdtaudiocontrol(1), close(2), fcntl(2),
ioctl(2), open(2), poll(2), read(2), write(2), attri-
butes(5), audiocs(7D), audioens(7D), audiots(7D),
usbac(7D), audio(7I), audiosupport(7I), streamio(7I)
BUGS
Due to a feature of the STREAMS implementation, programs
that are terminated or exit without closing the audio device
may hang for a short period while audio output drains. In
general, programs that produce audio output should catch the
SIGINT signal and flush the output stream before exiting.
SunOS 5.11 Last change: 31 Dec 2001 14
|