mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 04:16:43 +00:00 
			
		
		
		
	Correct typos of the following word families: command-line immediately extensions momentarily mustn't numbered bytes caching ASTERISK-29714 Change-Id: I8b2b125c5d4d2f9e87a58515c97468ad47ca44f8
		
			
				
	
	
		
			1091 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1091 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 *
 | 
						|
 * Programs for processing sound files in raw- or WAV-format.
 | 
						|
 * -- Useful functions for parsing command line options and
 | 
						|
 *    issuing errors, warnings, and chit chat.
 | 
						|
 *
 | 
						|
 * Name:    frame.c
 | 
						|
 * Version: see static char *standardversion, below.
 | 
						|
 * Author:  Mark Roberts <mark@manumark.de>
 | 
						|
 *	    Michael Labuschke <michael@labuschke.de> sys_errlist fixes
 | 
						|
 *
 | 
						|
 ****************************************************************************/
 | 
						|
/****************************************************************************
 | 
						|
 *  These are useful functions that all DSP programs might find handy
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <math.h>
 | 
						|
#include <stdlib.h> /* for exit and malloc */
 | 
						|
#include <string.h>
 | 
						|
#include <time.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <assert.h>
 | 
						|
#include "frame.h"
 | 
						|
 | 
						|
time_t stopwatch;       /* will hold time at start of calculation */
 | 
						|
int samplefrequency;
 | 
						|
unsigned short samplewidth;
 | 
						|
unsigned short channels;
 | 
						|
int wavout;            /* TRUE iff out file should be a .WAV file */
 | 
						|
int iswav;             /* TRUE iff in file was found to be a .WAV file */
 | 
						|
FILE *in, *out;
 | 
						|
char *infilename, *outfilename;
 | 
						|
int verboselevel;
 | 
						|
char *version = "";
 | 
						|
char *usage = "";
 | 
						|
static int test_usage;
 | 
						|
 | 
						|
static char *standardversion = "frame version 1.3, June 13th 2001";
 | 
						|
static char *standardusage =
 | 
						|
"\nOptions common to all mark-dsp programs:\n"
 | 
						|
 | 
						|
"-h \t\t create a WAV-header on output files.\n"
 | 
						|
"-c#\t\t set number of channels to # (1 or 2). Default: like input.\n"
 | 
						|
"-w#\t\t set number of bits per sample (width) to # (only 16)\n"
 | 
						|
"-f#\t\t set sample frequency to #. Default: like input.\n"
 | 
						|
"-V \t\t verbose: talk a lot.\n"
 | 
						|
"-Q \t\t quiet: talk as little as possible.\n\n"
 | 
						|
"In most cases, a filename of '-' means stdin or stdout.\n\n"
 | 
						|
"Bug-reports: mark@manumark.de\n"
 | 
						|
;
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Writes the number of samples to result that are yet to be read from anyin.
 | 
						|
   Return values are TRUE on success, FALSE on failure.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
