Open Sound System
The Hitchhiker's Guide to OSS 4.1 Internals

Do you have problems with sound/audio application development? Don't panic! Click here for help!


Audio engine/device descriptor structure


The adev_t structure is the key foundation of the OSS digital audio subsystem. It defines the parameters required by the audio core to communicate with the low level drivers. Among others it contains a pointer to audiodrv_t structure (the d field) that defines the driver methods/callbacks. In addition it has pointers to the two dmap_t structures (dmap_out and dmap_in) that contain the DMA buffer parameters for playback and recording.

Audio engines and audio device files

OSS v4 uses two level audio device organization. The lowest level is the audio engines. An audio engine is the part of a sound card that can play and/or record single independent audio stream. Recent OSS drivers implement only unidirectional audio engines (input or output) but many earlier drivers use convention where the same engine is used for both directions (has both dmap_out and dmap_in structures).

An audio engine is created when the low level driver calls oss_install_audiodev. Audio engines themselves are hidden from the applications but the ossinfo command can show them (ossinfo -e or ossinfo -a -v[1|2|3]). Audio engines are defined in the global audio_engines[] table and the num_audio_engines variable contains the number of (currently) available engines.

The second level of audio devices are audio device files which are defined in the audio_devfiles[]/num_audio_devfiles table. Each audio device file will have a device node created in /dev and applications can open them. Each audio_devfiles[] entry is a pointer to one entry in the audio_engines[] table.

By default oss_install_audiodev will add the new audio engine to both of these tables. Applications will see the device (in the /dev directory). However the indexes in these tables are likely to be different.

This two level scheme is used to support devices that have multiple fully identical audio engines (like sblive). In such cases the driver can create subsequent engines with the ADEV_SHADOW flag. Now oss_install_audiodev() will no longer add the engines to the audio_devfiles[] table or to create any device node under the /dev directory.

When an audio device file with multiple engines is opened the audio core will first try if the audio engine pointed by the audio_devfiles[dev] entry is available. If this fisr engine is busy it will try the subsequent engines (pointed by the next field) until it finds a free one. Only the first engine is defined in audio_devfiles[] but the shadow engines can be found by following the chain.

OSS audio drivers and the audio core normally uses only the audio_engines[] table. The audio_devfiles[] table is only used in some special cases when a device needs to be located using it's device file number (device index). Programmers developing virtual drivers that use services of other drivers (like vmix) should be very carefull about using the right table. Developers of normal OSS drivers can forget that the audio_devfiles[] table exists and to use only audio_engines[]).

Some operating systems (currently FreeBSD) don't support this scheme and this cases both tables (audio_devfiles and audio_engines) will always be identical.

Fields of the adev_t structure

