mirror of
				https://github.com/ElvishArtisan/rivendell.git
				synced 2025-11-03 23:53:59 +01:00 
			
		
		
		
	* Removed all CVS tags. * Removed 'const char *name' parameter from all QObject contructors.
		
			
				
	
	
		
			1185 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1185 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* wavlib.c 
 | 
						|
 *
 | 
						|
 * A C Library for abstracting WAV files
 | 
						|
 *
 | 
						|
 * (C) Copyright 1997,1999-2003,2016 Fred Gleason <fredg@paravelsystems.com>
 | 
						|
 *
 | 
						|
 *   This program is free software; you can redistribute it and/or modify
 | 
						|
 *   it under the terms of the GNU General Public License version 2 as
 | 
						|
 *   published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 *   This program is distributed in the hope that it will be useful,
 | 
						|
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 *   GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 *   You should have received a copy of the GNU General Public
 | 
						|
 *   License along with this program; if not, write to the Free Software
 | 
						|
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <math.h>
 | 
						|
#include <sys/soundcard.h>
 | 
						|
#include <sys/time.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <sys/ioctl.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <strings.h>
 | 
						|
#include <string.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <math.h>
 | 
						|
#include "wavlib.h"
 | 
						|
 | 
						|
/* #define BUFFER_SIZE 65536 */
 | 
						|
#define BUFFER_SIZE 8192
 | 
						|
#define DEFAULT_WAV_MODE 0644
 | 
						|
 | 
						|
/*
 | 
						|
 * Global Variables
 | 
						|
 */
 | 
						|
int iWav=0;
 | 
						|
int dWavPause=0;
 | 
						|
int hGlobalAudio;
 | 
						|
 | 
						|
