Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
#ifndef OSSPLAY_H #define OSSPLAY_H #include <errno.h> #include <fcntl.h> #include <limits.h> #include <unistd.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <soundcard.h> #undef MPEG_SUPPORT #define PLAYBUF_SIZE 1024 #define RECBUF_SIZE 512 #define DEFAULT_CHANNELS 1 #define DEFAULT_FORMAT AFMT_U8 #define DEFAULT_SPEED 11025 #define MAX_CHANNELS 128
Every update of output in verbose mode while playing is separated by at least PLAY_UPDATE_INTERVAL milliseconds.
#define PLAY_UPDATE_INTERVAL 200.0 /* As above, but for recording */ #define REC_UPDATE_INTERVAL 1000.0 /* As above, but used for level meters while recording */ #define LMETER_UPDATE_INTERVAL 20.0 /* Should be smaller than the others. Used to ensure an update at end of file */ #define UPDATE_EPSILON 1.0 typedef signed char int8; typedef unsigned char uint8; typedef short int16; typedef unsigned short uint16; typedef int int32; typedef unsigned int uint32; typedef char flag; #define S32_MAX 2147483647 #define S32_MIN (-S32_MAX - 1) #define U32_MAX 4294967295U
We overload the format definitions to include some "fake" formats. Therefor, the values should be negative to avoid collusions.
enum { AFMT_MS_ADPCM = -256, AFMT_MS_IMA_ADPCM, AFMT_MS_IMA_ADPCM_3BITS, AFMT_MAC_IMA_ADPCM, AFMT_S24_PACKED_BE, AFMT_CR_ADPCM_2, AFMT_CR_ADPCM_3, AFMT_CR_ADPCM_4, AFMT_FIBO_DELTA, AFMT_EXP_DELTA, AFMT_FLOAT32_BE, AFMT_FLOAT32_LE, AFMT_DOUBLE64_BE, AFMT_DOUBLE64_LE }; #define AFMT_S24_PACKED_LE AFMT_S24_PACKED typedef struct { int fd; int format; int channels; int speed; int flags; int reclevel; #ifndef OSS_DEVNODE_SIZE #define OSS_DEVNODE_SIZE 32 #endif char dname[OSS_DEVNODE_SIZE]; #ifndef OSS_LONGNAME_SIZE #define OSS_LONGNAME_SIZE 64 #endif char current_songname[OSS_LONGNAME_SIZE]; char * recsrc; char * playtgt; } dspdev_t; typedef enum { WAVE_FILE, AU_FILE, RAW_FILE, AIFF_FILE, AIFC_FILE, WAVE_FILE_BE, _8SVX_FILE, _16SV_FILE, MAUD_FILE } fctypes_t;
Used in the format_t table below. Shows what actions can be done with the format - Play, Record or both.
typedef enum { CP = 0x1, CR = 0x2, CRP = 0x3 } direction_t; typedef struct fmt_struct { const char * name; const int fmt; const direction_t dir; const int may_conv; } format_t; typedef struct cnt_struct { const char * name; const fctypes_t type; const int dformat; const int dchannels; const int dspeed; } container_t; typedef struct { int coeff1, coeff2; } adpcm_coeff; typedef struct msadpcm_values { int nBlockAlign; int wSamplesPerBlock; int wNumCoeff; int bits; adpcm_coeff coeff[32]; int channels; } msadpcm_values_t; typedef ssize_t (decfunc_t) (unsigned char **, unsigned char *, ssize_t, void *); typedef ssize_t (seekfunc_t) (int, unsigned long long *, unsigned long long, double, unsigned long long, int); typedef enum { FREE_OBUF = 1, FREE_META = 2 } decoder_flag_t; typedef struct decoders_queue { struct decoders_queue * next; decfunc_t * decoder; unsigned char * outbuf; void * metadata; decoder_flag_t flag; } decoders_queue_t; typedef enum { E_OK, E_SETUP_ERROR, E_FORMAT_UNSUPPORTED, E_CHANNELS_UNSUPPORTED, E_DECODE, E_ENCODE, E_USAGE,
Not an error, but since seek function can also return an error this needs to be different from the others
SEEK_CONT_AFTER_DECODE } errors_t; static const format_t format_a[] = { {"S8", AFMT_S8, CRP, AFMT_S16_NE}, {"U8", AFMT_U8, CRP, AFMT_S16_NE}, {"S16_LE", AFMT_S16_LE, CRP, AFMT_S16_NE}, {"S16_BE", AFMT_S16_BE, CRP, AFMT_S16_NE}, {"U16_LE", AFMT_U16_LE, CRP, AFMT_S16_NE}, {"U16_BE", AFMT_U16_BE, CRP, AFMT_S16_NE}, {"S24_LE", AFMT_S24_LE, CRP, 0}, {"S24_BE", AFMT_S24_BE, CRP, 0}, {"S32_LE", AFMT_S32_LE, CRP, AFMT_S32_NE}, {"S32_BE", AFMT_S32_BE, CRP, AFMT_S32_NE}, {"A_LAW", AFMT_A_LAW, CRP, AFMT_S16_NE}, {"MU_LAW", AFMT_MU_LAW, CRP, AFMT_S16_NE}, {"IMA_ADPCM", AFMT_IMA_ADPCM, CP, 0}, {"IMA_ADPCM_3BITS", AFMT_MS_IMA_ADPCM_3BITS,CP, 0}, {"MS_ADPCM", AFMT_MS_ADPCM, CP, 0}, {"CR_ADPCM_2", AFMT_CR_ADPCM_2, CP, 0}, {"CR_ADPCM_3", AFMT_CR_ADPCM_3, CP, 0}, {"CR_ADPCM_4", AFMT_CR_ADPCM_4, CP, 0}, {"FLOAT32_LE", AFMT_FLOAT32_LE, CP, 0}, {"FLOAT32_BE", AFMT_FLOAT32_BE, CP, 0}, {"DOUBLE64_LE", AFMT_DOUBLE64_LE, CP, 0}, {"DOUBLE64_BE", AFMT_DOUBLE64_BE, CP, 0}, {"S24_PACKED", AFMT_S24_PACKED, CRP, 0}, {"S24_PACKED_BE", AFMT_S24_PACKED_BE, CP, 0}, {"SPDIF_RAW", AFMT_SPDIF_RAW, CR, 0}, {"FIBO_DELTA", AFMT_FIBO_DELTA, CP, 0}, {"EXP_DELTA", AFMT_EXP_DELTA, CP, 0}, {NULL, 0, 0, 0} }; static const container_t container_a[] = { {"WAV", WAVE_FILE, AFMT_S16_LE, 2, 48000}, {"AU", AU_FILE, AFMT_MU_LAW, 1, 8000}, {"RAW", RAW_FILE, AFMT_S16_LE, 2, 44100}, {"AIFF", AIFF_FILE, AFMT_S16_BE, 2, 48000}, {NULL, 0, 0, 0, 0} }; /* Order should match fctypes_t enum so that container_a[type] works */ int be_int (const unsigned char *, int); const char * filepart (const char *); float format2bits (int); int le_int (const unsigned char *, int); long double ossplay_ldexpl (long double, int); off_t ossplay_lseek_stdin (int, off_t, int); int ossplay_parse_opts (int, char **, dspdev_t *); int ossrecord_parse_opts (int, char **, dspdev_t *); int play (dspdev_t *, int, unsigned long long *, unsigned long long, double, decoders_queue_t *, seekfunc_t *); int record (dspdev_t *, FILE *, const char *, double, unsigned long long, unsigned long long *, decoders_queue_t * dec); const char * sample_format_name (int); int setup_device (dspdev_t *, int, int, int); int silence (dspdev_t *, unsigned long long, int); void select_playtgt (dspdev_t *); void select_recsrc (dspdev_t *); void open_device (dspdev_t *); void close_device (dspdev_t *); #if !defined(OSS_BIG_ENDIAN) && !defined(OSS_LITTLE_ENDIAN) #if AFMT_S16_NE == AFMT_S16_BE #define OSS_BIG_ENDIAN #else #define OSS_LITTLE_ENDIAN #endif /* AFMT_S16_NE == AFMT_S16_BE */ #endif /* !OSS_BIG_ENDIAN && !OSS_LITTLE_ENDIAN */ #include "ossplay_console.h" #endif