of this audio engine. Reserved for internal use of the audio core.}
char name[64] Name of the audio devices (see oss_install_audiodev).
char handle[32] See the description of the handle field returned by SNDCTL_AUDIOINFO.
int engine_num Audio engine number. This field is an index to the audio_engines[]) table.
int audio_devfile Audio device file number. This field is an index to the audio_devfiles[] table. Note that several engines in audio_devfiles[] may share the same device file number. This field is reserved for internal use by OSS.
int enabled The device is not enabled for the time being if this field is not zero. For example an hot-pluggable device has been unplugged.
int unloaded Non-zero value means that the driver for this device has been detached.
struct _adev_t *next_in This field is used as a link to the "shadow" input devices of this audio engine. The oss_audio_open_devfile routine uses this field to find alternative device(s) if this one is busy.
struct _adev_t *next_out Like next_in but for playback devices.
int flags Audio device flags. See the Audio device flags section for more info.
int open_flags Application specific open flags (see below).
int src_quality Quality parameter used when doing sofrware based sample rate conversions (see include/grc3.h for more info. This field is initialized to the global src_quality configuration value just before the adrv_open entry point is called. The driver may change this field after that. Next open will reset it back to the default value.
int caps Audio device capabilities. See the Audio device capabilities section for more info. Usually this field is 0 but the driver can use it to force certain capability bits to be reported to the application using the device.
int magic Reserved for 4Front Technologies.
int latency Reserved for future use.
sample_parms user_parms Sample format info for the application side.
sample_parms hw_parms Like user_parms but for the device side. In general these fields point to the same format descriptor. However they will point to different descriptors when automatic sample format conversions are active.
int iformat_mask Sample format mask for input direction (see below).
int oformat_mask Sample format mask for output direction (see below).
int xformat_mask Sample format mask for simultaneous input and output (see below).
int min_rate Minimum sampling rate supported by the device. The driver should initialize this value after installing the device.
int max_rate Like min_rate buf for the maximum sampling rate.
int min_channels Smallest number of channels supported by the device (usually 2).
int max_channels Largest number of channels supported by the device.
char *inch_names Multi channel (professional) devices can define names for each input stereo pair by using this field (string). Channel-pair names are separated by spaces.
char *outch_names Like inch_names but for output channel pairs.
int binding Reserved.
void *devc Driver defined pointer (see below).
audiodrv_t *d Pointer to the driver method callback table. See audiodrv_t for more info.
void *portc Driver defined pointer (see below).
void *portc_play Driver defined pointer (see below).
void *portc_record Driver defined pointer (see below).
dmap_t *dmap_out Pointer to the DMA buffer descriptor record(dmap_t) for playback direction.
dmap_t *dmap_in Like dmap_out but for recording.
int mixer_dev Mixer device number that is associated with this audio engine (-1 means no mixer). Traditionally OSS audio derivers set this field to point to the mixer device for this device.
int open_mode Current open mode (OPEN_READ|OPEN_WRITE
int go Normally set to 1. Value of zero means that the device has some wait operation pending. Related with the SNDCTL_DSP_SYNCGROUP and SNDCTL_DSP_SYNCSTART ioctl calls.
int enable_bits Control variable used by handling of SNDCTL_DSP_SETTRIGGER ioctl call. Reserved for the audio core.
int parent_dev This field is not used for the time being.
int max_block Maximum fragment size (in bytes) supported by the audio engine.
int min_block Minimum fragment size (in bytes) supported by the audio engine.
int min_fragments Minimum number of fragments required by the device.
int max_fragments Maximum number of fragments supported by the device.
int max_intrate Maximum interrupt rate (interrupts/sec) supported by the device. By default this field will be initialized to the value defined by the max_intrate parameter (see the osscore module). The driver can set this field if the device has problems with too frequent interrupts. By default OSS will limit number of interrupts to 100 intr/sec.
int dmabuf_alloc_flags Flags that affect the way how the DMA buffer is allocated for this device. See the "DMA Buffer allocation flags" section (below).
oss_uint64_t dmabuf_maxaddr Maximum DMA buffer address supported by the device. See the "DMA Buffer allocation flags" section (below).
int fixed_rate Devices that use the ADEV_FIXEDRATE flag need to initialize this field to the supported sampling rate. In this way the audio core can initialize the device to the correct sampling rate when the device is being opened (this happens immediately after the adrv_open entry has been called.
int vmix_flags Flags that control the vmix engine (see below).
pid_t pid This field will be initialized by oss_audio_open_engine to the PID of the application that opened the device. Some virtual drivers may need to set the pid to 0 to tell that the device is being used by a virtual driver. However this should be done only if multiple applications can share the same "master" device.
char cmd[16] Like pid but contains the name of the application using the device. Virtual drivers using this device as their master device should set this field to the name of the driver if multiple applications can share the same real device..
oss_device_t *osdev This is a pointer to the osdev structure of the sound card/chip that owns this audio engine..
oss_device_t *master_osdev Like osdev but points to the osdev structure of the "real" device. This field will be initialized by oss_install_audiodev to match it's master_osdev parameter.
int setfragment_warned Reserved for internal use by the audio core.
int getispace_error_count Reserved for internal use by the audio core.
int redirect_in Used by oss_audio_open_devfile to locate the vmix engines for recording direction.
int redirect_out Used by oss_audio_open_devfile to locate the vmix engines for playback direction.
int dmask Reserved for internal use by the audio core.
int nonblock Reserved for the audio core. Used as a cache for the blocking/non-blocking state.
int forced_nonblock Rserved for the audio core. This field will be set to 0 when the device is opened and to 1 when SNDCTL_DSP_NONBLOCK is called. This field is used to force non-blocking I/O even if the application doesn't have set the O_NONBLOCK file flag.
int ossd_registered Reserved for future use by the audio core.
int sync_flags Reserved for internal use by the audio core. Used for handling of the SNDCTL_DSP_SYNCGROUP and SNDCTL_DSP_SYNCSTART ioctl calls.
int sync_group See sync_flags.
int sync_mode See sync_flags.
adev_t *sync_next See sync_flags.
int rate_source This field is used by devices with multiple audio engines synchronized to the same sample rate clock. It contains the audio engine number of the first engine that shares the same clock or the engine that is the master clock source.
unsigned int nrates Number of supported sample rates defined in the rates[] field. Devices that support only limited number of sampling rates should set this field. In addition the rates[] table should be initialized to contain the supported rates..
unsigned int rates[] See the nrates fiels.
oss_mutex_t mutex Mutex variable used for concurrence control on the device.
oss_wait_queue_t *out_wq Sleep queue for output direction.
oss_wait_queue_t *in_wq Sleep queue for input directio.
int card_number Reserved for internal use by the audio core. This field contains an index to the device object (card) structure that owns this audio engine.
int port_number Reserved for internal use by the audio core. This field contains the audio engine number within the sound card/chip.
int real_dev Reserved for internal use by the audio core. This field contains the /dev/dsp# number that is associated with this audio engine. This field is managed by the ossdevlinks utility.
int cooked_enable Reserved for internal use by the audio core. This field contains the "cooked mode" state which is uded to enable/disable the automatic sample rate/format conversions done by OSS. When the device is opened this field is initialized to the cooked_enable configuration option defined in osscore.conf. Applications can change it by calling SNDCTL_DSP_COOKEDMODE.
int timeout_count Reserved for internal use by the audio core. Used to track the number of DMA timeouts occurred since the device was opened.
void (*outputintr) (int dev, int intr_flags) Reserved for internal use by the audio core and the cuckoo module.
void (*inputintr) (int dev, int intr_flags) Reserved for internal use by the audio core and the cuckoo module.
int policy Reserved for internal use by the audio core. Used for handling of the SNDCTL_DSP_POLICY ioctl.
void *os_id Reserved for internal use by the audio core.
oss_longname_t song_name This field is used to handle the SNDCTL_SETSONG and SNDCTL_GETSONG ioctl calls.
oss_label_t label This field is used to handle the SNDCTL_SETLABEL and SNDCTL_GETLABEL ioctl calls.
oss_devnode_t devnode Reserved for internal use by the audio core. This field contains the actual device file/node name (in /dev/oss/).

The adev_t/adev_p structure

The adev_t structure contains all global information about an audio engine/device. In addition each device will have dmap_t descriptors that contain information about the currently allocated DMA buffers for recording and playback (dmap_in and dmap_out).

Device initialization

To create a new audio device (engine) instance the driver needs to create a callnack function list (audiodrv_t) and to register the device by calling oss_install_audiodev. After this it should initialize certain fields in the audio_engines[] entry for the newly created audio engine.

Under construction.

Application open flags

OSS audio core uses some open flags to handle special requirements of virtual drviers (such as vmix). In addition to audio core these flags are also accessible to the low level drivers.

Another purpose of these flags are all kind of bug workarounds required by many common audio applications for Linux. In these cases the flags come from the special_apps table located in the beginning of audio/oss_audio_core.c.

The following application open_flags are available

OF_BLOCK Disable non-blocking I/O (O_NONFBLOCK). Some applications turn on non-blocking I/O but then don't handle the special cases related with buffer full/empty situations.
OF_MMAP This flag tells the audio core (and some drivers) to set up the device in a way that permits mmap() access method. This means that automatic sample rate and format conversions are disabled because they are not compatible with mmap. This flag is required because some applications that use mmap don't call SNDCTL_DSP_COOKEDMODE to disable format conversions.
OF_NOCONV Disable automatic rate and format conversions.
OF_SMALLFRAGS Some applications request too large fragment sizes that may break the syncronization algorithms they use. This flag is used to tell the audio core to force smaller fragment size.
OF_SMALLBUF The vmix driver needs very small DMA buffer on the master device. This flag is used to tell the audio core to allocate smallest possible DMA buffer for the device.
OF_MEDIUMBUF Much like OF_SMALLBUF but for applications that need about 16k buffer.

Supported format masks

OSS audio core uses three different supported format bitmasks for each audio engine: iformat_mask is used when the device has been opened with O_RDONLY, oformat_mask is for O_WRONLY and xformat_mask is for O_RDWR. These masks control which formats the audio core can use. In addition these masks are returned by the SNDCTL_DSP_GETFMTS and SNDCTL_AUDIOINFO ioctl calls.

Normally the driver uses the format_mask parameter of oss_install_audiodev to set (all) these format masks. If the device supports different formats for recording and playback then the driver should set the oformat_mask and iformat_mask fields in the audio_engines[] entry after installing the device. The xformat_mask field is managed by the audio core so it doesn't make sense to change it in the drivers.

DMA Buffer allocation

The way how DMA buffer allocation works depends on the host operating system. The default buffer size is 64k, 32k or 16k. If buffer with the requested size cannot be allocated then OSS will attempt to allocate one with half of that size until allocation succeeds. The dmabuf_alloc_flags field (bit map) can be used to control the allocation in the following way.

DMABUF_NONCONTIG The device supports physically noncontiguous buffers (scatter/gather). This flag has no effect at this moment.
DMABUF_ISA Allocate a DMA buffer that is suitable for ISA devices. Currently not used.
DMABUF_LARGE The device needs larger than usual (64k) DMA buffer to work properly. This flag is supported under some operating systems (in other operating systems it doesn't have any effect).
DMABUF_QUIET Do not display warnings if there are problems in allocating a DMA buffer with the requested size.
DMABUF_SIZE_16BITS Limit the DMA buffer size to 64k. This flag can be used by devices that have only 16 bit register for the transfer size.

The dmabuf_maxaddr field is used to control the physical/bus memory range where the DMA buffer is allocated. The default is MEMLIMIT_32BITS which equals the full PCI address range. If the device can access only limited memory/bus range then the following predefined constants can be used.

MEMLIMIT_ISA 24 bit DMA addressing (16M) supported by ISA devices.
MEMLIMIT_28BITS 28 bit (256M) address range.
MEMLIMIT_30BITS 30 bit (1G) address range.
MEMLIMIT_31BITS 31 bit (2G) address range.
MEMLIMIT_32BITS Full 32 bit address range (4G)
MEMLIMIT_64BITS Full 64 bit address range.

Vmix engine flags

The vmix module uses the flags and vmix_flags fields when deciding if to attach to the audio device and how. The flag field has some bits that affect all virtual drivers (not just vmix). This is defined in the Audio device flags section of this document.

The vmix_flags field has some bits that control only the vmix module in the following way. They don't affect any other virtual audio drivers.

VMIX_MULTIFRAG Some devices require that the vmix engine uses more than two fragments (which is the default). Otherwise there may be problems such as frequent clicking in output.
VMIX_DISABLED This flag prevents vmix from attaching to this device. It can be used if the device (for any reason) doesn't work with vmix. It can also be used with (professional) devices that should play/record audio without any modifications caused by the mixer. The ADEV_DISABLE_VIRTUAL flag performs similar function but affects all virtual drivers instead of just vmix.
VMIX_NOINPUT Use vmix only for output with this device.
VMIX_NOMAINVOL Do not create a vmix main output volume slider in the mixer. This flag can be used in cases where the vmix volume control is redundant with some other "hardware" control.
VMIX_SKIP Do not attach vmix to this device by default. However vmix can be attached if the user does some kind of manual configuration changes to enable it. Similar to the ADEV_NOVIRTUAL flag.
VMIX_SMART_ATTACH This flag is used by the USB audio driver to delay vmix initialization until both input and output master devices have been created. Without this flag vmix can do only output with USB devices.

Referenced by

vmix_core/rec_export_int.incLocal input buffer to application export routine for vmix (int)
vmix_core/vmix.hDefinitions for the vmix driver
vmix_core/vmix_input.cVirtual mixing audio driver recording routines
vmix_core/playmix.incApplication to local playback buffer import routine for vmix (FP)
vmix_core/playmix_src.incApplication to local playback buffer resampling routine for vmix
vmix_core/playmix_int.incApplication to local playback buffer import routine for vmix (int)
vmix_core/rec_export.incLocal input buffer to application export routine for vmix (FP version)
vmix_core/vmix_output.cVirtual mixing audio driver output mixing routines
vmix_core/vmix_core.cSet the master sampling rate of given vmix instance.
audio/audiocnv.incHelper functions used by audiofmt.c
audio/oss_audiofmt.cAudio format conversion routines used by audio.c
audio/oss_audio_core.cAudio core functionality of OSS
include/audio_core.hInternal definitions for the OS audio core
remux/oss_remux.cMulti channel playback support for devices with multiple stereo engines.
mixer/oss_mixer_core.cOSS mixer core.
sndstat/oss_sndstat.c/dev/sndstat driver
oss_hdaudio/oss_hdaudio.cThe High Definition Audio (HDA/Azalia) driver.
oss_cmpci/oss_cmpci.cDriver for CMEDIA CM8738 PCI audio controller.
oss_userdev/oss_userdev.cThis entry point is used to create new userdev instances and to redirect clients to them.
oss_userdev/oss_userdev_devicepair.cClient/server audio device pair for oss_userdev
oss_envy24ht/oss_envy24ht.cVIA ENVY24HT chipset driver.
oss_trident/oss_trident.cDriver for Trident 4DWAVE, ALI 5451 and SiS 7918 audio chips
oss_cs4281/oss_cs4281.cDriver for Crystal PCI audio controller.
oss_solo/oss_solo.cDriver for ESS Solo PCI audio controller.
oss_sbpci/oss_sbpci.cCreative/Ensoniq AudioPCI97 driver (ES1371/ES1373)
oss_madi/oss_madi.cDriver for RME MADI and AES32 audio interfaces
oss_ymf7xx/oss_ymf7xx.cDriver for Yamaha YMF7xx PCI audio controller.
oss_imux/oss_imux.cPseudo driver for sharing one input device between multiple apps.
oss_via823x/oss_via823x.cDriver for the VIA8233/8235 AC97 audio controller
oss_digi96/oss_digi96.cDriver for RME Digi96 family
oss_fmedia/oss_fmedia.cDriver for FM801 FM801 PCI audio controller.
oss_ich/oss_ich.cDriver for the Intel ICH AC97 audio controller
oss_sblive/oss_sblive.cDriver for Creative SB Live/Audigy/2/4. Audio, MIDI and mixer services.
oss_audiopci/oss_audiopci.cCreative/Ensoniq AudioPCI driver (ES1370 "CONCERT" ASIC and AKM4531 codec/mixer)
oss_sadasupport/sadasupport_sol9.hSolaris 9 compatible version of sadasupport_open/close
oss_sadasupport/oss_sadasupport.cSupport for the legacy (SADA) /dev/audio interfaces of Solaris
oss_audioloop/oss_audioloop.cOSS audio loopback (virtual) driver
oss_emu10k1x/oss_emu10k1x.cDriver for Creative emu10k1x audio controller
oss_cmi878x/oss_cmi878x.cDriver for C-Media CMI8788 PCI audio controller.
oss_audigyls/oss_audigyls.cDriver for Creative Audigy LS audio controller
oss_cs461x/oss_cs461x.cDriver for Crystal cs461x and cs461x PCI audio controllers
oss_geode/oss_geode.cDriver for the NS/Cyrix/AMD Geode AC97 audio controller
oss_via97/oss_via97.cDriver for the VIA VT82C686A AC97 audio controller
oss_ali5455/oss_ali5455.cDriver for the ALI 5455 (AC97) audio controller
oss_usb/ossusb.hDefinitions for the USB audio driver files
oss_usb/ossusb_audio.cUSB audio streaming interface support
oss_usb/oss_usb.cTop level USB audio class initialization and mixer functions
oss_atiaudio/oss_atiaudio.cDriver for the ATI IXP (AC97) audio controller
oss_sbxfi/oss_sbxfi.cDriver for Sound Blaster X-Fi (emu20k)
oss_sbxfi/sbxfi_hwaccess.cSource file oss-current/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c
oss_audiocs/oss_audiocs.cDriver for the UltraSparc workstations using CS4231 codec for audio
oss_envy24/oss_envy24.cDriver for IC Ensemble ENVY24 based audio cards.
oss_envy24/envy24_direct.cDirect 24 bit multich driver for Envy24.
Linux/os_linux.hOS specific definitions for Linux
Linux/os_linux.cOperating system abstraction functions for Linux
VxWorks/os_vxworks.hOS specific definitions for VxWorks
SunOS/os_solaris.cOperating system abstraction functions for Solaris
SunOS/os_solaris.hOS specific definitions for Solaris
BeOS/os_beos.hOS specific definitions for BeOS/Haiku
BeOS/os_beos.cOperating system abstraction functions for BeOS/Haiku
FreeBSD/bsddefs.hDefinitions for routines and variables exported by osscore.c
FreeBSD/os_freebsd.cOperating system abstraction functions for FreeBSD
SCO_SV/os_sco.hOS specific definitions for SCO OpenServer and SCO UnixWare (DDI8)
SCO_SV/os_sco.cOperating system abstraction functions for SCO OpenServer/UnixWare

Copyright (C) 4Front Technologies, 2007. All rights reserved.
Back to index OSS web site