int getremainingfilelength( FILE *anyin, long *result)
 | 
						|
{
 | 
						|
    long i;
 | 
						|
 | 
						|
    i = ftell(anyin);
 | 
						|
    if (i == -1) return FALSE;
 | 
						|
    if (fseek(anyin, 0, SEEK_END) == -1) return FALSE;
 | 
						|
    *result = ftell(anyin);
 | 
						|
    if (*result == -1) return FALSE;
 | 
						|
    (*result) -= i;
 | 
						|
    (*result) /= samplewidth;
 | 
						|
    if (fseek(anyin, i, SEEK_SET) == -1) return FALSE;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Read a .pk-header from 'anyin'.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
void readpkheader( FILE *anyin)
 | 
						|
{
 | 
						|
   unsigned short tempushort;
 | 
						|
   int tempint, i, x;
 | 
						|
   unsigned char blood[8];
 | 
						|
 | 
						|
   for (i = 0; i < 11; i++)
 | 
						|
   {
 | 
						|
	   if (!fread( &tempint, 4, 1, anyin)) {
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   printf( "%d: %d, ", i, tempint);
 | 
						|
   }
 | 
						|
   printf( "\n");
 | 
						|
   if (!fread( blood, 1, 8, anyin)) {
 | 
						|
	   return;
 | 
						|
   }
 | 
						|
   for (i = 0; i < 8; i++)
 | 
						|
	   printf( "%d ", blood[i]);
 | 
						|
   printf( "\n");
 | 
						|
   for (i = 0; i < 8; i++)
 | 
						|
   {
 | 
						|
	   for (x = 128; x > 0; x /= 2)
 | 
						|
		   printf((blood[i] & x) == 0? "0 ":"1 ");
 | 
						|
	   printf(i%4==3? "\n":"| ");
 | 
						|
   }
 | 
						|
   printf( "\n");
 | 
						|
   for (i = 0; i < 2; i++)
 | 
						|
   {
 | 
						|
	   if (!fread( &tempint, 4, 1, anyin)) {
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   printf( "%d: %d, ", i, tempint);
 | 
						|
   }
 | 
						|
   printf( "\n");
 | 
						|
   for (i = 0; i < 2; i++)
 | 
						|
   {
 | 
						|
	   if (!fread( &tempushort, 2, 1, anyin)) {
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   printf( "%d: %d, ", i, tempushort);
 | 
						|
   }
 | 
						|
   printf( "\n");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Read a .WAV header from 'anyin'. See header for details.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
void readwavheader( FILE *anyin)
 | 
						|
{
 | 
						|
   unsigned int tempuint, sf;
 | 
						|
   unsigned short tempushort, cn;
 | 
						|
   char str[9];
 | 
						|
   int nowav = FALSE;
 | 
						|
 | 
						|
   iswav = FALSE;
 | 
						|
 | 
						|
   if (ftell(anyin) == -1) /* If we cannot seek this file */
 | 
						|
   {
 | 
						|
	   nowav = TRUE;   /* -> Pretend this is no wav-file */
 | 
						|
	   chat("File not seekable: not checking for WAV-header.\n");
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
	   /* Expect four bytes "RIFF" and four bytes filelength */
 | 
						|
	   if (!fread(str, 1, 8, anyin)) {           /* 0 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   str[4] = '\0';
 | 
						|
	   if (strcmp(str, "RIFF") != 0) nowav = TRUE;
 | 
						|
	   /* Expect eight bytes "WAVEfmt " */
 | 
						|
	   if (!fread(str, 1, 8, anyin)) {           /* 8 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   str[8] = '\0';
 | 
						|
	   if (strcmp(str, "WAVEfmt ") != 0) nowav = TRUE;
 | 
						|
	   /* Expect length of fmt data, which should be 16 */
 | 
						|
	   if (!fread(&tempuint, 4, 1, anyin)) {	/* 16 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (tempuint != 16) nowav = TRUE;
 | 
						|
	   /* Expect format tag, which should be 1 for pcm */
 | 
						|
	   if (!fread(&tempushort, 2, 1, anyin)) { /* 20 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (tempushort != 1)
 | 
						|
		   nowav = TRUE;
 | 
						|
	   /* Expect number of channels */
 | 
						|
	   if (!fread(&cn, 2, 1, anyin)) { /* 20 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (cn != 1 && cn != 2) nowav = TRUE;
 | 
						|
	   /* Read samplefrequency */
 | 
						|
	   if (!fread(&sf, 4, 1, anyin)) {  /* 24 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* Read bytes per second: Should be samplefreq * channels * 2 */
 | 
						|
	   if (!fread(&tempuint, 4, 1, anyin)) {         /* 28 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (tempuint != sf * cn * 2) nowav = TRUE;
 | 
						|
	   /* read bytes per frame: Should be channels * 2 */
 | 
						|
	   if (!fread(&tempushort, 2, 1, anyin)) {       /* 32 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (tempushort != cn * 2) nowav = TRUE;
 | 
						|
	   /* Read bits per sample: Should be 16 */
 | 
						|
	   if (!fread(&tempushort, 2, 1, anyin)) {       /* 34 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (tempushort != 16) nowav = TRUE;
 | 
						|
	   if (!fread(str, 4, 1, anyin)) {            /* 36 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   str[4] = '\0';
 | 
						|
	   if (strcmp(str, "data") != 0) nowav = TRUE;
 | 
						|
	   if (!fread(&tempuint, 4, 1, anyin)) {   /* 40 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (nowav)
 | 
						|
	   {
 | 
						|
		   fseek(anyin, 0, SEEK_SET);   /* Back to beginning of file */
 | 
						|
		   chat("File has no WAV header.\n");
 | 
						|
	   }
 | 
						|
	   else
 | 
						|
	   {
 | 
						|
		   samplefrequency = sf;
 | 
						|
		   channels = cn;
 | 
						|
		   chat("Read WAV header: %d channels, samplefrequency %d.\n",
 | 
						|
			 channels, samplefrequency);
 | 
						|
		   iswav = TRUE;
 | 
						|
	   }
 | 
						|
   }
 | 
						|
   return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Write a .WAV header to 'out'. See header for details.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
void makewavheader( void)
 | 
						|
{
 | 
						|
   unsigned int tempuint, filelength;
 | 
						|
   unsigned short tempushort;
 | 
						|
 | 
						|
   /* If fseek fails, don't create the header. */
 | 
						|
   if (fseek(out, 0, SEEK_END) != -1)
 | 
						|
   {
 | 
						|
	   filelength = ftell(out);
 | 
						|
	   chat("filelength %d, ", filelength);
 | 
						|
	   fseek(out, 0, SEEK_SET);
 | 
						|
	   if (!fwrite("RIFF", 1, 4, out)) { /* 0 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   tempuint = filelength - 8;
 | 
						|
	   if (!fwrite(&tempuint, 4, 1, out)) {    /* 4 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (!fwrite("WAVEfmt ", 1, 8, out)) {   /* 8 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* length of fmt data 16 bytes */
 | 
						|
	   tempuint = 16;
 | 
						|
	   if (!fwrite(&tempuint, 4, 1, out)) {   /* 16 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* Format tag: 1 for pcm */
 | 
						|
	   tempushort = 1;
 | 
						|
	   if (!fwrite(&tempushort, 2, 1, out)) { /* 20 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   chat("%d channels\n", channels);
 | 
						|
	   if (!fwrite(&channels, 2, 1, out)) {
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   chat("samplefrequency %d\n", samplefrequency);
 | 
						|
	   if (!fwrite(&samplefrequency, 4, 1, out)) {   /* 24 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* Bytes per second */
 | 
						|
	   tempuint = channels * samplefrequency * 2;
 | 
						|
	   if (!fwrite(&tempuint, 4, 1, out)) {         /* 28 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* Block align */
 | 
						|
	   tempushort = 2 * channels;
 | 
						|
	   if (!fwrite(&tempushort, 2, 1, out)) {       /* 32 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   /* Bits per sample */
 | 
						|
	   tempushort = 16;
 | 
						|
	   if (!fwrite(&tempushort, 2, 1, out)) {       /* 34 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   if (!fwrite("data", 4, 1, out)) {            /* 36 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
	   tempuint = filelength - 44;
 | 
						|
	   if (!fwrite(&tempuint, 4, 1, out)) {   /* 40 */
 | 
						|
		   return;
 | 
						|
	   }
 | 
						|
   }
 | 
						|
   return;
 | 
						|
}
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   After all is read and done, inform the inclined user of the elapsed time
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
static void statistics( void)
 | 
						|
{
 | 
						|
   int temp;
 | 
						|
 | 
						|
   temp = time(NULL) - stopwatch;
 | 
						|
   if (temp != 1)
 | 
						|
   {
 | 
						|
      inform ("\nTime: %d seconds\n", temp);
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      inform ("\nTime: 1 second\n");
 | 
						|
   }
 | 
						|
   return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Start the stopwatch and make sure the user is informed at end of program.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
void startstopwatch(void)
 | 
						|
{
 | 
						|
   stopwatch = time(NULL);       /* Remember time 'now' */
 | 
						|
   atexit(statistics);           /* Call function statistics() at exit. */
 | 
						|
 | 
						|
   return;
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Tests the character 'coal' for being a command line option character,
 | 
						|
   momentarily '-'.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int isoptionchar (char coal)
 | 
						|
{
 | 
						|
   return (coal =='-');
 | 
						|
}
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   Reads through the arguments on the lookout for an option starting
 | 
						|
   with 'string'. The rest of the option is read as a time and passed
 | 
						|
   to *result, where the result is meant to mean 'number of samples' in
 | 
						|
   that time.
 | 
						|
   On failure, *result is unchanged.
 | 
						|
   return value is TRUE on success, FALSE otherwise.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
int parsetimearg( int argcount, char *args[], char *string, int *result)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    if ((i = findoption( argcount, args, string)) > 0)
 | 
						|
    {
 | 
						|
	if (parsetime(args[i] + 1 + strlen( string), result))
 | 
						|
	    return TRUE;
 | 
						|
	argerrornum(args[i]+1, ME_NOTIME);
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   The string argument is read as a time and passed
 | 
						|
   to *result, where the result is meant to mean 'number of samples' in
 | 
						|
   that time.
 | 
						|
   On failure, *result is unchanged.
 | 
						|
   return value is TRUE on success, FALSE otherwise.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
int parsetime(char *string, int *result)
 | 
						|
{
 | 
						|
    int k;
 | 
						|
    double temp;
 | 
						|
    char m, s, end;
 | 
						|
 | 
						|
    k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
 | 
						|
    switch (k)
 | 
						|
      {
 | 
						|
      case 0: case EOF: case 4:
 | 
						|
	return FALSE;
 | 
						|
      case 1:
 | 
						|
	*result = temp;
 | 
						|
	break;
 | 
						|
      case 2:
 | 
						|
	if (m == 's')
 | 
						|
	  *result = temp * samplefrequency;
 | 
						|
	else
 | 
						|
	  return FALSE;
 | 
						|
	break;
 | 
						|
      case 3:
 | 
						|
	if (m == 'm' && s == 's')
 | 
						|
	  *result = temp * samplefrequency / 1000;
 | 
						|
	else if (m == 'H' && s == 'z')
 | 
						|
	  *result = samplefrequency / temp;
 | 
						|
	else
 | 
						|
	  return FALSE;
 | 
						|
	break;
 | 
						|
      default:
 | 
						|
	argerrornum(NULL, ME_THISCANTHAPPEN);
 | 
						|
      }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------
 | 
						|
   The string argument is read as a frequency and passed
 | 
						|
   to *result, where the result is meant to mean 'number of samples' in
 | 
						|
   one cycle of that frequency.
 | 
						|
   On failure, *result is unchanged.
 | 
						|
   return value is TRUE on success, FALSE otherwise.
 | 
						|
   -----------------------------------------------------------------------*/
 | 
						|
int parsefreq(char *string, double *result)
 | 
						|
{
 | 
						|
    int k;
 | 
						|
    double temp;
 | 
						|
    char m, s, end;
 | 
						|
 | 
						|
    k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
 | 
						|
    switch (k)
 | 
						|
      {
 | 
						|
      case 0: case EOF: case 2: case 4:
 | 
						|
	return FALSE;
 | 
						|
      case 1:
 | 
						|
	*result = temp;
 | 
						|
	break;
 | 
						|
      case 3:
 | 
						|
	if (m == 'H' && s == 'z')
 | 
						|
	  *result = samplefrequency / temp;
 | 
						|
	else
 | 
						|
	  return FALSE;
 | 
						|
	break;
 | 
						|
      default:
 | 
						|
	argerrornum(NULL, ME_THISCANTHAPPEN);
 | 
						|
      }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
char *parsefilearg( int argcount, char *args[])
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  char *result = NULL;
 | 
						|
 | 
						|
   for (i = 1; i < argcount; i++)
 | 
						|
   {
 | 
						|
      if (args[i][0] != '\0' &&
 | 
						|
	  (!isoptionchar (args[i][0]) || args[i][1] == '\0' ))
 | 
						|
      {
 | 
						|
	/*---------------------------------------------*
 | 
						|
	 * The argument is a filename:                 *
 | 
						|
	 * it is either no dash followed by something, *
 | 
						|
	 * or it is a dash following by nothing.       *
 | 
						|
	 *---------------------------------------------*/
 | 
						|
	result = malloc( strlen( args[i]) + 1);
 | 
						|
	if (result == NULL)
 | 
						|
	    fatalperror( "Couldn't allocate memory for filename\n");
 | 
						|
	strcpy( result, args[i]);
 | 
						|
	args[i][0] = '\0';                    /* Mark as used up */
 | 
						|
	break;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   return result;
 | 
						|
}
 | 
						|
 | 
						|
int parseswitch( char *found, char *wanted)
 | 
						|
{
 | 
						|
  if (strncmp( found, wanted, strlen( wanted)) == 0)
 | 
						|
    {
 | 
						|
      if (found[strlen( wanted)] == '\0')
 | 
						|
	return TRUE;
 | 
						|
      else
 | 
						|
	argerrornum( found, ME_NOSWITCH);
 | 
						|
    }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
int parseswitcharg( int argcount, char *args[], char *string)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  if ((i = findoption( argcount, args, string)) > 0)
 | 
						|
    {
 | 
						|
      if (args[i][strlen( string) + 1] == '\0')
 | 
						|
	return TRUE;
 | 
						|
      else
 | 
						|
	argerrornum( args[i] + 1, ME_NOSWITCH);
 | 
						|
    }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
int parseintarg( int argcount, char *args[], char *string, int *result)
 | 
						|
{
 | 
						|
  int i, temp;
 | 
						|
  char c;
 | 
						|
 | 
						|
  if ((i = findoption( argcount, args, string)) > 0)
 | 
						|
   {
 | 
						|
      switch (sscanf(args[i] + 1 + strlen( string),
 | 
						|
		     "%30d%1c", &temp, &c))
 | 
						|
      {
 | 
						|
	case 0: case EOF: case 2:
 | 
						|
            argerrornum(args[i]+1, ME_NOINT);
 | 
						|
            return FALSE;
 | 
						|
         case 1:
 | 
						|
	   *result = temp;
 | 
						|
            break;
 | 
						|
         default:
 | 
						|
            say("frame.c: This can't happen\n");
 | 
						|
      }
 | 
						|
      return TRUE;
 | 
						|
   }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reads through the arguments on the lookout for an option starting
 | 
						|
   with 'string'. The rest of the option is read as a double and
 | 
						|
   passed to *result.
 | 
						|
   On failure, *result is unchanged.
 | 
						|
   return value is TRUE on success, FALSE otherwise.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int parsedoublearg( int argcount, char *args[], char *string, double *result)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  double temp;
 | 
						|
  char end;
 | 
						|
 | 
						|
  if ((i = findoption( argcount, args, string)) > 0)
 | 
						|
    {
 | 
						|
      switch (sscanf(args[i] + 1 + strlen( string), "%30lf%1c", &temp, &end))
 | 
						|
	{
 | 
						|
	case 0: case EOF: case 2:
 | 
						|
	  argerrornum(args[i]+1, ME_NODOUBLE);
 | 
						|
	  return FALSE;
 | 
						|
	case 1:
 | 
						|
	  *result = temp;
 | 
						|
	  break;
 | 
						|
	default:
 | 
						|
	  say("frame.c: This can't happen\n");
 | 
						|
	}
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reads through the arguments on the lookout for an option starting
 | 
						|
   with 'string'. The rest of the option is read as a volume, i.e.
 | 
						|
   absolute, percent or db. The result is passed to *result.
 | 
						|
   On failure, *result is unchanged.
 | 
						|
   return value is TRUE on success, FALSE otherwise.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int parsevolarg( int argcount, char *args[], char *string, double *result)
 | 
						|
{
 | 
						|
  double vol = 1.0;
 | 
						|
  char sbd, sbb, end;
 | 
						|
  int i, weird = FALSE;
 | 
						|
 | 
						|
  if ((i = findoption( argcount, args, string)) > 0)
 | 
						|
    {
 | 
						|
      switch (sscanf(args[i] + 1 + strlen( string),
 | 
						|
		     "%30lf%1c%1c%1c", &vol, &sbd, &sbb, &end))
 | 
						|
	{
 | 
						|
	  case 0: case EOF: case 4:
 | 
						|
	  weird = TRUE;
 | 
						|
	  break;    /* No number: error */
 | 
						|
	case 1:
 | 
						|
	  *result = vol;
 | 
						|
	  break;
 | 
						|
	case 2:
 | 
						|
	  if (sbd == '%')
 | 
						|
	    *result = vol / 100;
 | 
						|
	  else
 | 
						|
	    weird = TRUE;    /* One char but no percent: error */
 | 
						|
	  break;
 | 
						|
	case 3:
 | 
						|
	  if (sbd =='d' && sbb == 'b')
 | 
						|
	    *result = pow(2, vol / 6.02);
 | 
						|
	  else
 | 
						|
	    weird = TRUE;    /* Two chars but not db: error */
 | 
						|
	  break;
 | 
						|
	default:
 | 
						|
	  say("frame.c: This can't happen.\n");
 | 
						|
	}
 | 
						|
      if (weird)
 | 
						|
	argerrornum( args[i] + 1, ME_NOVOL);
 | 
						|
	  /* ("Weird option: couldn't parse volume '%s'\n", args[i]+2); */
 | 
						|
      return !weird;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reads the specified string 's' and interprets it as a volume. The string
 | 
						|
   would be of the form 1.8 or 180% or 5db.
 | 
						|
   On success, the return value TRUE and *result is given result
 | 
						|
   (i.e. the relative volume, i.e. 1.8). On failure, FALSE is returned and
 | 
						|
   result is given value 1.0.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int parsevolume(char *s, double *result)
 | 
						|
{
 | 
						|
    int k;
 | 
						|
    char sbd, sbb, end;
 | 
						|
 | 
						|
    *result = 1.0;
 | 
						|
    k = sscanf(s, "%30lf%1c%1c%1c", result, &sbd, &sbb, &end);
 | 
						|
    switch (k)
 | 
						|
    {
 | 
						|
      case 0:
 | 
						|
      case EOF:
 | 
						|
      case 4:
 | 
						|
       return FALSE;
 | 
						|
      case 1:
 | 
						|
       break;
 | 
						|
      case 2:
 | 
						|
       if (sbd != '%')
 | 
						|
	   return FALSE;
 | 
						|
       (*result) /=100;
 | 
						|
       break;
 | 
						|
      case 3:
 | 
						|
       if (sbd !='d' || sbb != 'b')
 | 
						|
	   return FALSE;
 | 
						|
       (*result) = pow(2, (*result) / 6.02);
 | 
						|
       break;
 | 
						|
      default:
 | 
						|
       say("parsevolume: This can't happen (%d).\n", k);
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reports an error due to parsing the string 's' encountered on the
 | 
						|
   command line.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
void argerror(char *s)
 | 
						|
{
 | 
						|
  error ("Error parsing command line. Unrecognized option:\n\t-%s\n", s);
 | 
						|
  fatalerror("\nTry --help for help.\n");
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reports an error due to parsing the string 's' encountered on the
 | 
						|
   command line. 'code' indicates the type of error.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
void argerrornum(char *s, Errornum code)
 | 
						|
{
 | 
						|
  char *message;
 | 
						|
 | 
						|
  if (code == ME_TOOMANYFILES)
 | 
						|
    {
 | 
						|
      error("Too many files on command line: '%s'.\n", s);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (s != NULL)
 | 
						|
	error ("Error parsing option -%s:\n\t", s);
 | 
						|
      switch( code)
 | 
						|
	{
 | 
						|
	case ME_NOINT:
 | 
						|
	  message = "Integer expected";
 | 
						|
	  break;
 | 
						|
	case ME_NODOUBLE:
 | 
						|
	  message = "Floating point number expected";
 | 
						|
	  break;
 | 
						|
	case ME_NOTIME:
 | 
						|
	  message = "Time argument expected";
 | 
						|
	  break;
 | 
						|
	case ME_NOVOL:
 | 
						|
	  message = "Volume argument expected";
 | 
						|
	  break;
 | 
						|
	case ME_NOSWITCH:
 | 
						|
	  message = "Garbage after switch-type option";
 | 
						|
	  break;
 | 
						|
	case ME_HEADERONTEXTFILE:
 | 
						|
	  message = "Option -h is not useful for text-output";
 | 
						|
	  break;
 | 
						|
	case ME_NOINFILE:
 | 
						|
	  message = "No input file specified";
 | 
						|
	  break;
 | 
						|
	case ME_NOOUTFILE:
 | 
						|
	  message = "No output file specified";
 | 
						|
	  break;
 | 
						|
	case ME_NOIOFILE:
 | 
						|
	  message = "No input/output file specified";
 | 
						|
	  break;
 | 
						|
	case ME_NOSTDIN:
 | 
						|
	  message = "Standard in not supported here";
 | 
						|
	  break;
 | 
						|
	case ME_NOSTDOUT:
 | 
						|
	  message = "Standard out not supported here";
 | 
						|
	  break;
 | 
						|
	case ME_NOSTDIO:
 | 
						|
	  message = "Standard in/out not supported here";
 | 
						|
	  break;
 | 
						|
	case ME_NOTENOUGHFILES:
 | 
						|
	  message = "Not enough files specified";
 | 
						|
	  break;
 | 
						|
	case ME_THISCANTHAPPEN:
 | 
						|
	  fatalerror("\nThis can't happen. Report this as a bug\n");
 | 
						|
	  /* fatalerror does not return */
 | 
						|
	default:
 | 
						|
	  error("Error code %d not implemented. Fix me!\n", code);
 | 
						|
	  message = "Error message not implemented. Fix me!";
 | 
						|
	}
 | 
						|
      error("%s\n", message);
 | 
						|
    }
 | 
						|
  fatalerror("\nTry --help for help.\n");
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reports an error due to parsing the string 's' encountered on the
 | 
						|
   command line. 'message' explains the type of error.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
void argerrortxt(char *s, char *message)
 | 
						|
{
 | 
						|
  if (s != NULL)
 | 
						|
    error ("Error parsing option -%s:\n\t", s);
 | 
						|
  else
 | 
						|
    error ("Error parsing command line:\n\t");
 | 
						|
  error ("%s\n", message);
 | 
						|
  fatalerror("\nTry --help for help.\n");
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Check for any remaining arguments and complain about their existence
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
void checknoargs( int argcount, char *args[])
 | 
						|
{
 | 
						|
  int i, errorcount = 0;
 | 
						|
 | 
						|
  for (i = 1; i < argcount; i++)
 | 
						|
    {
 | 
						|
      if (args[i][0] != '\0')   /* An unused argument! */
 | 
						|
	{
 | 
						|
	  errorcount++;
 | 
						|
	  if (errorcount == 1)
 | 
						|
	    error("The following arguments were not recognized:\n");
 | 
						|
	  error("\t%s\n", args[i]);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  if (errorcount > 0)           /* Errors are fatal */
 | 
						|
    fatalerror("\nTry --help for help.\n");
 | 
						|
 | 
						|
  return;                       /* No errors? Return. */
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Parses the command line arguments as represented by the function
 | 
						|
   arguments. Sets the global variables 'in', 'out', 'samplefrequency'
 | 
						|
   and 'samplewidth' accordingly. Also verboselevel.
 | 
						|
   The files 'in' and 'out' are even opened according to 'fileswitch'.
 | 
						|
   See headerfile for details
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
void parseargs( int argcount, char *args[], int fileswitch)
 | 
						|
{
 | 
						|
   char *filename;
 | 
						|
   int tempint = 0;
 | 
						|
 | 
						|
   if ((fileswitch & 1) != 0)     /* If getting infile  */
 | 
						|
     in = NULL;
 | 
						|
   if ((fileswitch & 4) != 0)     /* If getting outfile */
 | 
						|
     out = NULL;
 | 
						|
   wavout = FALSE;
 | 
						|
   verboselevel = 5;
 | 
						|
   samplefrequency = DEFAULTFREQ;
 | 
						|
   samplewidth = 2;
 | 
						|
   channels = 1;
 | 
						|
 | 
						|
   /*-----------------------------------------------*
 | 
						|
    * First first check testcase, usage and version *
 | 
						|
    *-----------------------------------------------*/
 | 
						|
   test_usage = parseswitcharg( argcount, args, "-test-usage");
 | 
						|
   if (parseswitcharg( argcount, args, "-help"))
 | 
						|
       {
 | 
						|
	 printf("%s%s", usage, standardusage);
 | 
						|
	 exit(0);
 | 
						|
       }
 | 
						|
   if (parseswitcharg( argcount, args, "-version"))
 | 
						|
       {
 | 
						|
	 printf("%s\n(%s)\n", version, standardversion);
 | 
						|
	 exit(0);
 | 
						|
       }
 | 
						|
   /*--------------------------------------*
 | 
						|
    * Set verboselevel                     *
 | 
						|
    *--------------------------------------*/
 | 
						|
   while (parseswitcharg( argcount, args, "V"))
 | 
						|
               verboselevel = 10;
 | 
						|
   while (parseswitcharg( argcount, args, "Q"))
 | 
						|
               verboselevel = 1;
 | 
						|
   /*-------------------------------------------------*
 | 
						|
    * Get filenames and open files *
 | 
						|
    *-------------------------------------------------*/
 | 
						|
   if ((fileswitch & 1) != 0)        /* Infile wanted */
 | 
						|
     {
 | 
						|
       infilename = parsefilearg( argcount, args);
 | 
						|
       if (infilename == NULL)
 | 
						|
	 argerrornum( NULL, ME_NOINFILE);
 | 
						|
       if (strcmp( infilename, "-") == 0)
 | 
						|
	 {
 | 
						|
	   infilename = "<stdin>";
 | 
						|
	   in = stdin;
 | 
						|
	   if ((fileswitch & 2) != 0)   /* Binfile wanted */
 | 
						|
	     readwavheader( in);
 | 
						|
	 }
 | 
						|
       else
 | 
						|
	 {
 | 
						|
	   if ((fileswitch & 2) == 0)   /* Textfile wanted */
 | 
						|
	     in = fopen(infilename, "rt");
 | 
						|
	   else                         /* Binfile wanted */
 | 
						|
	     if ((in = fopen(infilename, "rb")) != NULL)
 | 
						|
	       readwavheader( in);
 | 
						|
	 }
 | 
						|
       if (in == NULL)
 | 
						|
	 fatalerror("Error opening input file '%s': %s\n", infilename,strerror(errno));
 | 
						|
       else
 | 
						|
	 inform("Using file '%s' as input\n", infilename);
 | 
						|
     }
 | 
						|
   if ((fileswitch & 4) != 0)        /* Outfile wanted */
 | 
						|
     {
 | 
						|
       outfilename = parsefilearg( argcount, args);
 | 
						|
       if (outfilename == NULL)
 | 
						|
	 argerrornum( NULL, ME_NOOUTFILE);
 | 
						|
       if (strcmp( outfilename, "-") == 0)
 | 
						|
	 {
 | 
						|
	   outfilename = "<stdout>";
 | 
						|
	   out = stdout;
 | 
						|
	 }
 | 
						|
       else
 | 
						|
	 {
 | 
						|
 | 
						|
	   if ((fileswitch & 8) == 0)   /* Textfile wanted */
 | 
						|
	     out = fopen(outfilename, "wt");
 | 
						|
	   else                         /* Binfile wanted */
 | 
						|
	     out = fopen(outfilename, "wb");
 | 
						|
	 }
 | 
						|
       if (out == NULL)
 | 
						|
	 fatalerror("Error opening output file '%s': %s\n", outfilename,strerror(errno));
 | 
						|
       else
 | 
						|
	 inform("Using file '%s' as output\n", outfilename);
 | 
						|
     }
 | 
						|
   if ((fileswitch & 32) != 0)      /* In-/Outfile wanted */
 | 
						|
     {
 | 
						|
       assert (in == NULL && out == NULL);
 | 
						|
       infilename = outfilename = parsefilearg( argcount, args);
 | 
						|
       if (outfilename == NULL)
 | 
						|
	 argerrornum( NULL, ME_NOIOFILE);
 | 
						|
       if (strcmp( infilename, "-") == 0)
 | 
						|
	 argerrornum( infilename, ME_NOSTDIN);
 | 
						|
       inform("Using file '%s' as input/output\n", outfilename);
 | 
						|
       in = out = fopen(outfilename, "r+");
 | 
						|
       if (out == NULL)
 | 
						|
	 fatalerror("Error opening input/output file '%s': %s\n", outfilename,strerror(errno));
 | 
						|
 | 
						|
       readwavheader( in);
 | 
						|
     }
 | 
						|
   if ((fileswitch & 16) == 0)  /* No additional files wanted */
 | 
						|
     {
 | 
						|
       if ((filename = parsefilearg( argcount, args)) != NULL)
 | 
						|
	 argerrornum( filename, ME_TOOMANYFILES);
 | 
						|
     }
 | 
						|
 | 
						|
   /*-------------------------------------------------*
 | 
						|
    * Set samplefrequency, width, wavout,
 | 
						|
    *-------------------------------------------------*/
 | 
						|
   parseintarg( argcount, args, "f", &samplefrequency);
 | 
						|
   wavout = parseswitcharg( argcount, args, "h");
 | 
						|
   if (parseintarg( argcount, args, "w", &tempint))
 | 
						|
     {
 | 
						|
       if (tempint != 16)
 | 
						|
	 argerrortxt(NULL, "Option -w is only valid "
 | 
						|
		     "with value 16. Sorry.");
 | 
						|
       else
 | 
						|
	 samplewidth = tempint;
 | 
						|
     }
 | 
						|
   if (parseintarg( argcount, args, "c", &tempint))
 | 
						|
     {
 | 
						|
       if (tempint != 1 && tempint != 2)
 | 
						|
	 argerrortxt(NULL, "Option -c is only valid "
 | 
						|
		     "with values 1 or 2. Sorry.");
 | 
						|
       else
 | 
						|
	 channels = tempint;
 | 
						|
     }
 | 
						|
   /*-------------------------------------------------*
 | 
						|
    * Create WAV-header on output if wanted.          *
 | 
						|
    *-------------------------------------------------*/
 | 
						|
   if (wavout)
 | 
						|
     switch (fileswitch & (12))
 | 
						|
       {
 | 
						|
       case 4:   /* User wants header on textfile */
 | 
						|
	 argerrornum( NULL, ME_HEADERONTEXTFILE);
 | 
						|
       case 12:  /* User wants header on binfile  */
 | 
						|
	 makewavheader();
 | 
						|
	 break;
 | 
						|
       case 0:   /* User wants header, but there is no outfile */
 | 
						|
	 /* Problem: what about i/o-file, 32? You might want a header
 | 
						|
	    on that? Better ignore this case. */
 | 
						|
	 break;
 | 
						|
       case 8:    /* An application mustn't ask for this */
 | 
						|
       default:   /* This can't happen */
 | 
						|
	 assert( FALSE);
 | 
						|
       }
 | 
						|
   return;
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Returns the index 'i' of the first argument that IS an option, and
 | 
						|
   which begins with the label 's'. If there is none, -1.
 | 
						|
   We also mark that option as done with, i.e. we cross it out.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int findoption( int argcount, char *args[], char *s)
 | 
						|
{
 | 
						|
   int i;
 | 
						|
 | 
						|
   if (test_usage)
 | 
						|
     printf("Checking for option -%s\n", s);
 | 
						|
 | 
						|
   for (i=1; i<argcount; i++)
 | 
						|
   {
 | 
						|
     if (isoptionchar (args[i][0]) &&
 | 
						|
	 strncmp( args[i] + 1, s, strlen( s)) == 0)
 | 
						|
       {
 | 
						|
	 args[i][0] = '\0';
 | 
						|
	 return i;
 | 
						|
       }
 | 
						|
   }
 | 
						|
   return -1;
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Finishes off the .WAV header (if any) and exits correctly and formerly.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int myexit (int value)
 | 
						|
{
 | 
						|
  switch (value)
 | 
						|
    {
 | 
						|
    case 0:
 | 
						|
      if (wavout)
 | 
						|
	makewavheader();  /* Writes a fully informed .WAV header */
 | 
						|
      chat("Success!\n");
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      chat("Failure.\n");
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  exit (value);
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------------------------------------------------
 | 
						|
   Reads the stated input file bufferwise, calls the function 'work'
 | 
						|
   with the proper values, and writes the result to the stated output file.
 | 
						|
   Return value: TRUE on success, FALSE otherwise.
 | 
						|
   -------------------------------------------------------------------- */
 | 
						|
int workloop( FILE *theinfile, FILE *theoutfile,
 | 
						|
	      int (*work)( short *buffer, int length) )
 | 
						|
{
 | 
						|
  short *buffer;
 | 
						|
  int length, nowlength;
 | 
						|
 | 
						|
  length = BUFFSIZE;
 | 
						|
  if ((buffer = malloc( sizeof(short) * length)) == NULL)
 | 
						|
    fatalperror ("");
 | 
						|
  while (TRUE)
 | 
						|
    {
 | 
						|
      nowlength = fread(buffer, sizeof(short), length, theinfile);
 | 
						|
      if (ferror( theinfile) != 0)
 | 
						|
	fatalperror("Error reading input file");
 | 
						|
      if (nowlength == 0)   /* Reached end of input file */
 | 
						|
	break;
 | 
						|
      /* Call the routine that does the work */
 | 
						|
      if (!work (buffer, nowlength))         /* On error, stop. */
 | 
						|
	return FALSE;
 | 
						|
      if (!fwrite(buffer, sizeof(short), nowlength, theoutfile)) {
 | 
						|
	      return FALSE;
 | 
						|
      }
 | 
						|
      if (ferror( theoutfile) != 0)
 | 
						|
	fatalperror("Error writing to output file");
 | 
						|
    }
 | 
						|
  return TRUE;      /* Input file done with, no errors. */
 | 
						|
}
 | 
						|
 | 
						|
int __attribute__((format(printf,1,2))) chat( const char *format, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
    int result = 0;
 | 
						|
 | 
						|
    if (verboselevel > 5)
 | 
						|
    {
 | 
						|
	va_start( ap, format);
 | 
						|
	result = vfprintf( stderr, format, ap);
 | 
						|
	va_end( ap);
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
int __attribute__((format(printf,1,2))) inform( const char *format, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
    int result = 0;
 | 
						|
 | 
						|
    if (verboselevel > 1)
 | 
						|
    {
 | 
						|
	va_start( ap, format);
 | 
						|
	result = vfprintf( stderr, format, ap);
 | 
						|
	va_end( ap);
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
int __attribute__((format(printf,1,2))) error( const char *format, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
    int result;
 | 
						|
 | 
						|
    va_start( ap, format);
 | 
						|
    result = vfprintf( stderr, format, ap);
 | 
						|
    va_end( ap);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
void __attribute__((format(printf,1,2))) fatalerror( const char *format, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    va_start( ap, format);
 | 
						|
    vfprintf( stderr, format, ap);
 | 
						|
    va_end( ap);
 | 
						|
    myexit(1);
 | 
						|
}
 | 
						|
 | 
						|
void fatalperror( const char *string)
 | 
						|
{
 | 
						|
  perror( string);
 | 
						|
  myexit( 1);
 | 
						|
}
 | 
						|
 | 
						|
int __attribute__((format(printf,1,2))) say( const char *format, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
    int result;
 | 
						|
 | 
						|
    va_start( ap, format);
 | 
						|
    result = vfprintf( stdout, format, ap);
 | 
						|
    va_end( ap);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char *malloccopy( char *string)
 | 
						|
{
 | 
						|
    char *result;
 | 
						|
 | 
						|
    result = malloc( strlen( string) + 1);
 | 
						|
    if (result != NULL)
 | 
						|
	strcpy( result, string);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char *mallocconcat( char *one, char *two)
 | 
						|
{
 | 
						|
    char *result;
 | 
						|
 | 
						|
    result = malloc( strlen( one) + strlen( two) + 1);
 | 
						|
    if (result != NULL)
 | 
						|
      {
 | 
						|
	strcpy( result, one);
 | 
						|
	strcat( result, two);
 | 
						|
      }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
double double2db( double value)
 | 
						|
{
 | 
						|
  if (value < 0)
 | 
						|
    value = -value;
 | 
						|
  return 6.0 * log( value / 32767) / log( 2);
 | 
						|
}
 | 
						|
 | 
						|
void readawaysamples( FILE *input, size_t size)
 | 
						|
{
 | 
						|
  short *buffer;
 | 
						|
  int samplesread, count;
 | 
						|
 | 
						|
  buffer = malloc( sizeof( *buffer) * BUFFSIZE);
 | 
						|
  if (buffer == NULL) fatalperror("Couldn't allocate buffer");
 | 
						|
 | 
						|
  while (size > 0)
 | 
						|
    {
 | 
						|
      if (size > BUFFSIZE)
 | 
						|
	count = BUFFSIZE;
 | 
						|
      else
 | 
						|
	count = size;
 | 
						|
 | 
						|
      samplesread = fread( buffer, sizeof(*buffer), count, input);
 | 
						|
      if (ferror( input) != 0)
 | 
						|
	fatalperror("Error reading input file");
 | 
						|
      size -= samplesread;
 | 
						|
    }
 | 
						|
  free( buffer);
 | 
						|
}
 |