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),&amp);
		      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 )