int IsWav(int hFilename)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  char cBuffer[5];
 | 
						|
 | 
						|
  /* Is this a riff file? */
 | 
						|
  lseek(hFilename,0,SEEK_SET);
 | 
						|
  i=read(hFilename,cBuffer,4);
 | 
						|
  if(i==4) {
 | 
						|
    cBuffer[4]=0;
 | 
						|
    if(strcmp("RIFF",cBuffer)!=0) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  /* Is this a WAVE file? */
 | 
						|
  if(lseek(hFilename,8,SEEK_SET)!=8) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  i=read(hFilename,cBuffer,4);
 | 
						|
  if(i==4) {
 | 
						|
    cBuffer[4]=0;
 | 
						|
    if(strcmp("WAVE",cBuffer)!=0) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int OpenWav(char *sFilename,struct wavHeader *wavFilename)
 | 
						|
{
 | 
						|
  int hFilename;
 | 
						|
  struct wavChunk wavChunk;
 | 
						|
  unsigned char cBuffer[16];
 | 
						|
  int i;
 | 
						|
  off_t oDataChunk;
 | 
						|
 | 
						|
  hFilename=open(sFilename,O_RDWR);
 | 
						|
  if(hFilename<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  if(!IsWav(hFilename)) {
 | 
						|
    return -2;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Find the format chunk
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"fmt ");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {
 | 
						|
    close(hFilename);
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Found the format chunk, now get the data
 | 
						|
   */
 | 
						|
  lseek(hFilename,8,SEEK_CUR);  
 | 
						|
  i=read(hFilename,cBuffer,14);
 | 
						|
  if(i<14) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  wavFilename->wFormatTag=cBuffer[0]+256*cBuffer[1];
 | 
						|
  wavFilename->wChannels=cBuffer[2]+256*cBuffer[3];
 | 
						|
  wavFilename->dwSamplesPerSec=cBuffer[4]+256*cBuffer[5]+
 | 
						|
    65536*cBuffer[6]+16777216*cBuffer[7];
 | 
						|
  wavFilename->dwAvgBytesPerSec=cBuffer[8]+256*cBuffer[9]+
 | 
						|
    65536*cBuffer[10]+16777216*cBuffer[11];
 | 
						|
  wavFilename->wBlockAlign=cBuffer[12]+256*cBuffer[13];
 | 
						|
  if(wavFilename->wFormatTag==WAVE_FORMAT_PCM) { /*Get bits per sample*/
 | 
						|
    i=read(hFilename,cBuffer,2);
 | 
						|
    if(i<2) {
 | 
						|
      close(hFilename);
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    wavFilename->wBitsPerSample=cBuffer[0]+256*cBuffer[1];
 | 
						|
  }
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Find the data chunk
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"data");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {
 | 
						|
    close(hFilename);
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  wavFilename->dwWaveDataSize=wavChunk.oSize;
 | 
						|
  oDataChunk=wavChunk.oOffset;  /* Save this for restoration later */
 | 
						|
 | 
						|
  /*
 | 
						|
   * Determine total number of samples (preferably from the fact chunk)
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"fact");
 | 
						|
  lseek(hFilename,12,SEEK_SET);
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {  /* Not present, calculate the size */
 | 
						|
    wavFilename->dwFileSize=wavFilename->dwWaveDataSize/
 | 
						|
      wavFilename->wBlockAlign;
 | 
						|
  }
 | 
						|
  else {   /* Pull it from the fact chunk */
 | 
						|
    lseek(hFilename,8,SEEK_CUR);
 | 
						|
    i=read(hFilename,cBuffer,4);
 | 
						|
    if(i!=4) {
 | 
						|
      close(hFilename);
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    wavFilename->dwFileSize=cBuffer[0]+256*cBuffer[1]+65536*cBuffer[2]+
 | 
						|
      16777216*cBuffer[3];
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Calculate audio length in seconds
 | 
						|
   */
 | 
						|
  wavFilename->tWavLength=wavFilename->dwFileSize/wavFilename->dwSamplesPerSec;
 | 
						|
  lseek(hFilename,oDataChunk+8,SEEK_SET);
 | 
						|
  return hFilename;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int CreateWav(char *sFilename,struct wavHeader *wavHeader)
 | 
						|
{
 | 
						|
  int hFilename;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Some sanity checks
 | 
						|
   */
 | 
						|
  if(wavHeader->wFormatTag!=WAVE_FORMAT_PCM) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  /*
 | 
						|
   * Don't use O_TRUNC here, it can cause a significant (several second or 
 | 
						|
   * more) delay on large files.  We'll come back and trim the fat after the 
 | 
						|
   * recording's done.
 | 
						|
   */
 | 
						|
  hFilename=open(sFilename,O_RDWR|O_CREAT,DEFAULT_WAV_MODE);
 | 
						|
  if(hFilename<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Write the WAVE Header
 | 
						|
   */
 | 
						|
  write(hFilename,"RIFF",4);
 | 
						|
  WriteDword(hFilename,0);
 | 
						|
  write(hFilename,"WAVE",4);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Write the format chunk
 | 
						|
   */
 | 
						|
  write(hFilename,"fmt ",4);
 | 
						|
  WriteDword(hFilename,16);
 | 
						|
  WriteSword(hFilename,wavHeader->wFormatTag);
 | 
						|
  WriteSword(hFilename,wavHeader->wChannels);
 | 
						|
  WriteDword(hFilename,wavHeader->dwSamplesPerSec);
 | 
						|
  WriteDword(hFilename,wavHeader->dwAvgBytesPerSec);
 | 
						|
  WriteSword(hFilename,wavHeader->wBlockAlign);
 | 
						|
  WriteSword(hFilename,wavHeader->wBitsPerSample);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Write the fact chunk
 | 
						|
   */
 | 
						|
  write(hFilename,"fact",4);
 | 
						|
  WriteDword(hFilename,4);
 | 
						|
  WriteDword(hFilename,0);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Write the data chunk
 | 
						|
   */
 | 
						|
  write(hFilename,"data",4);
 | 
						|
  WriteDword(hFilename,0);
 | 
						|
 | 
						|
  return hFilename;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int FixWav(int hFilename,unsigned dSamples,unsigned dBytes)
 | 
						|
{
 | 
						|
  struct stat statData;
 | 
						|
  struct wavChunk wavChunk;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Get the file size
 | 
						|
   */
 | 
						|
  if(fstat(hFilename,&statData)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Update the file-size counter 
 | 
						|
   */
 | 
						|
  lseek(hFilename,4,SEEK_SET);
 | 
						|
  WriteDword(hFilename,statData.st_size-8);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Update the fact chunk
 | 
						|
   */ 
 | 
						|
  strcpy(wavChunk.sName,"fact");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)>0) {
 | 
						|
    lseek(hFilename,8,SEEK_CUR);
 | 
						|
    WriteDword(hFilename,dSamples);
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Update the data chunk
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"data");
 | 
						|
  FindChunk(hFilename,&wavChunk);
 | 
						|
  lseek(hFilename,4,SEEK_CUR);
 | 
						|
  WriteDword(hFilename,dBytes);
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int FindChunk(int hFilename,struct wavChunk *wavChunk)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  char sName[5]={0,0,0,0,0};
 | 
						|
  unsigned char dBuffer[4];
 | 
						|
  off_t oSize;
 | 
						|
 | 
						|
  lseek(hFilename,12,SEEK_SET);
 | 
						|
  i=read(hFilename,sName,4);
 | 
						|
  i=read(hFilename,dBuffer,4);
 | 
						|
  oSize=dBuffer[0]+(256*dBuffer[1])+(65536*dBuffer[2])+(16777216*dBuffer[3]);
 | 
						|
  while(i==4) {
 | 
						|
    if(strcasecmp(wavChunk->sName,sName)==0) {
 | 
						|
      wavChunk->oOffset=lseek(hFilename,-8,SEEK_CUR);
 | 
						|
      wavChunk->oSize=oSize;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    lseek(hFilename,oSize,SEEK_CUR);
 | 
						|
    i=read(hFilename,sName,4);
 | 
						|
    i=read(hFilename,dBuffer,4);
 | 
						|
    oSize=dBuffer[0]+(256*dBuffer[1])+(65536*dBuffer[2])+(16777216*dBuffer[3]);
 | 
						|
  }
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
  
 | 
						|
 | 
						|
 | 
						|
int GetNextChunk(int hFilename,struct wavChunk *wavChunk)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  char sName[5]={0,0,0,0,0};
 | 
						|
  unsigned char dBuffer[4];
 | 
						|
  off_t oSize;
 | 
						|
 | 
						|
  i=read(hFilename,sName,4);
 | 
						|
  i=read(hFilename,dBuffer,4);
 | 
						|
  oSize=dBuffer[0]+(dBuffer[1]*256)+(dBuffer[2]*65536)+(dBuffer[3]*16777216);
 | 
						|
  if(i==4) {
 | 
						|
    strcpy(wavChunk->sName,sName);
 | 
						|
    wavChunk->oOffset=lseek(hFilename,0,SEEK_CUR);
 | 
						|
    wavChunk->oSize=oSize;
 | 
						|
    lseek(hFilename,oSize,SEEK_CUR);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int GetListChunk(int hFilename,struct wavList *wavList)
 | 
						|
{
 | 
						|
  struct wavChunk wavChunk;
 | 
						|
  int i;
 | 
						|
  char cBuffer[LIST_SIZE];
 | 
						|
  off_t oLimit,oOffset;
 | 
						|
  char sName[5]={0,0,0,0,0};
 | 
						|
  unsigned dBuffer[4];
 | 
						|
  char sBuffer[LIST_SIZE];
 | 
						|
  off_t oTemp,oSize;
 | 
						|
  int dReturn=1;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Initialize Data Structures 
 | 
						|
   */
 | 
						|
  memset(wavList,0,sizeof(struct wavList));
 | 
						|
 | 
						|
  /*
 | 
						|
   * Find the list chunk
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"LIST");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  oLimit=wavChunk.oOffset+wavChunk.oSize;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Setup to start & do some basic sanity checking 
 | 
						|
   */
 | 
						|
  oOffset=lseek(hFilename,8,SEEK_CUR);
 | 
						|
  i=read(hFilename,cBuffer,4);
 | 
						|
  oOffset+=i;
 | 
						|
  cBuffer[4]=0;
 | 
						|
  if(strcasecmp(cBuffer,"INFO")!=0) {  /* I don't understand this format! */
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Scan through the chunk
 | 
						|
   */
 | 
						|
  while(oOffset<oLimit) {
 | 
						|
    oOffset+=read(hFilename,sName,4);
 | 
						|
    oOffset+=read(hFilename,dBuffer,4);
 | 
						|
    oSize=dBuffer[0]+(dBuffer[1]<<8)+(dBuffer[2]<<16)+(dBuffer[3]<<24);
 | 
						|
    oTemp=read(hFilename,sBuffer,dBuffer[0]);
 | 
						|
    lseek(hFilename,oSize-oTemp,SEEK_CUR);
 | 
						|
    read(hFilename,dBuffer,1);
 | 
						|
    if(dBuffer[0]!=0) {
 | 
						|
      lseek(hFilename,-1,SEEK_CUR);
 | 
						|
    }
 | 
						|
 | 
						|
    /* 
 | 
						|
     * Assign the field value
 | 
						|
     */
 | 
						|
    if(strcasecmp(sName,"ICRD")==0) {
 | 
						|
      strcpy(wavList->sIcrd,sBuffer);
 | 
						|
      dReturn=0;
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"IART")==0) {
 | 
						|
      strcpy(wavList->sIart,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ICMT")==0) {
 | 
						|
      strcpy(wavList->sIcmt,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ICOP")==0) {
 | 
						|
      strcpy(wavList->sIcop,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"IENG")==0) {
 | 
						|
      strcpy(wavList->sIeng,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"IGNR")==0) {
 | 
						|
      strcpy(wavList->sIgnr,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"IKEY")==0) {
 | 
						|
      strcpy(wavList->sIkey,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"IMED")==0) {
 | 
						|
      strcpy(wavList->sImed,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"INAM")==0) {
 | 
						|
      strcpy(wavList->sInam,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ISFT")==0) {
 | 
						|
      strcpy(wavList->sIsft,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ISRC")==0) {
 | 
						|
      strcpy(wavList->sIsrc,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ITCH")==0) {
 | 
						|
      strcpy(wavList->sItch,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ISBJ")==0) {
 | 
						|
      strcpy(wavList->sIsbj,sBuffer);
 | 
						|
    }
 | 
						|
    if(strcasecmp(sName,"ISRF")==0) {
 | 
						|
      strcpy(wavList->sIsrf,sBuffer);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return dReturn;
 | 
						|
}  
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int SetDspDesc(int hAudio,struct wavHeader *wavHeader)
 | 
						|
{
 | 
						|
  int dRequest;
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Set sampling format & bits per sample 
 | 
						|
   */
 | 
						|
  if(wavHeader->wFormatTag==WAVE_FORMAT_PCM) {
 | 
						|
    switch(wavHeader->wBitsPerSample) {
 | 
						|
    case 8:
 | 
						|
      dRequest=AFMT_U8;
 | 
						|
      ioctl(hAudio,SNDCTL_DSP_SETFMT,&dRequest);
 | 
						|
      if(dRequest!=AFMT_U8) {
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case 16:
 | 
						|
      dRequest=AFMT_S16_LE;
 | 
						|
      ioctl(hAudio,SNDCTL_DSP_SETFMT,&dRequest);
 | 
						|
      if(dRequest!=AFMT_S16_LE) {
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return -1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  /* Set number of channels */
 | 
						|
  if(wavHeader->wChannels>0 && wavHeader->wChannels<3) {
 | 
						|
    dRequest=wavHeader->wChannels-1;
 | 
						|
    ioctl(hAudio,SNDCTL_DSP_STEREO,&dRequest);
 | 
						|
    if(dRequest!=wavHeader->wChannels-1) {
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Set sampling rate 
 | 
						|
   */
 | 
						|
  dRequest=(int)wavHeader->dwSamplesPerSec;
 | 
						|
  ioctl(hAudio,SNDCTL_DSP_SPEED,&dRequest);
 | 
						|
  if((dRequest<(int)(.99*wavHeader->dwSamplesPerSec)) ||
 | 
						|
     (dRequest>(int)(1.01*wavHeader->dwSamplesPerSec))) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int PlayWavFile(char *sFilename,char *sAudioDev,unsigned dOptions)
 | 
						|
{
 | 
						|
  int hAudio;
 | 
						|
  int i;
 | 
						|
 | 
						|
  if((hAudio=open(sAudioDev,O_WRONLY))<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  i=PlayWavDesc(sFilename,hAudio,dOptions);
 | 
						|
  close(hAudio);
 | 
						|
  if(i<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int PlayWavDesc(char *sFilename,int hAudio,unsigned dOptions)
 | 
						|
{
 | 
						|
  return PlayWavOffsetDesc(sFilename,hAudio,0,dOptions);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int PlayWavOffsetDesc(char *sFilename,int hAudio,int dOffset,unsigned dOptions)
 | 
						|
{
 | 
						|
  struct wavHeader wavFilename;
 | 
						|
  struct wavChunk wavChunk;
 | 
						|
  int hFilename;
 | 
						|
  int j,k;
 | 
						|
  unsigned char cBuffer[BUFFER_SIZE];
 | 
						|
  unsigned dWaveOffset=0;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Pass the device fd to a global so the signal handlers can get it
 | 
						|
   */
 | 
						|
  hGlobalAudio=hAudio;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Signal Handling Stuff
 | 
						|
   */
 | 
						|
  if((dOptions&WAVLIB_PAUSEABLE)!=0) {
 | 
						|
    (void) signal(SIGTERM,SigStopWav);
 | 
						|
    (void) signal(SIGUSR1,SigPauseWav);
 | 
						|
    (void) signal(SIGUSR2,SigResumeWav);
 | 
						|
  }
 | 
						|
    
 | 
						|
  hFilename=OpenWav(sFilename,&wavFilename);
 | 
						|
  if(hFilename<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  if(SetDspDesc(hAudio,&wavFilename)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Calculate Wave Data Offset
 | 
						|
   */
 | 
						|
  dWaveOffset=dOffset*wavFilename.wBlockAlign;
 | 
						|
 | 
						|
  /* 
 | 
						|
   * OK -- time to play the file! 
 | 
						|
   */
 | 
						|
  strcpy(wavChunk.sName,"data");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  lseek(hFilename,8+dWaveOffset,SEEK_CUR);
 | 
						|
  if((dOptions & WAVLIB_TEST)==0) {
 | 
						|
    j=(wavFilename.dwWaveDataSize-dWaveOffset)/BUFFER_SIZE;
 | 
						|
    k=(wavFilename.dwWaveDataSize-dWaveOffset)-j*BUFFER_SIZE;
 | 
						|
    for(iWav=0;iWav<j;iWav++) {
 | 
						|
      read(hFilename,cBuffer,BUFFER_SIZE);
 | 
						|
      if(dWavPause==1) {
 | 
						|
	select(0,NULL,NULL,NULL,NULL);    /* Sleep till we get a signal */
 | 
						|
      }
 | 
						|
      write(hAudio,cBuffer,BUFFER_SIZE);
 | 
						|
    }
 | 
						|
    memset(cBuffer,0,BUFFER_SIZE);
 | 
						|
    read(hFilename,cBuffer,k);
 | 
						|
    if(dWavPause==1) {
 | 
						|
      select(0,NULL,NULL,NULL,NULL);    /* Sleep till we get a signal */
 | 
						|
    }
 | 
						|
    write(hAudio,cBuffer,k);
 | 
						|
  }
 | 
						|
  /* Finish up */
 | 
						|
  close(hFilename);
 | 
						|
  return 0;    
 | 
						|
}
 | 
						|
 | 
						|
void SigStopWav(int sig)
 | 
						|
{
 | 
						|
  ioctl(hGlobalAudio,SNDCTL_DSP_RESET,NULL);
 | 
						|
  exit(0);
 | 
						|
}
 | 
						|
 | 
						|
void SigPauseWav(int sig)
 | 
						|
{
 | 
						|
  dWavPause=1;
 | 
						|
  ioctl(hGlobalAudio,SNDCTL_DSP_RESET,NULL);
 | 
						|
  (void) signal(SIGUSR1,SigPauseWav);
 | 
						|
}
 | 
						|
 | 
						|
void SigResumeWav(int sig)
 | 
						|
{     
 | 
						|
  dWavPause=0;
 | 
						|
  (void) signal(SIGUSR2,SigResumeWav);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RecWavFile(char *sFilename,char *sAudioDev,unsigned dSeconds,
 | 
						|
	   unsigned short dChannels,unsigned ldSamplesPerSec,
 | 
						|
           unsigned short dBitsPerSample,unsigned dOptions)
 | 
						|
{
 | 
						|
  int hAudio;
 | 
						|
  int i;
 | 
						|
 | 
						|
  hAudio=open(sAudioDev,O_RDONLY);
 | 
						|
  if(hAudio<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  i=RecWavDesc(sFilename,hAudio,dSeconds,dChannels,ldSamplesPerSec,
 | 
						|
	     dBitsPerSample,dOptions);
 | 
						|
  close(hAudio);
 | 
						|
  if(i<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int RecWavDesc(char *sFilename,int hAudio,unsigned dSeconds,
 | 
						|
	   unsigned short dChannels,unsigned ldSamplesPerSec,
 | 
						|
           unsigned short dBitsPerSample,unsigned dOptions)
 | 
						|
{
 | 
						|
  int hFilename=0;
 | 
						|
  int dRequest;
 | 
						|
  char cBuffer[BUFFER_SIZE];
 | 
						|
  unsigned dBytesPerSec,dBytesPerSample=0;
 | 
						|
  unsigned dBufferWrites;
 | 
						|
  unsigned dTotalSampleBytes;
 | 
						|
  unsigned dTotalWavSize;
 | 
						|
  unsigned i;
 | 
						|
  unsigned short dFormatTag=WAVE_FORMAT_PCM;
 | 
						|
  unsigned short dBlockAlign;
 | 
						|
 | 
						|
  /* Check for format encoding type */
 | 
						|
  if(dFormatTag!=WAVE_FORMAT_PCM) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  /* Set sampling format & bits per sample */
 | 
						|
  if(dFormatTag==WAVE_FORMAT_PCM) {
 | 
						|
    switch(dBitsPerSample) {
 | 
						|
    case 8:
 | 
						|
      dRequest=AFMT_U8;
 | 
						|
      ioctl(hAudio,SNDCTL_DSP_SETFMT,&dRequest);
 | 
						|
      if(dRequest!=AFMT_U8) {
 | 
						|
	close(hFilename);
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case 16:
 | 
						|
      dRequest=AFMT_S16_LE;
 | 
						|
      ioctl(hAudio,SNDCTL_DSP_SETFMT,&dRequest);
 | 
						|
      if(dRequest!=AFMT_S16_LE) {
 | 
						|
	close(hFilename);
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      close(hFilename);
 | 
						|
      return -1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    close(hFilename);
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  /* Set number of channels */
 | 
						|
  if(dChannels>0 && dChannels<3) {
 | 
						|
    dRequest=dChannels-1;
 | 
						|
    ioctl(hAudio,SNDCTL_DSP_STEREO,&dRequest);
 | 
						|
    if(dRequest!=dChannels-1) {
 | 
						|
      close(hFilename);
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    close(hFilename);
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Set sampling rate */
 | 
						|
  dRequest=(int)ldSamplesPerSec;
 | 
						|
  ioctl(hAudio,SNDCTL_DSP_SPEED,&dRequest);
 | 
						|
  /*      if(dRequest<(int).99*ldSamplesPerSec ||
 | 
						|
	  dRequest>(int)1.01*ldSamplesPerSec) {
 | 
						|
	  close(hFilename);
 | 
						|
	  return -1;
 | 
						|
	  }  */
 | 
						|
 | 
						|
  /* OK, we know the soundcard can handle it */
 | 
						|
  /* If this is just a test, exit */
 | 
						|
  if((dOptions & WAVLIB_TEST)!=0) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Calculate actual bytes/sec overall */
 | 
						|
  if(dBitsPerSample<=8) {
 | 
						|
    dBytesPerSample=1;
 | 
						|
  }
 | 
						|
  if(dBitsPerSample>8 && dBitsPerSample<=16) {
 | 
						|
    dBytesPerSample=2;
 | 
						|
  }
 | 
						|
  if(dBitsPerSample>16) {
 | 
						|
    dBytesPerSample=3;
 | 
						|
  }
 | 
						|
  dBlockAlign=dBytesPerSample*dChannels;
 | 
						|
  dBytesPerSec=ldSamplesPerSec*dBytesPerSample*dChannels;
 | 
						|
  /* Calculate buffer writes and total sample bytes needed */
 | 
						|
  dTotalSampleBytes=dBytesPerSec*dSeconds;
 | 
						|
  dBufferWrites=dTotalSampleBytes/BUFFER_SIZE+1;
 | 
						|
  dTotalSampleBytes=dBufferWrites*BUFFER_SIZE;
 | 
						|
  dTotalWavSize=dTotalSampleBytes+36;
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Open the file and write the header 
 | 
						|
   *
 | 
						|
   * First, open the file, using the appropriate permissions 
 | 
						|
   *
 | 
						|
   * Don't use O_TRUNC here, it can cause a significant (several second or 
 | 
						|
   * more) delay on large files.  We'll come back and trim the fat after the 
 | 
						|
   * recording's done.
 | 
						|
   */
 | 
						|
  hFilename=open(sFilename,O_WRONLY|O_CREAT,DEFAULT_WAV_MODE);
 | 
						|
  if(hFilename<0) {
 | 
						|
    perror("open");
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* The 'RIFF' field */
 | 
						|
  strcpy(cBuffer,"RIFF");
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* The size pointer */
 | 
						|
  /* wav files are little endian! */
 | 
						|
  cBuffer[0]=dTotalWavSize & 0x000000FF;
 | 
						|
  cBuffer[1]=(dTotalWavSize & 0x0000FF00) >> 8;
 | 
						|
  cBuffer[2]=(dTotalWavSize & 0x00FF0000) >> 16;
 | 
						|
  cBuffer[3]=(dTotalWavSize & 0xFF000000) >> 24;
 | 
						|
  write(hFilename,cBuffer,4);  
 | 
						|
 | 
						|
  /* The WAVE field */
 | 
						|
  strcpy(cBuffer,"WAVE");
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* Now the format chunk */
 | 
						|
  /* First the chunk header */
 | 
						|
  strcpy(cBuffer,"fmt ");
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* The chunk size field */
 | 
						|
  cBuffer[0]=0x10;
 | 
						|
  cBuffer[1]=0;
 | 
						|
  cBuffer[2]=0;
 | 
						|
  cBuffer[3]=0;
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* The Format Category */
 | 
						|
  cBuffer[0]=dFormatTag & 0x00FF;
 | 
						|
  cBuffer[1]=(dFormatTag & 0xFF00) >> 8;
 | 
						|
  write(hFilename,cBuffer,2);
 | 
						|
 | 
						|
  /* Number of Channels */
 | 
						|
  cBuffer[0]=dChannels & 0x00FF;
 | 
						|
  cBuffer[1]=(dChannels & 0xFF00) >> 8;
 | 
						|
  write(hFilename,cBuffer,2);
 | 
						|
 | 
						|
  /* Samples/second/channel */
 | 
						|
  cBuffer[0]=ldSamplesPerSec & 0x000000FF;
 | 
						|
  cBuffer[1]=(ldSamplesPerSec & 0x0000FF00) >> 8;
 | 
						|
  cBuffer[2]=(ldSamplesPerSec & 0x00FF0000) >> 16;
 | 
						|
  cBuffer[3]=(ldSamplesPerSec & 0xFF000000) >> 24;
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* Average bytes per second */
 | 
						|
  cBuffer[0]=dBytesPerSec & 0x000000FF;
 | 
						|
  cBuffer[1]=(dBytesPerSec & 0x0000FF00) >> 8;
 | 
						|
  cBuffer[2]=(dBytesPerSec & 0x00FF0000) >> 16;
 | 
						|
  cBuffer[3]=(dBytesPerSec & 0xFF000000) >> 24;
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* Data Block Alignment */
 | 
						|
  cBuffer[0]=dBlockAlign & 0x00FF;
 | 
						|
  cBuffer[1]=(dBlockAlign & 0xFF00) >> 8;
 | 
						|
  write(hFilename,cBuffer,2);
 | 
						|
 | 
						|
  /* Bits per Sample */
 | 
						|
  /* NOTE: This field pertains only to WAVE_FORMAT_PCM format encoding */
 | 
						|
  cBuffer[0]=dBitsPerSample & 0x00FF;
 | 
						|
  cBuffer[1]=(dBitsPerSample & 0xFF00) >> 8;
 | 
						|
  write(hFilename,cBuffer,2);
 | 
						|
 | 
						|
  /* Now, the data chunk */
 | 
						|
  /* The 'data' field */
 | 
						|
  strcpy(cBuffer,"data");
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* The data size field */
 | 
						|
  cBuffer[0]=dTotalSampleBytes & 0x000000FF;
 | 
						|
  cBuffer[1]=(dTotalSampleBytes & 0x0000FF00) >> 8;
 | 
						|
  cBuffer[2]=(dTotalSampleBytes & 0x00FF0000) >> 16;
 | 
						|
  cBuffer[3]=(dTotalSampleBytes & 0xFF000000) >> 24;
 | 
						|
  write(hFilename,cBuffer,4);
 | 
						|
 | 
						|
  /* Move the audio data */
 | 
						|
  for(i=0;i<dBufferWrites;i++) {
 | 
						|
    read(hAudio,cBuffer,BUFFER_SIZE);
 | 
						|
    write(hFilename,cBuffer,BUFFER_SIZE);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* Finish up */
 | 
						|
  ftruncate(hFilename,lseek(hFilename,0,SEEK_CUR));
 | 
						|
  close(hFilename);
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int RecordWavFile(char *sFilename,char *sAudio,int dSeconds,
 | 
						|
		  struct wavHeader *wavHeader,struct wavProcess *wavProcess,
 | 
						|
		  unsigned dOptions)
 | 
						|
{
 | 
						|
  int hAudio;
 | 
						|
 | 
						|
  hAudio=open(sAudio,O_RDWR);
 | 
						|
  if(hAudio<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  return RecordWavDesc(sFilename,hAudio,dSeconds,
 | 
						|
		       wavHeader,wavProcess,dOptions);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int RecordWavDesc(char *sFilename,int hAudio,int dSeconds,
 | 
						|
		  struct wavHeader *wavHeader,struct wavProcess *wavProcess,
 | 
						|
		  unsigned dOptions)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  int hFilename;
 | 
						|
  int dBufferWrites,dExcessWrites;
 | 
						|
  int dSense=0,dStartWrite=BUFFER_SIZE,dPosThreshold,dNegThreshold;
 | 
						|
  unsigned char cBuffer[BUFFER_SIZE];
 | 
						|
  short *dBuffer;
 | 
						|
  int dBufferCount=0;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Do we support this format?
 | 
						|
   */
 | 
						|
  if(wavHeader->wFormatTag!=WAVE_FORMAT_PCM) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Flesh out the wavHeader Structure
 | 
						|
   */
 | 
						|
  wavHeader->dwAvgBytesPerSec=wavHeader->wChannels*wavHeader->dwSamplesPerSec*
 | 
						|
    (wavHeader->wBitsPerSample/8);
 | 
						|
  wavHeader->wBlockAlign=wavHeader->wChannels*(wavHeader->wBitsPerSample/8);
 | 
						|
  wavHeader->dwWaveDataSize=wavHeader->dwAvgBytesPerSec*dSeconds;
 | 
						|
  wavHeader->dwFileSize=wavHeader->dwWaveDataSize/wavHeader->wBlockAlign;
 | 
						|
  wavHeader->tWavLength=dSeconds;
 | 
						|
 | 
						|
  if(SetDspDesc(hAudio,wavHeader)<0) {   /* Format not supported by hardware */
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  if((dOptions&WAVLIB_TEST)!=0) {   /* Just a test, exit */
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Look for silence sense option
 | 
						|
   */
 | 
						|
  if(wavProcess!=NULL) {
 | 
						|
    if(wavProcess->dSenseTimeout!=0) {
 | 
						|
      if(wavHeader->wBitsPerSample==8) {
 | 
						|
	dPosThreshold=(int)(128+(128*DbToLinear(-wavProcess->dfThreshold)));
 | 
						|
	dNegThreshold=(int)(128-(128*DbToLinear(-wavProcess->dfThreshold)));
 | 
						|
	dBufferCount=wavHeader->dwAvgBytesPerSec*wavProcess->dSenseTimeout/
 | 
						|
	  BUFFER_SIZE;
 | 
						|
	while((dSense==0)&&((dBufferCount--)>0)) {
 | 
						|
	  read(hAudio,cBuffer,BUFFER_SIZE);
 | 
						|
	  for(i=0;i<BUFFER_SIZE;i++) {
 | 
						|
	    if((cBuffer[i]>dPosThreshold)||(cBuffer[i]<dNegThreshold)) {
 | 
						|
	      dSense=1;
 | 
						|
	      dStartWrite=i;
 | 
						|
	      i=BUFFER_SIZE;
 | 
						|
	    }
 | 
						|
	  }
 | 
						|
	}
 | 
						|
      }
 | 
						|
      if(wavHeader->wBitsPerSample==16) {
 | 
						|
	dBuffer=(short *)cBuffer;
 | 
						|
	dPosThreshold=(int)(32768*DbToLinear(-wavProcess->dfThreshold));
 | 
						|
	dNegThreshold=(int)(-32768*DbToLinear(-wavProcess->dfThreshold));
 | 
						|
	dBufferCount=wavHeader->dwAvgBytesPerSec*wavProcess->dSenseTimeout/
 | 
						|
	  BUFFER_SIZE;
 | 
						|
	while((dSense==0)&&((dBufferCount--)>0)) {
 | 
						|
	  read(hAudio,cBuffer,BUFFER_SIZE);
 | 
						|
	  for(i=0;i<BUFFER_SIZE/2;i++) {
 | 
						|
	    if((dBuffer[i]>dPosThreshold)||(dBuffer[i]<dNegThreshold)) {
 | 
						|
	      dSense=1;
 | 
						|
	      dStartWrite=i*2;
 | 
						|
	      i=BUFFER_SIZE;
 | 
						|
	    }
 | 
						|
	  }
 | 
						|
	}
 | 
						|
      }
 | 
						|
      if(dBufferCount<=0) {
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Write the wav file
 | 
						|
   */
 | 
						|
  hFilename=CreateWav(sFilename,wavHeader);
 | 
						|
  if(hFilename<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  dBufferWrites=(wavHeader->dwWaveDataSize-(BUFFER_SIZE-dStartWrite))/
 | 
						|
    BUFFER_SIZE;
 | 
						|
  dExcessWrites=(wavHeader->dwWaveDataSize-(BUFFER_SIZE-dStartWrite))-
 | 
						|
    (dBufferWrites*BUFFER_SIZE);
 | 
						|
  if(dSense==1) {
 | 
						|
    write(hFilename,cBuffer+dStartWrite,BUFFER_SIZE-dStartWrite);
 | 
						|
  }
 | 
						|
  for(i=0;i<dBufferWrites;i++) {
 | 
						|
    read(hAudio,cBuffer,BUFFER_SIZE);
 | 
						|
    write(hFilename,cBuffer,BUFFER_SIZE);
 | 
						|
  }
 | 
						|
  read(hAudio,cBuffer,dExcessWrites);
 | 
						|
  write(hFilename,cBuffer,dExcessWrites);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Finish Up
 | 
						|
   */
 | 
						|
  ftruncate(hFilename,lseek(hFilename,0,SEEK_CUR));
 | 
						|
  FixWav(hFilename,wavHeader->dwFileSize,wavHeader->dwWaveDataSize);
 | 
						|
  close(hFilename);
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int SoundConfigFile(char *sAudioDev,int dParam,int dRequest)
 | 
						|
 | 
						|
     /* This function performs an ioctl call on the audio device 
 | 
						|
        named by sAudioDev, using the ioctl dParam and the argument
 | 
						|
	dRequest.  The ioctls are those defined in the OSS API. 
 | 
						|
	If successful, the function returns the updated value of
 | 
						|
	dRequest, otherwise, it returns a -1. 
 | 
						|
 | 
						|
	It is anticipated that this function will be useful mainly
 | 
						|
	as a way for manipulating the soundcard mixer settings */
 | 
						|
 | 
						|
{     
 | 
						|
  int dAudioDev;
 | 
						|
  int i;
 | 
						|
 | 
						|
  dAudioDev=open(sAudioDev,O_RDONLY);
 | 
						|
  if(dAudioDev<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  i=SoundConfigDesc(dAudioDev,dParam,dRequest);
 | 
						|
  close(dAudioDev);
 | 
						|
  if(i<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return dRequest;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
double DbToLinear(double dfDb)
 | 
						|
{
 | 
						|
  return pow(10,dfDb/20);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
double LinearToDb(double dfLinear)
 | 
						|
{
 | 
						|
  if(dfLinear==0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  return 20*log10(dfLinear);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int SoundConfigDesc(int dAudioDev,int dParam,int dRequest)
 | 
						|
 | 
						|
     /* This function performs an ioctl call on the audio device 
 | 
						|
        open on hAudioDev, using the ioctl dParam and the argument
 | 
						|
	dRequest.  The ioctls are those defined in the OSS API. 
 | 
						|
	If successful, the function returns the updated value of
 | 
						|
	dRequest, otherwise, it returns a -1. 
 | 
						|
 | 
						|
	It is anticipated that this function will be useful mainly
 | 
						|
	as a way for manipulating the soundcard mixer settings */
 | 
						|
 | 
						|
{     
 | 
						|
  int i;
 | 
						|
 | 
						|
  i=ioctl(dAudioDev,dParam,&dRequest);
 | 
						|
  if(i<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    return dRequest;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
     
 | 
						|
int Pattern(int dFilename,char *sPattern)
 | 
						|
 | 
						|
     /* This function finds the looks for the string sPattern
 | 
						|
in the file pointed to by dFilename, starting at the current 
 | 
						|
pointer position.  If found, it returns the pointer offset and
 | 
						|
with the pointer set to the byte immediately following the pattern.
 | 
						|
If the pattern is not found, it returns -1. */
 | 
						|
 | 
						|
{
 | 
						|
  int i,j;
 | 
						|
  int dOffset=0;  /* file pointer offset */
 | 
						|
  unsigned char cBuffer;
 | 
						|
  int dPatLength;
 | 
						|
 | 
						|
  dPatLength=strlen(sPattern);
 | 
						|
  i=read(dFilename,&cBuffer,1);
 | 
						|
  if(i<0) {
 | 
						|
    perror("read");
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  dOffset++;
 | 
						|
  while(i==1) {
 | 
						|
    j=0;
 | 
						|
    while(cBuffer==sPattern[j++] && j<=dPatLength) {
 | 
						|
      if(j==dPatLength) {   /* it's a match! */
 | 
						|
	return dOffset;
 | 
						|
      }
 | 
						|
      i=read(dFilename,&cBuffer,1);
 | 
						|
      dOffset++;
 | 
						|
    }
 | 
						|
    lseek(dFilename,-(j-1),SEEK_CUR);
 | 
						|
    dOffset-=(j-1);
 | 
						|
    i=read(dFilename,&cBuffer,1);
 | 
						|
    dOffset++;
 | 
						|
  }
 | 
						|
  lseek(dFilename,-dOffset,SEEK_CUR);
 | 
						|
  printf("Offset: %d\n",dOffset);
 | 
						|
  return (-1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
ssize_t WriteSword(int hFilename,unsigned dValue)
 | 
						|
{
 | 
						|
  unsigned char cBuffer[2];
 | 
						|
 | 
						|
  cBuffer[0]=dValue&0xFF;
 | 
						|
  cBuffer[1]=(dValue>>8)&0xFF;
 | 
						|
 | 
						|
  return write(hFilename,cBuffer,2);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
ssize_t WriteDword(int hFilename,unsigned dValue)
 | 
						|
{
 | 
						|
  unsigned char cBuffer[4];
 | 
						|
 | 
						|
  cBuffer[0]=dValue&0xFF;
 | 
						|
  cBuffer[1]=(dValue>>8)&0xFF;
 | 
						|
  cBuffer[2]=(dValue>>16)&0xFF;
 | 
						|
  cBuffer[3]=(dValue>>24)&0xFF;
 | 
						|
 | 
						|
  return write(hFilename,cBuffer,4);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int TailTrim(char *sFilename,int dThreshold)
 | 
						|
{
 | 
						|
  int i,j;
 | 
						|
  int hFilename;
 | 
						|
  struct wavHeader wavHeader;
 | 
						|
  struct wavChunk wavChunk;
 | 
						|
  long dEnd;
 | 
						|
  unsigned char cBuffer[BUFFER_SIZE];
 | 
						|
  short *dBuffer;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Initialize
 | 
						|
   */
 | 
						|
  dBuffer=(short *)cBuffer;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Open the file
 | 
						|
   */
 | 
						|
  hFilename=OpenWav(sFilename,&wavHeader);
 | 
						|
  if(hFilename<0) {
 | 
						|
    return hFilename;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /*
 | 
						|
   * Find the end of the audio data
 | 
						|
   */
 | 
						|
  memset(&wavChunk,0,sizeof(struct wavChunk));
 | 
						|
  strcpy(wavChunk.sName,"data");
 | 
						|
  if(FindChunk(hFilename,&wavChunk)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
  lseek(hFilename,wavChunk.oOffset+wavChunk.oSize-(BUFFER_SIZE*500),SEEK_SET);
 | 
						|
  read(hFilename,cBuffer,BUFFER_SIZE);
 | 
						|
  for(j=BUFFER_SIZE/2;j>0;j--) {
 | 
						|
    printf("VALUE: %d\n",dBuffer[j]);
 | 
						|
  }
 | 
						|
  exit(0);
 | 
						|
  */
 | 
						|
 | 
						|
  /*
 | 
						|
   * Scan backwards through the data looking for audio
 | 
						|
   */
 | 
						|
  lseek(hFilename,wavChunk.oOffset+wavChunk.oSize+6,SEEK_SET);
 | 
						|
  for(i=0;i<wavChunk.oSize/BUFFER_SIZE;i++) {
 | 
						|
    lseek(hFilename,-BUFFER_SIZE,SEEK_CUR);
 | 
						|
    read(hFilename,cBuffer,BUFFER_SIZE);
 | 
						|
    lseek(hFilename,-BUFFER_SIZE,SEEK_CUR);
 | 
						|
    for(j=BUFFER_SIZE/2-100;j>=0;j--) {
 | 
						|
      /*      printf("Threshold: %d   Value: %d\n",dThreshold,dBuffer[j]); */
 | 
						|
      if(abs(dBuffer[j])>=dThreshold) {
 | 
						|
	TruncWav(hFilename,&wavHeader,&wavChunk,lseek(hFilename,0,SEEK_CUR)+j*2); 
 | 
						|
	close(hFilename);
 | 
						|
	exit(0); 
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  dEnd=wavChunk.oSize-BUFFER_SIZE*(wavChunk.oSize/BUFFER_SIZE);
 | 
						|
  lseek(hFilename,-dEnd,SEEK_CUR);
 | 
						|
  read(hFilename,cBuffer,dEnd);
 | 
						|
  lseek(hFilename,-dEnd,SEEK_CUR);
 | 
						|
  for(j=dEnd-1;j>=0;j--) {
 | 
						|
    if(abs(dBuffer[j])>=dThreshold) {
 | 
						|
      TruncWav(hFilename,&wavHeader,&wavChunk,lseek(hFilename,0,SEEK_CUR)+j);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  /*
 | 
						|
   * Finish up
 | 
						|
   */
 | 
						|
  close(hFilename);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int TruncWav(int hFilename,struct wavHeader *wavHeader,
 | 
						|
	     struct wavChunk *wavChunk,unsigned dTruncPoint)
 | 
						|
{
 | 
						|
  unsigned dBytes;
 | 
						|
 | 
						|
  if(ftruncate(hFilename,dTruncPoint)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  dBytes=dTruncPoint-wavChunk->oOffset;
 | 
						|
  if(FixWav(hFilename,dBytes/(wavHeader->wBitsPerSample/8),dBytes)<0) {
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 |