PDL-Audio
view release on metacpan or search on metacpan
sndlib/audio.c view on Meta::CPAN
* char *audio_system_name(int system) returns some user-recognizable (?) name for the given card
* char *audio_moniker(void) returns some brief description of the overall audio setup.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <math.h>
#include <stdio.h>
#if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
#include <fcntl.h>
#endif
#include <signal.h>
#if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
#include <limits.h>
#endif
#include <errno.h>
#include <stdlib.h>
#if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
#include <libc.h>
#else
#if (!(defined(_MSC_VER))) && (!(defined(MPW_C)))
#include <unistd.h>
#endif
#endif
#define STRBUF_SIZE 4096
#if (defined(HAVE_CONFIG_H)) && (!defined(HAVE_STRERROR))
char *strerror(int errnum)
{
char *strerrbuf;
strerrbuf = (char *)CALLOC(16,sizeof(char));
sprintf(strerrbuf,"io err %d",errnum);
return(strerrbuf);
}
#else
#include <string.h>
#endif
#include "sndlib.h"
static char *version_name = NULL;
static int AUDIO_ERROR = SNDLIB_NO_ERROR;
int audio_error(void) {return(AUDIO_ERROR);}
void set_audio_error(int err) {AUDIO_ERROR = err;}
static int audio_initialized = 0;
static char *audio_error_name_1(int err)
{
switch (err)
{
case SNDLIB_NO_ERROR: return(""); break;
case SNDLIB_CHANNELS_NOT_AVAILABLE: return("channel(s) not available"); break;
case SNDLIB_SRATE_NOT_AVAILABLE: return("srate not available"); break;
case SNDLIB_FORMAT_NOT_AVAILABLE: return("format not available"); break;
case SNDLIB_NO_INPUT_AVAILABLE: return("no input available"); break;
case SNDLIB_NO_OUTPUT_AVAILABLE: return("no output available"); break;
case SNDLIB_INPUT_BUSY: return("input busy"); break;
case SNDLIB_OUTPUT_BUSY: return("output busy"); break;
case SNDLIB_CONFIGURATION_NOT_AVAILABLE: return("configuration not available"); break;
case SNDLIB_INPUT_CLOSED: return("input closed"); break;
case SNDLIB_OUTPUT_CLOSED: return("output closed"); break;
case SNDLIB_IO_INTERRUPTED: return("io interrupted"); break;
case SNDLIB_NO_LINES_AVAILABLE: return("no lines available"); break;
case SNDLIB_WRITE_ERROR: return("write error"); break;
case SNDLIB_SIZE_NOT_AVAILABLE: return("size not available"); break;
case SNDLIB_DEVICE_NOT_AVAILABLE: return("device not available"); break;
case SNDLIB_CANT_CLOSE: return("close failed"); break;
case SNDLIB_CANT_OPEN: return("open failed"); break;
case SNDLIB_READ_ERROR: return("read error"); break;
case SNDLIB_AMP_NOT_AVAILABLE: return("amp control not available"); break;
case SNDLIB_AUDIO_NO_OP: return("unimplemented operation"); break;
case SNDLIB_CANT_WRITE: return("write failed"); break;
case SNDLIB_CANT_READ: return("read failed"); break;
case SNDLIB_NO_READ_PERMISSION: return("need read permission on /dev/dsp"); break;
default: return("unknown error"); break;
}
}
static char *strbuf = NULL;
static void pprint(char *str);
int device_channels(int dev);
int device_gains(int dev);
int device_channels(int dev)
{
float val[1];
read_audio_state(dev,SNDLIB_CHANNEL_FIELD,0,val);
return((int)val[0]);
}
int device_gains(int ur_dev)
{
float val[1];
int err;
int dev;
dev = SNDLIB_DEVICE(ur_dev);
/* to get hardware gains, read device amp_field and error = none */
if ((dev == SNDLIB_DAC_FILTER_DEVICE) || (dev == SNDLIB_MIXER_DEVICE))
{
err = read_audio_state(ur_dev,SNDLIB_CHANNEL_FIELD,0,val);
return((int)val[0]);
}
err = read_audio_state(ur_dev,SNDLIB_AMP_FIELD,0,val);
if (err != SNDLIB_NO_ERROR) return(0);
return(device_channels(ur_dev));
}
/* ------------------------------- SGI ----------------------------------------- */
#ifdef SGI
#define AUDIO_OK
#include <audio.h>
static char *errstr = NULL;
sndlib/audio.c view on Meta::CPAN
audio_mixer[i] = -1;
audio_type[i] = NORMAL_CARD;
}
num_mixers = MAX_MIXERS;
num_dsps = MAX_DSPS;
#ifdef NEW_OSS
fd = open(DAC_NAME,O_WRONLY|O_NONBLOCK,0);
if (fd == -1) fd = open(SYNTH_NAME,O_RDONLY|O_NONBLOCK,0);
if (fd == -1) fd = open(MIXER_NAME,O_RDONLY|O_NONBLOCK,0);
if (fd != -1)
{
status = ioctl(fd,OSS_GETVERSION,&ignored);
new_oss_running = (status == 0);
if (new_oss_running)
{
status = ioctl(fd,OSS_SYSINFO,&sysinfo);
sysinfo_ok = (status == 0);
}
if ((new_oss_running) && (sysinfo_ok))
{
num_mixers = sysinfo.nummixers;
num_dsps = sysinfo.numaudios;
}
close(fd);
}
#endif
/* need to get which /dev/dsp lines match which /dev/mixer lines,
* find out how many separate systems (soundcards) are available,
* fill the audio_dsp and audio_mixer arrays with the system-related numbers,
* since we have no way to tell from OSS info which mixers/dsps are the
* main ones, we'll do some messing aound to try to deduce this info.
* for example, SB uses two dsp ports and two mixers per card, whereas
* Ensoniq uses 2 dsps and 1 mixer.
*
* the data we are gathering here:
* int audio_dsp[MAX_SOUNDCARDS] -> main_dsp_port[SNDLIB_AUDIO_SYSTEM(n)] (-1 => no such system dsp)
* int audio_mixer[MAX_SOUNDCARDS] -> main_mixer_port[SNDLIB_AUDIO_SYSTEM(n)]
* int sound_cards = 0 -> usable systems
* all auxiliary ports are currently ignored (SB equalizer, etc)
*/
sound_cards = 0;
ndsp = 0;
nmix = 0;
while ((nmix<num_mixers) && (ndsp < num_dsps))
{
/* for each mixer, find associated main dsp (assumed to be first in /dev/dsp ordering) */
/* if mixer's dsp overlaps or we run out of dsps first, ignore it (aux mixer) */
/* our by-guess-or-by-gosh method here is to try to open the mixer.
* if that fails, quit (if very first, try at least to get the dsp setup)
* find volume field, if none, go on, else read current volume
* open next unchecked dsp, try to set volume, read current, if different we found a match -- set and go on.
* if no change, move to next dsp and try again, if no more dsps, quit (checking for null case as before)
*/
sprintf(dname,"%s%d",MIXER_NAME,nmix);
md = open(dname,O_RDWR|O_NONBLOCK,0);
if (md == -1)
{
if (errno == EBUSY)
{
fprintf(stderr,"%s is busy: can't access it",dname);
nmix++;
continue;
}
else break;
}
sprintf(dname,"%s%d",DAC_NAME,ndsp);
fd = open(dname,O_RDWR|O_NONBLOCK,0);
if (fd == -1) fd = open(dname,O_RDONLY|O_NONBLOCK,0);
if (fd == -1) fd = open(dname,O_WRONLY|O_NONBLOCK,0); /* some output devices need this */
if (fd == -1)
{
close(md);
if (errno == EBUSY) /* in linux /usr/include/asm/errno.h */
{
fprintf(stderr,"%s is busy: can't access it\n",dname);
ndsp++;
continue;
}
else
{
if (errno != ENXIO && errno != ENODEV)
fprintf(stderr,"%s: %s! ",dname,strerror(errno));
break;
}
}
#ifdef NEW_OSS
/* can't change volume yet of Sonorus, so the method above won't work --
* try to catch this case via the mixer's name
*/
status = ioctl(md,SOUND_MIXER_INFO,&mixinfo);
if ((status == 0) && (mixinfo.name) && (*(mixinfo.name)) &&
(strlen(mixinfo.name) > 6) && (strncmp("STUDI/O",mixinfo.name,7) == 0))
{
/* a special case in every regard */
audio_type[sound_cards] = SONORUS_STUDIO;
audio_mixer[sound_cards] = nmix;
nmix++;
audio_dsp[sound_cards] = ndsp;
if (num_dsps >= 21)
{
ndsp+=21;
audio_mode[sound_cards] = 1;
}
else
{
ndsp+=9;
audio_mode[sound_cards] = 0;
}
sound_cards++;
close(fd);
close(md);
continue;
}
#endif
err = ioctl(md,SOUND_MIXER_READ_DEVMASK,&devmask);
responsive_field = SOUND_MIXER_VOLUME;
for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
if ((1<<i) & devmask)
{
responsive_field = i;
break;
}
if (!err)
{
err = ioctl(md,MIXER_READ(responsive_field),&old_mixer_amp);
if (!err)
{
err = ioctl(fd,MIXER_READ(responsive_field),&old_dsp_amp);
if ((!err) && (old_dsp_amp == old_mixer_amp))
{
if (old_mixer_amp == 0) amp = 50; else amp = 0; /* 0..100 */
err = ioctl(fd,MIXER_WRITE(responsive_field),&);
if (!err)
{
err = ioctl(md,MIXER_READ(responsive_field),&new_mixer_amp);
sndlib/audio.c view on Meta::CPAN
g = mina + val[0] * (maxa-mina);
if (chan == 0) gain.cgain[0].receive_gain = g; else gain.cgain[1].receive_gain = g;
ioctl(audio_fd,AUDIO_SET_GAINS,&gain);
break;
case SNDLIB_SRATE_FIELD:
srate = val[0];
ioctl(audio_fd,AUDIO_SET_SAMPLE_RATE,srate);
break;
default: AUDIO_ERROR = SNDLIB_CANT_WRITE; break;
}
break;
default: AUDIO_ERROR = SNDLIB_CANT_WRITE; break;
}
close(audio_fd);
if (AUDIO_ERROR != SNDLIB_NO_ERROR) return(-1);
return(0);
}
static int saved_gains[6];
void save_audio_state(void)
{
int fd;
struct audio_gain gain;
gain.channel_mask = (AUDIO_CHANNEL_LEFT | AUDIO_CHANNEL_RIGHT);
fd = open("/dev/audio",O_RDWR);
ioctl(fd,AUDIO_GET_GAINS,&gain);
close(fd);
saved_gains[0] = gain.cgain[0].transmit_gain;
saved_gains[1] = gain.cgain[0].receive_gain;
saved_gains[2] = gain.cgain[0].monitor_gain;
saved_gains[3] = gain.cgain[1].transmit_gain;
saved_gains[4] = gain.cgain[1].receive_gain;
saved_gains[5] = gain.cgain[1].monitor_gain;
}
void restore_audio_state(void)
{
int fd;
struct audio_gain gain;
gain.channel_mask = (AUDIO_CHANNEL_LEFT | AUDIO_CHANNEL_RIGHT);
fd = open("/dev/audio",O_RDWR);
ioctl(fd,AUDIO_GET_GAINS,&gain);
gain.cgain[0].transmit_gain = saved_gains[0];
gain.cgain[0].receive_gain = saved_gains[1];
gain.cgain[0].monitor_gain = saved_gains[2];
gain.cgain[1].transmit_gain = saved_gains[3];
gain.cgain[1].receive_gain = saved_gains[4];
gain.cgain[1].monitor_gain = saved_gains[5];
ioctl(fd,AUDIO_SET_GAINS,&gain);
}
int initialize_audio(void) {AUDIO_ERROR = SNDLIB_NO_ERROR; return(0);}
char *audio_error_name(int err) {return(audio_error_name_1(err));}
int audio_systems(void) {return(1);}
char *audio_system_name(int system) {return("HPUX");}
/* struct audio_status status_b;
* ioctl(devAudio, AUDIO_GET_STATUS, &status_b)
* not_busy = (status_b.transmit_status == AUDIO_DONE);
*/
int open_audio_input(int ur_dev, int srate, int chans, int format, int size)
{
int fd,i,dev;
struct audio_describe desc;
AUDIO_ERROR = SNDLIB_NO_ERROR;
dev = SNDLIB_DEVICE(ur_dev);
fd = open("/dev/audio",O_RDWR);
if (fd == -1) {AUDIO_ERROR = SNDLIB_CANT_OPEN; return(-1);}
ioctl(fd,AUDIO_SET_CHANNELS,chans);
if (dev == SNDLIB_MICROPHONE_DEVICE)
ioctl(fd,AUDIO_SET_INPUT,AUDIO_IN_MIKE);
else ioctl(fd,AUDIO_SET_INPUT,AUDIO_IN_LINE);
if (format == SNDLIB_16_LINEAR)
ioctl(fd,AUDIO_SET_DATA_FORMAT,AUDIO_FORMAT_LINEAR16BIT);
else
if (format == SNDLIB_8_MULAW)
ioctl(fd,AUDIO_SET_DATA_FORMAT,AUDIO_FORMAT_ULAW);
else
if (format == SNDLIB_8_ALAW)
ioctl(fd,AUDIO_SET_DATA_FORMAT,AUDIO_FORMAT_ALAW);
else {AUDIO_ERROR = SNDLIB_FORMAT_NOT_AVAILABLE; close(fd); return(-1);}
ioctl(fd,AUDIO_DESCRIBE,&desc);
for(i=0;i<desc.nrates;i++) if(srate == desc.sample_rate[i]) break;
if (i == desc.nrates) {AUDIO_ERROR = SNDLIB_SRATE_NOT_AVAILABLE; close(fd); return(-1);}
ioctl(fd,AUDIO_SET_SAMPLE_RATE,srate);
return(fd);
}
int read_audio(int line, char *buf, int bytes)
{
AUDIO_ERROR = SNDLIB_NO_ERROR;
read(line,buf,bytes);
return(0);
}
#endif
/* ------------------------------- WINDOZE ----------------------------------------- */
#if defined(WINDOZE) && (!(defined(__CYGWIN__)))
#define AUDIO_OK
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#define BUFFER_FILLED 1
#define BUFFER_EMPTY 2
#define OUTPUT_LINE 1
#define INPUT_LINE 2
#define SOUND_UNREADY 0
#define SOUND_INITIALIZED 1
#define SOUND_RUNNING 2
static int buffer_size = 1024;
( run in 1.827 second using v1.01-cache-2.11-cpan-5837b0d9d2c )