up | Inhaltsverzeichniss | Kommentar

Manual page for AUDIO(4)

audio - telephone quality audio device

CONFIG -- SUN-4c, SUN-4m SYSTEMS

device-driver audio

DESCRIPTION

The audio device plays and records a single channel of sound using the AM79C30A Digital Subscriber Controller chip. The chip has a built-in analog-to-digital converter (ADC) and digital-to-analog converter (DAC) that can drive either the built-in speaker or an external headphone jack, selectable under software control. Digital audio data is sampled at a rate of 8000 samples per second with 12-bit precision, though the data is compressed, using u-law encoding, to 8-bit samples. The resulting audio data quality is equivalent to that of standard telephone service.

The audio driver is implemented as a STREAMS device. In order to record audio input, applications open.2v the /dev/audio device and read data from it using the read.2v system call. Similarly, sound data is queued to the audio output port by using the write.2v system call.

Opening the Audio Device

The audio device is treated as an exclusive resource: only one process may typically open the device at a time. However, two processes may simultaneously access the device if one opens it read-only and the other opens it write-only.

When a process cannot open /dev/audio because the requested access mode is busy:

Since the audio device grants exclusive read or write access to a single process at a time, long-lived audio applications may choose to close the device when they enter an idle state, reopening it when required. The play.waiting and record.waiting flags in the audio information structure (see below) provide an indication that another process has requested access to the device. This information is advisory only; background audio output processes, for example, may choose to relinquish the audio device whenever another process requests write access.

Recording Audio Data

