dac_codec.c

来自「speech signal process tools」· C语言 代码 · 共 422 行

C
422
字号
/* * This material contains unpublished, proprietary software of  * Entropic Research Laboratory, Inc. Any reproduction, distribution,  * or publication of this work must be authorized in writing by Entropic  * Research Laboratory, Inc., and must bear the notice:  * *    "Copyright (c) 1990-1992 Entropic Research Laboratory, Inc.  *                   All rights reserved" * * The copyright notice above does not evidence any actual or intended  * publication of this source code.      * * Written by:  Derek Lin * Checked by: * Revised by: * * Brief description: * */static char *sccs_id = "@(#)dac_codec.c	1.4	5/22/93	ERL";#include <Objects.h>#include <sys/ioctl.h>#include <signal.h>#include <stropts.h>#include <esps/epaths.h>#include <sys/param.h>#include <sun/audioio.h>#include <esps/esps.h>#include <esps/feasd.h>#define SPARC_SAMPLE_FREQ 8000#define MAX_GAIN 100struct feasd *rec;                /* ESPS record -- for ereader.c *//* externals required by calling program */extern int debug_level;extern int left, right, bflag, gflag, aflag, external;extern float gain;extern int da_location;extern unsigned int gain_codec;extern int gain_codecflag;static long long_da_loc;static int nresamp;               /* length of data buffer after resampling */static char *bytedata = NULL;            /* data after mu-law conversion */static int readlen = 0;                  /* read buffer length */static int sizeof_sample = sizeof(short);static long maxsamps;                     /* total number of samples */static long sams_read=0;                  /* samples read so far */static long error_at;                     /* sample position when error */static int da_done;                      /* signal for D/A completion */static int shifts;                       /* automatic scaling *//*  * four main arguments passed by calling program */static int  infd = -1;                   /* file descriptor */static void *inhead=NULL;                /* ESPS file header */static FILE *instream=NULL;              /* file stream */static short *aft_resamp_data = NULL;    /* memory buffer */static int Audio_fd;void (*sig_save[4])();audio_info_t info;                 /* see /dev/audio.h */double input_rate;/* * */void stop_codec_da_waves(sig)     int sig;{  long number_left;  da_done = 1;  completion();  if(debug_level)    fprintf(stderr,"Caught a signal in waves (%d); da_location:%d\n",	    sig, long_da_loc);  if((number_left = maxsamps - long_da_loc) > 0) {    char str[200];    sprintf(str,"set da_location %d\n", long_da_loc);    send_xwaves2(NULL, NULL, str, debug_level);    /* This pause seems to be necessary to prevent the possibility that       the child's death will be registered before the send_xwaves is! */    usleep(200000);  }  exit(0);}/* * */void interrupt_codec_da(sig)     int sig;{  error_at = sams_read;  da_done = 1;  completion();  if(debug_level)    fprintf(stderr,"Caught a signal from intrp (%d); da_location:%d\n",	    sig, long_da_loc);  exit(0);}/* * */void stop_codec_da(){  error_at = sams_read;  da_done = 1;  completion();  if(debug_level)    fprintf(stderr,"stopping codec D/A; da_location:%d\n",	    long_da_loc);}/* * *//* normal completion will have its da_done set here.  completion   due to abnormal condition(intrpt) has da_done set in interrupt routine*/static completion(){  int err;  unsigned int sleep = 10000;  extern int errno;    if(Audio_fd >0)    {      if(da_done){          /* if interrupt, flush everything */	if((err = ioctl(Audio_fd, I_FLUSH, FLUSHW)) < 0)	  {	    fprintf(stderr,"Error flushing device\n");	    exit(-1);	  }      }      else                  /* if normal exit, wait till finish draining */	{	  do	    {	      if(ioctl(Audio_fd, AUDIO_GETINFO, &info) < 0)		{		  fprintf(stderr,"Error draining, errno %d\n", errno);		  exit(-1);		}	      usleep(sleep);	    } while ( (int) info.play.active );	}      if((err = ioctl(Audio_fd, AUDIO_GETINFO, &info)) < 0){	fprintf(stderr,"Error reading Audio_info_t, errno %d\n", errno);	exit(-1);      }      long_da_loc += (int) info.play.samples * input_rate / SPARC_SAMPLE_FREQ;       close(Audio_fd);    }  else    {      fprintf(stderr,"Device was closed pre-maturely\n");      exit(-1);    }  da_done = TRUE;  /* Restore the original signal handlers. */  signal(SIGINT,sig_save[1]);  signal(SIGQUIT,sig_save[2]);  signal(SIGUSR1,sig_save[3]);}/* * */dac_codec(inputfile, inbuffer, sig_size, freq, sigmax)     int inputfile, sig_size, sigmax;     short *inbuffer;     double *freq;{  return(dacmaster_codec(inputfile, inbuffer, sig_size, freq,			  sigmax, NULL, NULL, 1));}/* * allocate arrays, sets up device, read and play from: *      a memory buffer, or a file pointed by file descriptor or file stream. * If frequency is not 8000 for an ESPS file, resampling is done. * operation: read -> resample -> mu-law convert -> play * Non-ESPS file and memory buffer are treated as SHORT, 8000 Hz */dacmaster_codec(inputfile, membuffer, sig_size, freq, sigmax, stream, eheader,		repeats )     int inputfile;                  /* file descriptor */     int sig_size, sigmax;           /* signal length and signal max value */     short *membuffer;               /* a memory buffer containing data */     double *freq;                   /* sampling frequency of input */     FILE *stream;                   /* file stream */     void *eheader;                  /* header of ESPS file */     int repeats;{  int shifts = 0, tmp, err;  long offset;  long_da_loc = da_location;  input_rate = *freq;  sams_read = 0;  error_at = -1;  if(!sigmax) sigmax = 32767;         /* automatic scaling to full range */  if(aflag){    tmp = sigmax;    if(tmp < 16384)      while((tmp << shifts) < 16384) shifts++;    left +=shifts;    shifts=0;    if(sigmax > 16384)      while((sigmax >> shifts) > 16384) shifts++;    right +=shifts;  }  if((maxsamps = sig_size) <= 0) {    printf("Bogus sample count sams_read to dac(%d)\n",sig_size);    return(-1);  }  if((inputfile >= 0) || stream) {      /* input from a file */    infd = inputfile;    instream = stream;    inhead = eheader;    aft_resamp_data = NULL;    offset = ftell(instream);  } else                                 /* input from a memory buffer */    if(membuffer) {      infd = -1;      aft_resamp_data = membuffer;      instream = NULL;      inhead = NULL;    } else {      printf("Bogus input file and buffer specified to dacmaster_codec()\n");      return(-1);    }  /* Setup the signal handlers. */  sig_save[1] = signal( SIGINT, interrupt_codec_da);  sig_save[2] = signal( SIGQUIT, interrupt_codec_da);  sig_save[3] = signal( SIGUSR1, stop_codec_da_waves);  da_done = FALSE;    /* open audio device and initialize */  if(( Audio_fd = open("/dev/audio",2)) < 0 ){    fprintf(stderr,"dac_codec: Can't open audio device.\n");    exit(-1);  }  AUDIO_INITINFO(&info);  if(external)    info.play.port = AUDIO_HEADPHONE;  else    info.play.port = AUDIO_SPEAKER;  if ( gain_codecflag && (int) gain_codec >= 0 && (int)gain_codec <= MAX_GAIN)    info.play.gain = AUDIO_MIN_GAIN + (unsigned) irint ((double)       (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) * (double) gain_codec /	(double) MAX_GAIN);  else{    if (gain_codecflag){      fprintf(stderr, "dac_codec: codec gain level is out of range.\n");      exit(-1);    }  }  if( (err = ioctl(Audio_fd, AUDIO_SETINFO, &info)) < 0){    fprintf(stderr, "dac_codec: Can't AUDIO_SETINFO.\n");    exit(-1);  }    readlen = input_rate * 0.5;                     /* 1/2-second read buffer */  nresamp = (int)(((float) readlen)*(SPARC_SAMPLE_FREQ/(float) input_rate));     /* allocate data arrays */  if(inhead)    rec = allo_feasd_recs( inhead, SHORT, readlen, (char *)NULL, NO);  if( !aft_resamp_data )    if(!(aft_resamp_data = (short *) malloc(sizeof(short) * nresamp))){      fprintf(stderr,"dacmaster_codec: Can't allocate aft_resamp_data.\n");      return(-1);    }  if(!(bytedata = (char *) malloc((unsigned) nresamp))){    fprintf(stderr,"dac_codec: Can't allocate bytedata.\n");    return(-1);  }  if(debug_level)    fprintf(stderr,"tot_samples:%d membuffer:%x freq:%f readlen:%d sizeof_sample: %d\n", sig_size, membuffer, input_rate, readlen, sizeof_sample);  /* main loop */  while(repeats--){    while(!da_done && (error_at < 0)) {      if(codec_handle() == 0) break;    }    /* Error or stdin input exit */    if(error_at >= 0){      if(debug_level)	fprintf(stderr,"codec_handle(): closing audio device\n");      completion();      return(error_at);    }    /* if repeating, reset everything back to start */    if(repeats){      sams_read = 0;      nresamp = (int)(((float) readlen)*(SPARC_SAMPLE_FREQ/input_rate));      if(fseek(instream, offset, 0) < 0){	fprintf(stderr,"dacmaster_codec(): Can't fseek\n");	exit(-1);      }    }  }  /* Normal exit */  if(debug_level)    fprintf(stderr,"codec_handle(): closing audio device\n");  completion();  return(sams_read);}/* * read, resample memory buffer and file  */static codec_handle(){  int sams_frm;  int err;  if((sams_frm = (maxsamps - sams_read)) > readlen)    sams_frm = readlen;  if(instream || (infd >= 0)) {		/* samples from unix file? */    int nread;    /* read sams_frm long data, force termination if sams_frm is not read */    if((nread = read_any_file(aft_resamp_data, sizeof_sample, sams_frm,			      nresamp,instream, inhead, infd, 			      input_rate)) != sams_frm){      if(debug_level)	fprintf(stderr,"Read error or end of stdin at %d(%d:%d)\n",sams_read,sams_frm,nread);      error_at = sams_read;      sams_frm = nread;      maxsamps = sams_read + sams_frm;  /* To force termination */      if(debug_level)	fprintf(stderr,"Reached file end at sample %d\n",sams_read);    }    /* if sams_frm is less than 1/2 sec (readlen) */    if(sams_frm < readlen) nresamp = (int) nread*SPARC_SAMPLE_FREQ/input_rate;    if (gflag)      {	register short *sp;	register float ft, g=gain, round = 0.5;	register int i, nshifts = shifts;	for (i=nresamp, sp = aft_resamp_data ; i--;)	  if((ft = *sp * g) >= 0.0)	    *sp++ = ft + round;	  else	    *sp++ = ft - round;      }     else      {	register short *sp;	register int i;	if ( left > right && (aflag || bflag))	  {	    register int shift;	    shift = left - right;	    for (i=nresamp, sp = aft_resamp_data; i--; )	      (*sp++) <<= shift;	  } 	else	  if (right > left && (aflag || bflag)) 	    {	      register int shift, i;	      shift = right - left;	      for (i=nresamp, sp = aft_resamp_data; i--; )		(*sp++) >>= shift;	    }      }  }  if(linear_to_mu(aft_resamp_data, bytedata, (long)nresamp) !=0 ){    fprintf(stderr, "codec_handle: Error converting to mu data.-exiting.\n");    exit(-1);  }  if( write( Audio_fd, bytedata, nresamp) < 0) perror("/dev/audio");    if(Audio_fd >0){      if((err=ioctl(Audio_fd, AUDIO_GETINFO, &info)) < 0){	fprintf(stderr,"Error reading Audio_info_t\n");	exit(-1);      }    }  sams_read += sams_frm;  /* adjust the pointer to memory buffer */  if(infd < 0 && !instream && !inhead)    aft_resamp_data += (nresamp * (sizeof_sample/sizeof(short)));  if(error_at >= 0 || sams_read >= maxsamps)    return(0);  else    return(1);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?