Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
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.
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.
Field | Description |
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 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).
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.
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
open_flag | Description |
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. |
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.
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.
alloc_flag | Description |
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.
constant | Description |
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. |
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_flag | Description |
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. |
vmix_core/rec_export_int.inc | Local input buffer to application export routine for vmix (int) |
vmix_core/vmix.h | Definitions for the vmix driver |
vmix_core/vmix_input.c | Virtual mixing audio driver recording routines |
vmix_core/playmix.inc | Application to local playback buffer import routine for vmix (FP) |
vmix_core/playmix_src.inc | Application to local playback buffer resampling routine for vmix |
vmix_core/playmix_int.inc | Application to local playback buffer import routine for vmix (int) |
vmix_core/rec_export.inc | Local input buffer to application export routine for vmix (FP version) |
vmix_core/vmix_output.c | Virtual mixing audio driver output mixing routines |
vmix_core/vmix_core.c | Set the master sampling rate of given vmix instance. |
audio/audiocnv.inc | Helper functions used by audiofmt.c |
audio/oss_audiofmt.c | Audio format conversion routines used by audio.c |
audio/oss_audio_core.c | Audio core functionality of OSS |
include/audio_core.h | Internal definitions for the OS audio core |
remux/oss_remux.c | Multi channel playback support for devices with multiple stereo engines. |
mixer/oss_mixer_core.c | OSS mixer core. |
sndstat/oss_sndstat.c | /dev/sndstat driver |
oss_hdaudio/oss_hdaudio.c | The High Definition Audio (HDA/Azalia) driver. |
oss_cmpci/oss_cmpci.c | Driver for CMEDIA CM8738 PCI audio controller. |
oss_userdev/oss_userdev.c | This entry point is used to create new userdev instances and to redirect clients to them. |
oss_userdev/oss_userdev_devicepair.c | Client/server audio device pair for oss_userdev |
oss_envy24ht/oss_envy24ht.c | VIA ENVY24HT chipset driver. |
oss_trident/oss_trident.c | Driver for Trident 4DWAVE, ALI 5451 and SiS 7918 audio chips |
oss_cs4281/oss_cs4281.c | Driver for Crystal PCI audio controller. |
oss_solo/oss_solo.c | Driver for ESS Solo PCI audio controller. |
oss_sbpci/oss_sbpci.c | Creative/Ensoniq AudioPCI97 driver (ES1371/ES1373) |
oss_madi/oss_madi.c | Driver for RME MADI and AES32 audio interfaces |
oss_ymf7xx/oss_ymf7xx.c | Driver for Yamaha YMF7xx PCI audio controller. |
oss_imux/oss_imux.c | Pseudo driver for sharing one input device between multiple apps. |
oss_via823x/oss_via823x.c | Driver for the VIA8233/8235 AC97 audio controller |
oss_digi96/oss_digi96.c | Driver for RME Digi96 family |
oss_fmedia/oss_fmedia.c | Driver for FM801 FM801 PCI audio controller. |
oss_ich/oss_ich.c | Driver for the Intel ICH AC97 audio controller |
oss_sblive/oss_sblive.c | Driver for Creative SB Live/Audigy/2/4. Audio, MIDI and mixer services. |
oss_audiopci/oss_audiopci.c | Creative/Ensoniq AudioPCI driver (ES1370 "CONCERT" ASIC and AKM4531 codec/mixer) |
oss_sadasupport/sadasupport_sol9.h | Solaris 9 compatible version of sadasupport_open/close |
oss_sadasupport/oss_sadasupport.c | Support for the legacy (SADA) /dev/audio interfaces of Solaris |
oss_audioloop/oss_audioloop.c | OSS audio loopback (virtual) driver |
oss_emu10k1x/oss_emu10k1x.c | Driver for Creative emu10k1x audio controller |
oss_cmi878x/oss_cmi878x.c | Driver for C-Media CMI8788 PCI audio controller. |
oss_audigyls/oss_audigyls.c | Driver for Creative Audigy LS audio controller |
oss_cs461x/oss_cs461x.c | Driver for Crystal cs461x and cs461x PCI audio controllers |
oss_geode/oss_geode.c | Driver for the NS/Cyrix/AMD Geode AC97 audio controller |
oss_via97/oss_via97.c | Driver for the VIA VT82C686A AC97 audio controller |
oss_ali5455/oss_ali5455.c | Driver for the ALI 5455 (AC97) audio controller |
oss_usb/ossusb.h | Definitions for the USB audio driver files |
oss_usb/ossusb_audio.c | USB audio streaming interface support |
oss_usb/oss_usb.c | Top level USB audio class initialization and mixer functions |
oss_atiaudio/oss_atiaudio.c | Driver for the ATI IXP (AC97) audio controller |
oss_sbxfi/oss_sbxfi.c | Driver for Sound Blaster X-Fi (emu20k) |
oss_sbxfi/sbxfi_hwaccess.c | Source file oss-current/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c |
oss_audiocs/oss_audiocs.c | Driver for the UltraSparc workstations using CS4231 codec for audio |
oss_envy24/oss_envy24.c | Driver for IC Ensemble ENVY24 based audio cards. |
oss_envy24/envy24_direct.c | Direct 24 bit multich driver for Envy24. |
Linux/os_linux.h | OS specific definitions for Linux |
Linux/os_linux.c | Operating system abstraction functions for Linux |
VxWorks/os_vxworks.h | OS specific definitions for VxWorks |
SunOS/os_solaris.c | Operating system abstraction functions for Solaris |
SunOS/os_solaris.h | OS specific definitions for Solaris |
BeOS/os_beos.h | OS specific definitions for BeOS/Haiku |
BeOS/os_beos.c | Operating system abstraction functions for BeOS/Haiku |
FreeBSD/bsddefs.h | Definitions for routines and variables exported by osscore.c |
FreeBSD/os_freebsd.c | Operating system abstraction functions for FreeBSD |
SCO_SV/os_sco.h | OS specific definitions for SCO OpenServer and SCO UnixWare (DDI8) |
SCO_SV/os_sco.c | Operating system abstraction functions for SCO OpenServer/UnixWare |