The read() system call copies data from the system buffers to the application. Ordinarily, read() blocks until the user buffer is filled. The FIONREAD ioctl (see filio.4 may be used to determine the amount of data that may be read without blocking. The device may alternatively be set to a non-blocking mode, in which case read() completes immediately, but may return fewer bytes than requested. Refer to the read.2v 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. Since 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 below). All unread input data in the STREAMS queue may be discarded by using the I_FLUSH STREAMS ioctl (see streamio.4

Input data accumulates in STREAMS buffers at a rate of 8000 bytes per second. If the application that consumes the data cannot keep up with this data rate, the STREAMS queue may become full. When this occurs, the record.error flag is set in the audio information structure and input sampling ceases until there is room in the input queue for additional data. In such cases, the input data stream contains a discontinuity. For this reason, audio recording applications should open the audio device when they are prepared to begin reading data, rather than at the start of extensive initialization.

Playing Audio Data

The write() system call copies data from an applications 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 have transferred fewer bytes than requested (see write.2v

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() of the file descriptor hangs until audio output has drained. If a signal interrupts the close() , or if the process exits without closing the device, any remaining data queued for audio output is flushed and the 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.

Output data is played from the STREAMS buffers at a rate of 8000 bytes per second. If the output queue becomes empty, the play.error flag is set in the audio information structure and output ceases until additional data is written.

Asynchronous I/O

The I_SETSIG STREAMS ioctl may be used to enable asynchronous notification, via the SIGPOLL signal, of input and output ready conditions. This, in conjunction with non-blocking read() and write() requests, is normally sufficient for applications to maintain an audio stream in the background. Alternatively, asynchronous reads and writes may be initiated using the aioread.3 functions.

Audio Data Encoding

The data samples processed by the audio device are encoded in 8 bits. The high-order bit is a sign bit: 1 represents positive data and 0 represents negative data. The low-order 7 bits represent signal magnitude and are inverted (1's complement). The magnitude is encoded according to a u-law transfer function; such an encoding provides an improved signal-to-noise ratio at low amplitude levels. In order to achieve best results, the audio recording gain should be set so that typical amplitude levels lie within approximately three-fourths of the full dynamic range.

Audio Control Pseudo-Device

It is sometimes convenient to have an application, such as a volume control panel, modify certain characteristics of the audio device while it is being used by an unrelated process. The /dev/audioctl minor device is provided for this purpose. Any number of processes may open /dev/audioctl simultaneously. However, read() and write() system calls are ignored by /dev/audioctl. The AUDIO_GETINFO and AUDIO_SETINFO ioctl commands may be issued to /dev/audioctl in order to determine the status or alter the behavior of /dev/audio.

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. Such processes receive a SIGPOLL signal when any of the following events occurs:


Audio Information Structure

The state of the audio device may be polled or modified using the AUDIO_GETINFO and AUDIO_SETINFO ioctl commands. These commands operate on the audio_info structure, defined in <sun/audioio.h> as follows:

/* Data encoding values, used below in the encoding field */
#define AUDIO_ENCODING_ULAW	(1)	/* u-law encoding */
#define AUDIO_ENCODING_ALAW	(2)	/* A-law encoding */

/* These ranges apply to record, play, and monitor gain values */
#define AUDIO_MIN_GAIN	(0)		/* minimum gain value */
#define AUDIO_MAX_GAIN	(255)		/* maximum gain value */

/* Audio I/O channel status, used below in the audio_info structure */
struct audio_prinfo {
	/* The following values describe the audio data encoding */
	unsigned			sample_rate;	/* samples per second */
	unsigned			channels;	/* number of interleaved channels */
	unsigned			precision;	/* number of bits per sample */
	unsigned		  	encoding;	/* data encoding method */

	/* The following values control audio device configuration */
	unsigned			gain;		/* gain level */
	unsigned			port;		/* selected I/O port */

	/* The following values describe the current device state */
	unsigned			samples;		/* number of samples converted */
	unsigned			eof;		/* End Of File counter (play only) */
	unsigned char		pause;		/* non-zero if paused, zero to resume */
	unsigned char		error;		/* non-zero if overflow/underflow */
	unsigned char		waiting;		/* non-zero if a process wants access */

	/* The following values are read-only device state flags */
	unsigned char		open;		/* non-zero if open access granted */
	unsigned char		active;		/* non-zero if I/O active */
};

/* This structure is used in AUDIO_GETINFO and AUDIO_SETINFO ioctl commands */
typedef struct audio_info {
	struct audio_prinfo	record;		/* input status information */
	struct audio_prinfo	play;		/* output status information */
	unsigned			monitor_gain;	/* input to output mix */
}  audio_info_t;

The play.gain and record.gain fields specify the output and input volume levels. A value of AUDIO_MAX_GAIN indicates maximum gain. The device also allows input data to be monitored by mixing audio input onto the output channel. The monitor_gain field controls the level of this feedback path. The play.port field controls the output path for the audio device. It may be set to either AUDIO_SPEAKER or AUDIO_HEADPHONE to direct output to the built-in speaker or the headphone jack, respectively.

The play.pause and record.pause flags may be used to pause and resume the transfer of data between the audio device and the STREAMS buffers. The play.error and record.error flags indicate that data underflow or overflow has occurred. The play.active and record.active flags indicate that data transfer is currently active in the corresponding direction.

The play.open and record.open flags indicate that the device is currently open with the corresponding access permission. The play.waiting and record.waiting flags provide an indication that a process may be waiting to access the device. These flags are set automatically when a process blocks on open(), though they may also be set using the AUDIO_SETINFO ioctl command. They are cleared only when a process relinquishes access by closing the device.

The play.samples and record.samples fields are initialized, at open(), to zero and increment each time a data sample is copied to or from the associated STREAMS queue. Applications that keep track of the number of samples read or written may use these fields to determine exactly how many samples remain in the STREAMS buffers. The play.eof field increments whenever a zero-length output buffer is synchronously processed. Applications may use this field to detect the completion of particular segments of audio output.

The sample_rate, channels, precision, and encoding fields report the audio data format in use by the device. For now, these values are read-only; however, future audio device implementations may support more than one data encoding format, in which case applications might be able to modify these fields.

Filio and STREAMS IOCTLS

All of the filio.4 and streamio.4 ioctl commands may be issued for the /dev/audio device. Because the /dev/audioctl device has its own STREAMS queues, most of these commands neither modify nor report the state of /dev/audio if issued for the /dev/audioctl device. The I_SETSIG ioctl may be issued for /dev/audioctl to enable the notification of audio status changes, as described above.

Audio IOCTLS

The audio device additionally supports the following ioctl commands:

AUDIO_DRAIN
The argument is ignored. This command suspends the calling process until the output STREAMS queue is empty, or until a signal is delivered to the calling process. It may only be issued for the /dev/audio device. An implicit AUDIO_DRAIN is performed on the final close() of /dev/audio.
AUDIO_GETINFO
The argument is a pointer to an audio_info structure. This command may be issued for either /dev/audio or /dev/audioctl. The current state of the /dev/audio device is returned in the structure.
AUDIO_SETINFO
The argument is a pointer to an audio_info structure. This command may be issued for either /dev/audio or /dev/audioctl. This command configures the audio device according to the structure supplied and overwrites the structure with the new state of the device. [Note: The play.samples, record.samples, play.error, record.error, and play.eof fields are modified to reflect the state of the device when the AUDIO_SETINFO was issued. This allows programs to atomically modify these fields while retrieving the previous value.]

Certain fields in the information structure, such as the pause flags, are treated as read-only when /dev/audio is not open with the corresponding access permission. Other fields, such as the gain levels and encoding information, may have a restricted set of acceptable values. Applications that attempt to modify such fields should check the returned values to be sure that the corresponding change took effect.

Once set, the following values persist through subsequent open() and close() calls of the device: play.gain, record.gain, monitor_gain, play.port, and record.port. All other state is reset when the corresponding I/O stream of /dev/audio is closed.

The audio_info structure may be initialized through the use of the AUDIO_INITINFO macro. This macro sets all fields in the structure to values that are ignored by the AUDIO_SETINFO command. For instance, the following code switches the output port from the built-in speaker to the headphone jack without modifying any other audio parameters:

audio_info_t	info;

AUDIO_INITINFO(&info);
info.play.port = AUDIO_HEADPHONE;
err = ioctl(audio_fd, AUDIO_SETINFO, &info);

This technique is preferred over using a sequence of AUDIO_GETINFO followed by AUDIO_SETINFO.

Unsupported Device Control Features

The AM79C30A chip is capable of performing a number of functions that are not currently supported by the device driver, many of which were designed primarily for telephony applications. For example, the chip can generate ringer tones and has a number of specialized filtering capabilities that are designed to compensate for different types of external speakers and microphones.

Ordinarily, applications do not need to access these capabilities and, further, altering the chip's characteristics may interfere with its normal behavior. However, knowledgeable applications may use the unsupported AUDIOGETREG and AUDIOSETREG ioctl commands to read and write the chip registers directly. The description of this interface may be found in <sbusdev/audio_79C30.h>. Note: these commands are supplied for prototyping purposes only and may become obsolete in a future release of the audio driver.

FILES

/dev/audio
/dev/audioctl
/usr/demo/SOUND

SEE ALSO

ioctl.2 poll.2 read.2v write.2v aioread.3 filio.4 streamio.4

AMD data sheet for the AM79C30A Digital Subscriber Controller, Publication number 09893.

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.

The current driver implementation does not support the A-law encoding mode of the AM79C30A chip. Future implementations may permit the AUDIO_SETINFO ioctl to modify the play.encoding and record.encoding fields of the device information structure to enable this mode.

FUTURE DIRECTIONS

Workstation audio resources should be managed by a networked audio server, in the same way that the video monitor is manipulated by a window system server. For the time being, we encourage you to write your programs in a modular fashion, isolating the audio device-specific functions, so that they may be easily ported to such an environment.


index | Inhaltsverzeichniss | Kommentar

Created by unroff & hp-tools. © by Hans-Peter Bischof. All Rights Reserved (1997).

Last modified 21/April/97