mixer - audio mixer audio personality module interface
#include <sys/mixer.h>
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.
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.
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 interfaces remain the same and applications cannot distinguish between multi-stream Codec and traditional Codec.
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 captured by the audio driver, buffer size bytes are sent to the application for reading.
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.
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 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 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 AUDIO_SETINFO ioctl(2) fails.
When /dev/audio is opened, initial encoding and precision is 8-bit µ-Law (as in the Greek letter mu) . (As defined in audio(7I)
In mixer mode, the audio mixer supports formats in the following precisions:
|
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 precisions, the AUDIO_SETINFO ioctl(2) call fails.
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 different number of play and record channels, the AUDIO_SETINFO ioctl(2) call fails.
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.
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:
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 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.
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 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 initialization.
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 interrupts 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.
The I_SETSIG STREAMS ioctl (see streamio(7I)) enables asynchronous notification through the SIGPOLL signal of input and output ready conditions. The O_NONBLOCK flag may be set using the F_SETFL fcntl(2) to enable non-blocking read() and write() requests. This is normally sufficient for applications to maintain a background audio stream.
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 -
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:
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 structures. The audio mixer also uses the data structures described below.
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).
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).
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 */
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.
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
AUDIO_MIXER_SINGLE_OPEN
AUDIO_MIXER_GET_SAMPLE_RATES
AUDIO_MIXERCTL_GETINFO
AUDIO_MIXERCTL_SETINFO
AUDIO_MIXERCTL_GET_CHINFO
AUDIO_MIXERCTL_SET_CHINFO
AUDIO_MIXERCTL_GET_MODE
AUDIO_MIXERCTL_SET_MODE
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.
The following examples illustrate how these new data structures and ioctls can be used.
The following code demonstrates how to use the audio support and the audio mixer ioctl()s 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 device, i); } else { printf("Ch# %d, PID = %d, Type = %d, i, ch.pid, ch.dev_type); } } }
The following code demonstrates how to use the AUDIO_MIXER_GET_SAMPLE_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:); for (i = 0; i < sr->num_samp_rates; i++) { (void) printf(" %d, sr->samp_rates[i]); }
An open() fails if:
EBUSY
ENOMEM
EINTR
EIO
An ioctl() will fail if:
EBUSY
EINTR
EINVAL
EIO
ENOMEM
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
/dev/audioctl
/dev/sound/0
/dev/sound/0ctl
/dev/sound/x
/dev/sound/xctl
See attributes(5) for a description of the following attributes:
|
mixerctl(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)
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.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |