Google
 

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!

include/audio_core.h

Internal definitions for the OS audio core

Description


#ifndef AUDIO_CORE_H
#define AUDIO_CORE_H

IMPORTANT NOTICE!

This file contains internal structures used by Open Sound Systems. They will change without any notice between OSS versions. Care must be taken to make sure any software using this header gets properly re-compiled before use.

4Front Technologies (or anybody else) takes no responsibility of damages caused by use of this file.



This file is part of Open Sound System.

Copyright (C) 4Front Technologies 1996-2008.

This this source file is released under GPL v2 license (no other versions). See the COPYING file included in the main directory of this source distribution for the license terms and conditions.



Max number of audio channels currently supported by the sample format converter.

#define OSS_MAX_CONVERT_CHANNELS	64


Size of the temporary buffer used for audio conversions.

TMP_CONVERT_MAX defines how many bytes can be fed to the converter in one call.

TMP_CONVERT_BUF_SIZE defines how many bytes of buffer will be allocated. This is larger than TMP_CONVERT_MAX because amount of data may get expanded during the conversion (for example if the output sampling rate or #channels is larger than in the input side).

#define TMP_CONVERT_MAX		(16*1024)
#define TMP_CONVERT_BUF_SIZE	(8*TMP_CONVERT_MAX)


open_flags (for opening audio devices)

#define OF_MMAP		0x00000001	/* Opening application is known to use mmap() */
#define OF_BLOCK	0x00000002	/* Disable O_NONBLOCK */
#define OF_NOCONV	0x00000010	/* Disable all fmt/src conversions */
#define OF_DEVAUDIO	0x00000020	/* Solaris /dev/audio emulator */
#define OF_SMALLFRAGS	0x00000040	/* Use smaller fragments than requested */
#define OF_SMALLBUF	0x00000080	/* Allocate small (4k) buffer this time */
#define OF_MEDIUMBUF	0x00000100	/* Allocate moderate (16k) buffer */

#define CONVERTABLE_FORMATS \
	(AFMT_U8|AFMT_S8|AFMT_MU_LAW|AFMT_S16_LE|AFMT_S16_BE|\
	 AFMT_S24_LE|AFMT_S24_BE|AFMT_S32_LE|AFMT_S32_BE|AFMT_S24_PACKED)

#ifndef _KERNEL
typedef struct _audiodrv_t audiodrv_t;
#endif

typedef struct
{
  char *name;
  int fmt;
  unsigned char neutral_byte;
  char bits;
  char is_linear;
  char endianess;
#define ENDIAN_NONE		0
#define ENDIAN_LITTLE 	1
#define ENDIAN_BIG	  	2
#ifdef OSS_BIG_ENDIAN
# define ENDIAN_NATIVE ENDIAN_BIG
#else
# define ENDIAN_NATIVE ENDIAN_LITTLE
#endif

  char is_signed;
  char alignment;
#define ALIGN_MSB		0
#define ALIGN_LSB		1
  int no_convert;
}
audio_format_info_t, *audio_format_info_p;

typedef struct
{
  int fmt, rate, channels;
  int convert;
}
sample_parms;

typedef struct _adev_t adev_t, *adev_p;
typedef struct _dmap_t *dmap_p;
typedef int (*cnv_func_t) (adev_p adev, dmap_p dmap, unsigned char **srcp, int *srcl,
			   unsigned char **tgtp, sample_parms * source,
			   sample_parms * target);

struct _dmap_t
{

Static fields (not to be cleared during open)

#ifdef _KERNEL
  oss_mutex_t mutex;
#endif
  oss_device_t *osdev;
  oss_device_t *master_osdev;	/* The osdev pointer of the master (for virtual drivers) */
  adev_t *adev;
  unsigned char *dmabuf;
  oss_native_word dmabuf_phys;
  oss_dma_handle_t dmabuf_dma_handle;
  int buffsize;
  int buffer_protected;		/* Buffer is shared - don't modify/clear */
  unsigned char *tmpbuf1, *tmpbuf2;
  void *driver_use_ptr;
  long driver_use_value;
  /* Interrupt callback stuff */
  void (*audio_callback) (int dev, int parm);
  int callback_parm;

#ifdef OS_DMA_PARMS
    OS_DMA_PARMS
#endif

Dynamic fields (will be zeroed during open) Don't add anything before flags.

  void *srcstate[OSS_MAX_CONVERT_CHANNELS];
  oss_native_word flags;
#define DMAP_NOTIMEOUT	0x00000001
#define DMAP_POST		0x00000002
#define DMAP_PREPARED	0x00000004
#define DMAP_FRAGFIXED	0x00000008	/* Fragment size fixed */
#define DMAP_STARTED	0x00000010
#define DMAP_COOKED		0x00000020
#define DMAP_SMALLBUF     0x00000040	/* Allocate small buffers */
#define DMAP_MEDIUMBUF     0x00000040	/* Allocate 16k buffers */
  int dma_mode;			/* PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT or 0 */


Queue parameters.

  int nfrags;
  int fragment_size;
  int bytes_in_use;
  int data_rate;		/* Bytes/second */
  int frame_size;		/* Device frame size */
  int user_frame_size;		/* Application frame size */
  int fragsize_rq;
  int low_water, low_water_rq;
  volatile oss_uint64_t byte_counter;
  volatile oss_uint64_t user_counter;
  int interrupt_count;
  int fragment_counter;
  int expand_factor;

  int mapping_flags;
#define			DMA_MAP_MAPPED		0x00000001
  char neutral_byte;

  int error;
  int play_underruns, rec_overruns;
  int underrun_flag;
  int num_errors;
#define MAX_AUDIO_ERRORS	5
  int errors[MAX_AUDIO_ERRORS];
  int error_parms[MAX_AUDIO_ERRORS];

  unsigned char *leftover_buf;
  int leftover_bytes;
  int tmpbuf_len, tmpbuf_ptr;
  cnv_func_t convert_func;
  unsigned int convert_mode;
  struct audio_buffer *(*user_import) (adev_t * adev,
				       dmap_t * dmap,
				       sample_parms * parms,
				       unsigned char *cbuf, int len);
  int (*user_export) (adev_t * adev,
		      dmap_t * dmap, sample_parms * parms,
		      struct audio_buffer * buf, unsigned char *cbuf,
		      int maxbytes);
  struct audio_buffer *(*device_read) (adev_t * adev,
				       dmap_t * dmap,
				       sample_parms * parms,
				       unsigned char *cbuf, int len);
  int (*device_write) (adev_t * adev,
		       dmap_t * dmap,
		       void *frombuf, void *tobuf,
		       int maxspace, int *fromlen, int *tolen);
};
extern int dmap_get_qlen (dmap_t * dmap);
extern int dmap_get_qhead (dmap_t * dmap);
extern int dmap_get_qtail (dmap_t * dmap);

struct _adev_t
{
  char name[64];
  char handle[32];
  int engine_num;		/* Audio engine number */
  int audio_devfile;		/* Audio device file number */
  int enabled;
  int unloaded;
  struct _adev_t *next_in, *next_out;	/* Links to the next "shadow" devices */
  long long flags;
  int open_flags;
  int src_quality;
  int caps;
  int magic;			/* Secret low level driver ID */
  int latency;			/* In usecs, -1=unknown */



Sampling parameters


  sample_parms user_parms, hw_parms;
  int iformat_mask, oformat_mask;	/* Bitmasks for supported audio formats */
  int min_rate, max_rate;	/* Sampling rate limits */
  int min_channels, max_channels;
  char *inch_names, *outch_names;
  int xformat_mask;		/* Format mask for current open mode */
  int binding;
  void *devc;			/* Driver specific info */
  audiodrv_t *d;
  void *portc, *portc_play, *portc_record;	/* Driver specific info */
  dmap_t *dmap_in, *dmap_out;
  int mixer_dev;
  int open_mode;
  int go;
  int enable_bits;
  int parent_dev;		/* 0 -> no parent, 1 to n -> parent=parent_dev+1 */
  int max_block;		/* Maximum fragment size to be accepted */
  int min_block;		/* Minimum fragment size */
  int min_fragments;		/* Minimum number of fragments */
  int max_fragments;		/* Maximum number of fragments */
  int max_intrate;		/* Another form of min_block */
  int dmabuf_alloc_flags;
  oss_uint64_t dmabuf_maxaddr;
  int fixed_rate;
  int vmix_flags;		/* special flags sent to virtual mixer */
#define VMIX_MULTIFRAG	0x00000001	/* More than 2 fragments required (causes longer latencies) */
#define VMIX_DISABLED	0x00000002	/* Not compatible with vmix */
#define VMIX_NOINPUT	0x00000004	/* Disable input capability */
#define VMIX_NOMAINVOL	0x00000008	/* No main volume sliders/meters please */
  pid_t pid;
  char cmd[16];
  oss_device_t *osdev;
  oss_device_t *master_osdev;	/* The osdev pointer of the master (for virtual drivers) */
  int setfragment_warned;
  int getispace_error_count;
  int redirect_in, redirect_out;
  int dmask;			/* Open dmaps */
#define DMASK_OUT		0x01
#define DMASK_IN		0x02
  int nonblock;
  int forced_nonblock;
  int ossd_registered;
  int sync_flags;
#define SYNC_MASTER		0x01
#define SYNC_SLAVE		0x02
  int sync_group;
  int sync_mode;
  adev_t *sync_next;		/* Next device in sync group */

  int rate_source;
  unsigned int nrates, rates[OSS_MAX_SAMPLE_RATES + 1];

#ifdef _KERNEL
  oss_mutex_t mutex;
  oss_wait_queue_t *out_wq, *in_wq;
#endif

  int card_number;
  int port_number;
  int real_dev;


By default OSS will let applications to use sampling rates and formats that are not supported by the hardware. Instead OSS performs the necessary format conversions in software. Applications that don't tolerate this kind of conversions usually disable them by using features of the OSS API (SNDCTL_DSP_COOKEDMODE). If this option is set to 0 then the format conversions will be disabled for all applications and devices unless the application explicitly enables them.

cooked_enable is a global variable (int) defined in oss_core_options.c. The current value of this global variable will be copied to adev->cooked_enable when an audio engine is opened.

  int cooked_enable;
  int timeout_count;

  void (*outputintr) (int dev, int intr_flags);
  void (*inputintr) (int dev, int intr_flags);

  int policy;
  void *os_id;			/* The device ID (dip) given by the system. */
  oss_longname_t song_name;
  oss_label_t label;
  oss_devnode_t devnode;
  void *vmix_mixer;		/* Pointer to the vmix_mixer_t structure for this device */
  void *prev_vmix_mixer;	/* Reserved for vmix_core */
};

#define UNIT_EXPAND		1024


The audio_devfiles and audio_engines tables contain pointers to the (same) adev_t structures. The difference is that audio_engines contains an entry for all audio devices/engines in the system (including hidden and shadow devices). The 'dev' parameter of most audio core routines and audio driver methods are indexes to this array.

The audio_devfiles array is a "parallel" structure that contains only the audio engines that have a device file in /dev/oss (and usually also an legacy /dev/dsp# device file). This audio_devfiles array doesn't contain "hidden" audio engines.

Each audio operations structure in audio_devfiles will also be in audio_engines but the indexes are different. Both arrays contain pointer to the same structure in memory (not a copy).

For example the 6th audio device file (usually but not always /dev/dsp5) is audio_devfiles[5]. However it may be (say) audio_engines[11] if there are hidden devices created before it.

/dev/dsp5 -> audio_devfile[5] == audio_engines[11]

The next field of the adev_t structure contains a pointer to the next "identical" device. Most OSS implementations will try to open one of the subsequent devices in the next chain if the original device was busy. "Identical" means that the device suports multiple identical (hw mixing) engines or the vmix driver is used to add software mixing capability to the device.


extern adev_t **audio_engines;
extern int num_audio_engines;
extern adev_t **audio_devfiles;
extern int num_audio_devfiles;

#if 0
typedef struct
{
  int ndevs;
  unsigned short devices[MAX_AUDIO_DEVFILES];
}
oss_devlist_t;

extern oss_devlist_t dspoutlist, dspoutlist2, dspinlist, dspinoutlist;
#endif

int oss_install_audiodev (int vers,
			  oss_device_t * osdev,
			  oss_device_t * master_osdev,
			  char *name,
			  const audiodrv_t * driver,
			  int driver_size,
			  unsigned long long flags,
			  unsigned int format_mask, void *devc, int parent);

int oss_install_audiodev_with_devname (int vers,
			  oss_device_t * osdev,
			  oss_device_t * master_osdev,
			  char *name,
			  const audiodrv_t * driver,
			  int driver_size,
			  int flags,
			  unsigned int format_mask, void *devc, int parent,
			  const char *devfile_name);
extern void install_vdsp (oss_device_t * osdev);
extern int *load_mixer_volumes (char *name, int *levels, int present);

#ifdef _KERNEL
int oss_audio_read (int dev, struct fileinfo *file, uio_t * buf, int count);
int oss_audio_write (int dev, struct fileinfo *file, uio_t * buf, int count);
int oss_audio_open_engine (int dev, int dev_class, struct fileinfo *file,
			   int recursive, int open_flags, int *newdev);
int oss_audio_open_devfile (int dev, int dev_class, struct fileinfo *file,
			    int recursive, int open_flags, int *newdev);
int oss_open_vdsp (int dev, int dev_type, struct fileinfo *file,
		   int recursive, int open_flags, int *newdev);
void oss_audio_release (int dev, struct fileinfo *file);
int oss_audio_ioctl (int dev, struct fileinfo *file,
		     unsigned int cmd, ioctl_arg arg);
int oss_audio_set_format (int dev, int fmt, int format_mask);
int oss_audio_set_channels (int dev, int ch);
int oss_audio_set_rate (int dev, int val);
void audio_uninit_device (int dev);
int oss_audio_mmap (int dev, int direction);
#endif

/* From audiofmt.c */
int setup_format_conversions (adev_p adev, dmap_p dmap, sample_parms * source,
			      sample_parms * target,
			      sample_parms * user,
			      sample_parms * device, int format_mask);
audio_format_info_p oss_find_format (unsigned int fmt);


#define oss_audio_outputintr(dev, flags) audio_engines[dev]->outputintr(dev, flags)
#define oss_audio_inputintr(dev, flags) audio_engines[dev]->inputintr(dev, flags)
void oss_audio_reset (int dev);
void oss_audio_start_syncgroup (unsigned int syncgroup);
typedef int (*oss_audio_startup_func) (void *devc);
extern void oss_audio_register_client (oss_audio_startup_func func,
				       void *devc, oss_device_t * osdev);

extern int oss_encode_enum (oss_mixer_enuminfo * ei, const char *s,
			    int version);
extern char *audio_show_latency (int dev);
extern void oss_audio_inc_byte_counter (dmap_t * dmap, int increment);
extern void oss_add_audio_devlist (int list, int devfile);

#ifndef SMALL_DMABUF_SIZE
#define SMALL_DMABUF_SIZE (4*1024)
#endif

#define MEDIUM_DMABUF_SIZE (16*1024)
#endif

Copyright (C) 4Front Technologies, 2007. All rights reserved.

Back to index OSS web site


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