mixer(7I) Ioctl Requests mixer(7I)NAMEmixer - audio mixer audio personality module interface
SYNOPSIS
#include <sys/mixer.h>
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 interface.
Backward Compatibility
It is possible to disable the mixing function and return to 100% back‐
ward 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 provide 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 inter‐
faces remain the same and applications cannot distinguish between
multi-stream Codec and traditional 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 changing 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 cap‐
tured by the audio driver, buffer size bytes are sent to the applica‐
tion 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 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 fil‐
tering. The result is that high sample rate audio streams are not
degraded by filtering.
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, converting 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. Applications 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 sam‐
pling.
In compatible mode, the audio mixer programs the Codec to the sample
rate set by the application to avoid incurring any sample rate conver‐
sion overhead. If the Codec cannot support different play and record
sample rates, the AUDIO_SETINFO ioctl(2) fails.
Encodings and Precision
When /dev/audio is opened, initial encoding and precision is 8-bit
μ-Law (as in the Greek letter mu) . This is defined in audio(7I).
In mixer mode, the audio mixer supports formats in the following preci‐
sions:
┌──────────────────────────────────────────────────────────────┐
│Encoding Precision Channels │
│Signed Linear PCM 16-bit Mono or Stereo │
│Signed Linear PCM 8-bit Mono or Stereo │
│μ-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 dif‐
ferent play and record encodings or precisions, the AUDIO_SETINFO
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) channel 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 cannot support a differ‐
ent number of play and record channels, the AUDIO_SETINFO ioctl(2)
call fails.
DESCRIPTION
The device /dev/audio is a device driver that dispatches audio requests
to the appropriate underlying audio personality 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 configuration 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 once unless the
process has made an AUDIO_MIXER_MULTIPLE_OPEN 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 O_NDELAY or O_NONBLOCK flags are set in the
open() oflag argument, -1 is immediately returned, with
errno set to EBUSY.
o if neither the O_NDELAY nor the O_NONBLOCK 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 μ-Law data. If the audio device does not support this configura‐
tion, 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 con‐
figuration. 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 I_NREAD 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 (O_WRONLY).
The transfer of input data to STREAMS buffers may be paused (or
resumed) by using the AUDIO_SETINFO ioctl to set (or clear) the
record.pause flag in the audio information structure. (See audio(7I).)
All unread input data in the STREAMS queue may be discarded by using
the I_FLUSH 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 μ-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 struc‐
ture 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 initialization.
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 device 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 considerably longer. The
AUDIO_DRAIN 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 inter‐
rupts the close() or if the process exits without closing the audio
device, any remaining data queued for audio output is flushed and the
audio device is closed immediately.
The conversion of output data may be paused (or resumed) by using the
AUDIO_SETINFO ioctl to set (or clear) the play.pause flag in the audio
information structure. Queued output data may be discarded by using the
I_FLUSH STREAMS ioctl. (See streamio(7I).)
Output data is played from the STREAMS buffers at a default rate of
8000 bytes per second for μ-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 I_SETSIG STREAMS ioctl (see streamio(7I)) enables asynchronous
notification through the SIGPOLL signal of input and output ready con‐
ditions. The O_NONBLOCK flag may be set using the F_SETFL fcntl(2) to
enable non-blocking read() and write() requests. This is normally suf‐
ficient for applications to maintain a background audio stream.
Audio Control Pseudo-Device
The /dev/audioctl pseudo-device enables an application to modify char‐
acteristics 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.
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 S_MSG flag in an I_SETSIG STREAMS ioctl. (See
streamio(7I)). Such processes receive a SIGPOLL signal when any of the
following events occur:
o AUDIO_SETINFO, AUDIO_MIXERCTL_SETINFO, AUDIO_MIX‐
ERCTL_SET_CHINFO, or AUDIO_MIXERCTL_SET_MODE ioctl () has
altered the device state.
o Input overflow or output underflow has occurred.
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 control) has
altered the device state.
IOCTLS
The audio mixer implements all the ioctl()s defined in audio(7I) and
uses the audio_prinfo_t, audio_info_t, and audio_device_t structures.
See the audio(7I) manual page for details on these ioctl()s and struc‐
tures. 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
AUDIO_MIXERCTL_GETINFO and AUDIO_MIXERCTL_SETINFO ioctl commands.
struct am_control {
audio_info_t dev_info; /* the audio device's state */
int8_t ch_open[1]; /* variable sized array of */
/* of open channels */
};
typedef struct am_control_t;
See CODE EXAMPLES for sample code on how to use this structure and the
related macro AUDIO_MIXER_CTL_STRUCT_SIZE(num_ch).
Audio Mixer Sample Rates Structure
The following structure is used by the AUDIO_MIXER_GET_SAMPLE_RATES
ioctl to get a list of all the supported sample rates.
struct am_sample_rates {
uint_t type; /* play or capture */
uint_t flags;
uint_t num_samp_rates; /* number of elements */
/* in samp_rates[] */
uint_t samp_rates[1]; /*variable sized array */
/* of sample rates */
};
typedef struct am_sample_rates am_sample_rates_t;
#define AUDIO_PLAY 1 /* output */
#define AUDIO_RECORD 2 /* input */
#define MIXER_SR_LIMITS 0x00000001/* sample rates */
/* set limits */
See CODE EXAMPLES for example code on how to use this structure and
the related macro AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num_srs).
Audio Info Structure
When in mixer mode, the AM_MIXER bit in the audio_info_t structure's
sw_features_enabled field is set. When in compatibility mode, that bit
is clear.
The defines for the sw_features and the sw_features_enabled fields are:
#define AM_MIXER 0x00000001 /* mixer is present/enabled */
Streamio IOCTLS
All streamio(7I) ioctl commands may be issued for the /dev/audio and
/dev/audioctl devices. I_SETSIG ioctl may be issued for /dev/audioctl
to enable the notification of audio status changes as described above.
Audio Mixer IOCTLS
Except for AUDIO_MIXER_GET_SAMPLE_RATE, AUDIO_MIXERCTL_GET_MODE, and
AUDIO_MIXERCTL_SET_MODE, these ioctl()s are valid only in mixer mode.
Using them in compatible mode returns an EINVAL error.
AUDIO_MIXER_MULTIPLE_OPEN
This command allows an individual process to open /dev/audio more
than once for play or record. The argument is ignored. This feature
is useful for mixing panels that may control multiple audio
streams.
AUDIO_MIXER_SINGLE_OPEN
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 AUDIO_MIXER_MULTI‐
PLE_OPEN ioctl() is executed. This ioctl() fails if the process
has more than one play or record stream open.
AUDIO_MIXER_GET_SAMPLE_RATES
This command retrieves sample rates. The argument is a pointer to
an am_samples_rates_t structure. It is legal for the supported sam‐
ple rates to be different for mixer mode vs. compatible mode. The
type field must be set to either AUDIO_PLAY or AUDIO_RECORD to get
a list of either play or record sample rates, respectively. Setting
to both or neither is an error. The num_samp_rates field is set to
the number of sample rates that the samp_rates[] array may hold.
When the ioctl returns, num_samp_rates is set either to the number
of sample rates in the array samp_rates[], or the total number of
sample rates available if there are more than the array can hold.
In the former case, there are num_samp_rates 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 MIXER_SR_LIMITS flag set, the returned sample
rates are the lowest and the highest rates possible, with all sam‐
ple rates in-between being legal. Some Codecs that have DSP engines
on them have this capability.
AUDIO_MIXERCTL_GETINFO
This command gets device and channel state information. The argu‐
ment is a pointer to an am_control_t structure. The dev_info field
contains the state of the hardware device. It provides a convenient
way to determine the hardware's state. The ch_open array is used to
specify which channels are open and which are closed. Open channels
have non-zero values, closed channels are set to zero, The channel
number corresponds to the array index. The number of elements in
the ch_open 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.
AUDIO_MIXERCTL_SETINFO
This command sets the device state but cannot modify any channel's
state. Use AUDIO_MIXERCTL_SET_CHINFO (below) to modify a channel's
state. The argument is a pointer to an am_control_t structure. The
dev_info field sets the device state. The dev_info 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, moni‐
tor_gain and output_muted fields may be modified. (Modifying other
fields would interfere with how the audio mixer programs the audio
device.) The ch_open array is not used when setting the audio
device and may be set to a size of one.
AUDIO_MIXERCTL_GET_CHINFO
This command gets a channel's state information. The argument is a
pointer to an audio_channel_t structure. This command gets a chan‐
nel's state information. To enable the audio mixer to determine
channel information, set the ch_number field before making the
ioctl() call. The info_size field must be set to the size of the
audio_info_t structure. The *info field must point to an
audio_info_t structure. When the ioctl() returns, the pid field
should be checked. If it is set to 0, the remaining data in the
audio_channel_t structure is invalid because the channel has not
been allocated. The dev_type field describes the type of channel;
the *info pointer points to a buffer where the audio_info_t struc‐
ture for the audio channel is populated.
AUDIO_MIXERCTL_SET_CHINFO
This command sets a channel's state information. The argument is a
pointer to an audio_channel_t structure. Prior to issuing the ioctl
call, specify the channel to be set in the argument's ch_number
field, set *info to point to an audio_info_t structure containing
info used to program the state of the channel, and set the
info_size field to the size of an audio_info_t structure. When
the ioctl() returns, the pid field contains the process ID of the
process that has the channel open, and dev_type contains the type
of the device. If pid is 0 (zero), the channel is not open.
AUDIO_MIXERCTL_GET_MODE
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 AM_MIXER_MODE for mixer mode or AM_COM‐
PAT_MODE for compatible mode.
AUDIO_MIXERCTL_SET_MODE
This command sets the mode of the audio mixer. The argument is a
pointer to an integer that contains the audio mixer mode to be set.
It must be set to either AM_MIXER_MODE or AM_COMPAT_MODE. 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 single 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 elimi‐
nated by pausing the input and output or by closing all streams
before changing modes. The sdtaudiocontrol(1) or mixerctl(1) com‐
mands may be used to change the audio mixer's mode.
MACROS
The following macro is used to determine how large an am_control_t
structure is when it points to an audio_info_t structure.
AUDIO_MIXER_CTL_STRUCT_SIZE(num_ch)
Where num_ch is the number of channels the device supports. The number
of channels can be determined using the AUDIO_GET_NUM_CHS ioctl().
This macro is used when allocating an am_sample_rates_t structure.
AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num_srs)
Where num_srs is the number of samples rates requested.
EXAMPLES
The following examples illustrate how these new data structures and
ioctls can be used.
Example 1 Using Audio Support and Ioctls
The following code demonstrates how to use the audio support and the
audio mixer ioctls to get state information on /dev/audio.
audio_channel_t ch;
audio_info_t info;
am_control_t *ctl;
int num;
err = ioctl(audio_fd, AUDIO_GET_NUM_CHS, &num);
ctl = (am_control_t *)malloc(AUDIO_MIXER_CTL_STRUCT_SIZE(num));
err = ioctl(audio_fd, AUDIO_MIXERCTL_GETINFO, ctl);
ch.info = &info;
ch.info_size = sizeof (audio_info_t);
for (i = 0; i < num; i++) {
if (ctl->ch_open[i] != 0) {
ch.ch_number = i;
if (ioctl(audio_fd, AUDIO_MIXERCTL_GET_CHINFO, &ch) < 0) {
printf("Channel # %d isn't an audio/audioctl device0, i);
} else {
printf("Ch# %d, PID = %d, Type = %d0,
i, ch.pid, ch.dev_type);
}
}
}
Example 2 Using the AUDIO_MIXER_GET_SAMPLE_RATES ioctl
The following code demonstrates how to use the AUDIO_MIXER_GET_SAM‐
PLE_RATES ioctl to get the number of supported play sample rates. It
also shows how to deal with allocating a samp_rates[] array that is too
small.
#define LARGE_NUMBER 10000;
am_sample_rates_t *sr;
int num;
for (num = 4; num < LARGE_NUMBER; num += 2) {
sr = (am_sample_rates_t *)
malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num));
sr->num_samp_rates = num;
sr->type = AUDIO_PLAY;
err = ioctl(audio_fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
if (sr->num_samp_rates <= num) {
break;
}
free(sr);
}
(void) printf("Supported play sample rates:0);
for (i = 0; i < sr->num_samp_rates; i++) {
(void) printf(" %d0, sr->samp_rates[i]);
}
ERRORS
An open() fails if:
EBUSY The requested play or record access is busy and either the
O_NDELAY or O_NONBLOCK 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 explaining the failure.
An ioctl() will fail if:
EBUSY The parameter changes requested in the AUDIO_SETINFO 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 AUDIO_SETINFO ioctl
are invalid or are not supported 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 explaining 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 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
ATTRIBUTES
See attributes(5) for a description of the following attributes:
┌───────────────────┬─────────────────────────────────────────┐
│ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
├───────────────────┼─────────────────────────────────────────┤
│Architecture │ SPARC, x86 │
├───────────────────┼─────────────────────────────────────────┤
│Availability │ SUNWaudd, SUNWauddx, SUNWaudh, SUNWauda │
├───────────────────┼─────────────────────────────────────────┤
│Stability Level │ Evolving │
└───────────────────┴─────────────────────────────────────────┘
SEE ALSOmixerctl(1), sdtaudiocontrol(1), close(2), fcntl(2), ioctl(2), open(2),
poll(2), read(2), write(2), attributes(5), audiocs(7D), audioens(7D),
audiots(7D), usb_ac(7D), audio(7I), audio_support(7I), streamio(7I)BUGS
Due to a feature of the STREAMS implementation, programs that are ter‐
minated 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.10 16 May 2011 mixer(7I)