audio_hpold.c

来自「speech signal process tools」· C语言 代码 · 共 902 行 · 第 1/2 页

C
902
字号
/* * 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) 1995 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:  Checked by: Revised by: *  * Brief description: *  */static char    *sccs_id = "%W% %G% ERL";#include <stdio.h>#include <math.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <netinet/in.h>#include <audio/Alib.h>#include <sys/time.h>#include <sys/types.h>#include <errno.h>#include <unistd.h>#include <sys/param.h>/* * --------------------------------------------------------------- * Machine-dependent declaration * --------------------------------------------------------------- */static int     *sampleRates = NULL;static AGainDB  maxIn;static AGainDB  minIn;static AGainDB  maxOut;static AGainDB  minOut;static Audio   *audio = NULL;static int      sizeof_sample;static AInputChMask InputChannelsSupported;/* record */static AudioAttrMask recordAttribsMask;static AudioAttributes recordAttribs;static SSRecordParams recordStreamParams;static SStream  recordStream;static ATransID recordXid;static int      recordSocket = -1;static int      recordGainR, recordGainL;static AGainEntry recordGainEntry[4];static int      recordDestSet = 0;static int      recordGainSet = 0;static double   recordRate;static int      recordChannel;static int      recordNSampsPerChan;static          recordInitCalled = 0;/* play */static AudioAttrMask playSrcAttribsMask;static AudioAttrMask playAttribsMask;static AudioAttributes playSrcAttribs;static AudioAttributes playAttribs;static SSPlayParams playStreamParams;static SStream  playStream;static ATransID playXid = NULL;static int      playSocket = -1;/* <0 when audio is in close state */#ifndef WRITEstatic FILE    *playFP = NULL;#endifstatic int      playChan = 1;static int      playPortBufSize;static int      fileRate;static unsigned long     playSamps = 0;static long     playPauseCount = 0;static int      playPause = 0;static struct timeval playBgnTime;static AGainEntry playGainEntry[4];static int      playGainSet = 0;static int      playGainR, playGainL;static int      playDrain = 0;static double   playRate;static int      playNSampsPerChan;static int      playInitCalled = 0;static int      useIntSpeaker = 0;static AErrorHandler prevHandler;#ifdef WRITE_TESTstatic FILE *      test_fp = NULL;#endifstatic int      first_write=0;char            audio_error_msg[512];#define perror private_perrorextern int      sys_nerr;extern char    *sys_errlist[];int             closest_srate();static voidprivate_perror(s)   char           *s;{   if (errno < sys_nerr)      sprintf(audio_error_msg, "%s: %s\n", s, sys_errlist[errno]);   else      sprintf(audio_error_msg, "%s: Unknown ioctl error\n", s);}static longErrorHandler(audio, err_event)   Audio          *audio;   AErrorEvent    *err_event;{   char            errorbuff[132];   AGetErrorText(audio, err_event->error_code, errorbuff, 131);   fprintf(stderr, "HP Audio Error: %s\n", errorbuff);   return 0;}#define PLAYHOLD 300000static intGetFilled(fd)   int             fd;{   int             canread;   if (ioctl(fd, FIONREAD, &canread) < 0) {      perror("error in GetFilled");      return (0);   }   return canread / sizeof_sample;}intPortIsAvailable(){   long            status;   char            server[MAXHOSTNAMELEN], *s = NULL;   unsigned long  *srates;   long            nRates, i;   if (audio)      return 0;   s = getenv("AUDIO");   if (s)      strcpy(server, s);   else      strcpy(server, ":0");   prevHandler = ASetErrorHandler(ErrorHandler);   audio = AOpenAudio(server, &status);   if (status) {      sprintf(audio_error_msg,	      "Trouble opening audio, error code: %ld\n", status);      return (1);   }   nRates = ANumSamplingRates(audio);   if (!nRates) {      sprintf(audio_error_msg,	      "Trouble opening audio, ANumSamplingRates returns 0.\n");      return 1;   }   srates = ASamplingRates(audio);   if (sampleRates)      free(sampleRates);   sampleRates = (int *) malloc(sizeof(int) * (nRates + 1));   sampleRates[nRates] = 0;   for (i = 0; i < nRates; i++)      sampleRates[i] = srates[i];   maxIn = AMaxInputGain(audio);   maxOut = AMaxOutputGain(audio);   minIn = AMinInputGain(audio);   minOut = AMinOutputGain(audio);   InputChannelsSupported = AInputChannels(audio);   return (0);}/* * ----------------------------------------------------------------- Record * ----------------------------------------------------------------- */intAudioMaxChannels(){   /*    * InputChannelsSupported is a bit mask that represents the available A/D    * input channels on the hardware. Here we use that fact that mono    * capabilities is numerically equal to 1 and that the upper limit is two    * channels.    */   if ((InputChannelsSupported & AMonoInputChMask) &&       !(InputChannelsSupported & ALeftInputChMask) &&       !(InputChannelsSupported & ARightInputChMask))      return 1;   else if ((InputChannelsSupported & ALeftInputChMask) &&	    (InputChannelsSupported & ARightInputChMask))      return 2;   else      return 0;}int            *AudioGetRates(){   return (sampleRates);}intInitAudioRecord(srate, channel, nSampsPerChan)   double          srate;   int             channel;   int             nSampsPerChan;{   long            status;   if (PortIsAvailable()) {      (void) sprintf(audio_error_msg, "Sorry, this record program requires hp700 audio.\n");      return (1);   }   recordChannel = channel;   recordNSampsPerChan = nSampsPerChan;   sizeof_sample = sizeof(short);   /* Set the sample rate. */   recordAttribs = *ABestAudioAttributes(audio);   recordRate = recordAttribs.attr.sampled_attr.sampling_rate =      closest_srate(srate, sampleRates);   /*    * HP's audio server has a bufer of limited audio->block_size size. At    * least on HP700, this is 4096 (N) bytes.  Number of data points    * transferred must not exceed  N bytes in every consecutive read;    * otherwise, overflow occurs, unread data gets overwritten in the buffer.    * The result is samples lost during recording.  Here I use a rule of data    * transfered every some sec must not exceed N bytes (enough so that    * single channel 48 Hz is recordable)    */   if (0.08 * srate * channel * sizeof_sample > audio->block_size) {      sprintf(audio_error_msg,	      "InitAudioRecord: Sampling rate too high or too many channels specified.\n");      ACloseAudio(audio, NULL);      return (1);   }   /* Set up defaults in the HP audio attrib structure */   recordAttribsMask = 0;   recordAttribsMask = (recordAttribsMask | ASSamplingRateMask |			ASChannelsMask | ASDataFormatMask);   recordAttribs.attr.sampled_attr.channels = (channel < 2) ? 1 : 2;   recordAttribs.attr.sampled_attr.data_format = ADFLin16;   recordAttribs.attr.sampled_attr.bits_per_sample = 16;   switch (recordAttribs.attr.sampled_attr.channels) {   case 1:      recordGainEntry[0].u.i.in_ch = AICTMono;      recordGainEntry[0].gain = AUnityGain;      break;   case 2:   default:      recordGainEntry[0].u.i.in_ch = AICTLeft;      recordGainEntry[1].u.i.in_ch = AICTRight;      recordGainEntry[0].gain = AUnityGain;      recordGainEntry[1].gain = AUnityGain;      break;   }   recordStreamParams.event_mask = 0;   recordStreamParams.gain_matrix.type = AGMTInput;   recordStreamParams.gain_matrix.num_entries =      recordAttribs.attr.sampled_attr.channels;   recordStreamParams.gain_matrix.gain_entries = recordGainEntry;   recordXid = ARecordSStream(audio, ~0, &recordAttribs, &recordStreamParams,			      &recordStream, &status);   if (status) {      sprintf(audio_error_msg,	      "InitAudioRecord: can't open audio stream, code %ld.\n",	      status);      ACloseAudio(audio, NULL);      return 1;   }   recordInitCalled = 1;   return (0);}intCloseAudioRecord(){   long            status;   if (recordSocket < 0)      return (0);   close(recordSocket);   recordSocket = -1;   recordInitCalled = 0;   ACloseAudio(audio, &status);   audio = NULL;   return (status);}intPauseAudioRecord(){   (void) CloseAudioRecord();   return (0);}intStartAudioRecord(){   long            status;   recordXid = ARecordSStream(audio, ~0, &recordAttribs, &recordStreamParams,			      &recordStream, &status);   if (status) {      sprintf(audio_error_msg,	      "StartAudioRecord: can't open audio stream, code %ld.\n",	      status);      (void) ACloseAudio(audio, NULL);      return 1;   }   recordSocket = socket(AF_INET, SOCK_STREAM, 0);   if (recordSocket < 0) {      perror("StartAudioRecord: Socket creation failed");      return 1;   }   status = connect(recordSocket,		    (struct sockaddr *) & recordStream.tcp_sockaddr,		    sizeof(struct sockaddr_in));   if (status < 0) {      perror("StartAudioRecord: Connect failed");      return (1);   }   if (recordGainSet) {      switch (recordAttribs.attr.sampled_attr.channels) {      case 1:	 ASetChannelGain(audio, recordXid, ACTMono, recordGainL, &status);	 if (status) {	    sprintf(audio_error_msg,		    "StartAudioRecord: can't set channel gain, code %ld.\n",		    status);	    (void) ACloseAudio(audio, NULL);	    return 1;	 }	 break;      case 2:      default:	 ASetChannelGain(audio, recordXid, ACTLeft, recordGainL, &status);	 ASetChannelGain(audio, recordXid, ACTRight, recordGainR, &status);	 if (status) {	    sprintf(audio_error_msg,		    "StartAudioRecord: can't set channel gain, code %ld.\n",		    status);	    (void) ACloseAudio(audio, NULL);	    return 1;	 }	 break;      }   }   return (0);}intContAudioRecord(){   int status;   status = InitAudioRecord(recordRate, recordChannel, recordNSampsPerChan);   if (status) 	return 1;   status = StartAudioRecord();   if (status) 	return 1;   return (0);}/* * in case of STEREO recording, RecordAudio returns total number of samples * in both channels */intRecordAudio(inputBuffer)   short          *inputBuffer;{   int             canread, haveread = 0;   /*    * Sigh, can't find a way to reliably check for overflow condition. That    * is why a precaution check is installed in InitAudioRecord    */   canread = GetFilled(recordSocket);   if (canread)          haveread = read(recordSocket, inputBuffer, 	           canread * sizeof_sample) / sizeof_sample;   return (haveread);}intSetAudioInputType(src)   char           *src;{   int             useLineIn = 0;   if (!strcmp(src, "mic"))      useLineIn = 0;   else      useLineIn = 1;   /*    * Because InitAudioRecord must be called first to know how many channel    * we have, We can't set gainEntry which setting is channel dependent    * before the device is open.    */   if (recordInitCalled) {      /*       * close up the connection and restart.  Unfortunately HP won't let you       * change output destination while device is open.       */      (void) CloseAudioRecord();      switch (recordAttribs.attr.sampled_attr.channels) {      case 1:	 recordGainEntry[0].u.i.in_ch = AICTMono;	 recordGainEntry[0].u.i.in_src = (useLineIn) ? AISTMonoAuxiliary :	    AISTMonoMicrophone;	 break;      case 2:      default:	 recordGainEntry[0].u.i.in_ch = AICTLeft;	 recordGainEntry[0].u.i.in_src = (useLineIn) ? AISTLeftAuxiliary :	    AISTLeftMicrophone;	 recordGainEntry[1].u.i.in_ch = AICTRight;	 recordGainEntry[1].u.i.in_src = (useLineIn) ? AISTRightAuxiliary :	    AISTRightMicrophone;	 break;      }      recordDestSet = 1;      InitAudioRecord(recordRate, recordChannel, recordNSampsPerChan);   }

⌨️ 快捷键说明

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