utils/frame.c

Go to the documentation of this file.
00001 /****************************************************************************
00002  *
00003  * Programs for processing sound files in raw- or WAV-format.
00004  * -- Useful functions for parsing command line options and
00005  *    issuing errors, warnings, and chit chat.
00006  *
00007  * Name:    frame.c
00008  * Version: see static char *standardversion, below.
00009  * Author:  Mark Roberts <mark@manumark.de>
00010  *     Michael Labuschke <michael@labuschke.de> sys_errlist fixes 
00011  *    
00012  ****************************************************************************/
00013 /****************************************************************************
00014  *  These are useful functions that all DSP programs might find handy
00015  ****************************************************************************/
00016 
00017 #include <stdio.h>
00018 #include <math.h>
00019 #include <stdlib.h> /* for exit and malloc */
00020 #include <string.h>
00021 #include <time.h>
00022 #include <stdarg.h>
00023 #include <errno.h>
00024 #include <assert.h>
00025 #include "frame.h"
00026 
00027 time_t stopwatch;       /* will hold time at start of calculation */
00028 int samplefrequency;
00029 unsigned short samplewidth;
00030 unsigned short channels;
00031 int wavout;            /* TRUE iff out file should be a .WAV file */
00032 int iswav;             /* TRUE iff in file was found to be a .WAV file */
00033 FILE *in, *out;
00034 char *infilename, *outfilename;
00035 int verboselevel;
00036 char *version = "";
00037 char *usage = "";
00038 static int test_usage;
00039 
00040 static char *standardversion = "frame version 1.3, June 13th 2001";
00041 static char *standardusage =
00042 "\nOptions common to all mark-dsp programs:\n"
00043 
00044 "-h \t\t create a WAV-header on output files.\n"
00045 "-c#\t\t set number of channels to # (1 or 2). Default: like input.\n"
00046 "-w#\t\t set number of bits per sample (width) to # (only 16)\n"
00047 "-f#\t\t set sample frequency to #. Default: like input.\n"
00048 "-V \t\t verbose: talk a lot.\n"
00049 "-Q \t\t quiet: talk as little as possible.\n\n"
00050 "In most cases, a filename of '-' means stdin or stdout.\n\n"
00051 "Bug-reports: mark@manumark.de\n"
00052 ;
00053 
00054 /* -----------------------------------------------------------------------
00055    Writes the number of samples to result that are yet to be read from anyin.
00056    Return values are TRUE on success, FALSE on failure.
00057    -----------------------------------------------------------------------*/
00058 int getremainingfilelength( FILE *anyin, long *result)
00059 {
00060     long i;
00061 
00062     i = ftell(anyin);
00063     if (i == -1) return FALSE;
00064     if (fseek(anyin, 0, SEEK_END) == -1) return FALSE;
00065     *result = ftell(anyin);
00066     if (*result == -1) return FALSE;
00067     (*result) -= i;
00068     (*result) /= samplewidth;
00069     if (fseek(anyin, i, SEEK_SET) == -1) return FALSE;
00070     return TRUE;
00071 }
00072 
00073 /* -----------------------------------------------------------------------
00074    Read a .pk-header from 'anyin'.
00075    -----------------------------------------------------------------------*/
00076 void readpkheader( FILE *anyin)
00077 {
00078    unsigned short tempushort;
00079    int tempint, i, x;
00080    unsigned char blood[8];
00081 
00082    for (i = 0; i < 11; i++)
00083    {
00084       if (!fread( &tempint, 4, 1, anyin)) {
00085          return;
00086       }
00087       printf( "%d: %d, ", i, tempint);
00088    }
00089    printf( "\n");
00090    if (!fread( blood, 1, 8, anyin)) {
00091       return;
00092    }
00093    for (i = 0; i < 8; i++)
00094       printf( "%d ", blood[i]);
00095    printf( "\n");
00096    for (i = 0; i < 8; i++)
00097    {
00098       for (x = 128; x > 0; x /= 2)
00099          printf((blood[i] & x) == 0? "0 ":"1 ");
00100       printf(i%4==3? "\n":"| ");
00101    }
00102    printf( "\n");
00103    for (i = 0; i < 2; i++)
00104    {
00105       if (!fread( &tempint, 4, 1, anyin)) {
00106          return;
00107       }
00108       printf( "%d: %d, ", i, tempint);
00109    }
00110    printf( "\n");
00111    for (i = 0; i < 2; i++)
00112    {
00113       if (!fread( &tempushort, 2, 1, anyin)) {
00114          return;
00115       }
00116       printf( "%d: %d, ", i, tempushort);
00117    }
00118    printf( "\n");
00119 }
00120 
00121 
00122 
00123 /* -----------------------------------------------------------------------
00124    Read a .WAV header from 'anyin'. See header for details.
00125    -----------------------------------------------------------------------*/
00126 void readwavheader( FILE *anyin)
00127 {
00128    unsigned int tempuint, sf;
00129    unsigned short tempushort, cn;
00130    char str[9];
00131    int nowav = FALSE;
00132 
00133    iswav = FALSE;
00134 
00135    if (ftell(anyin) == -1) /* If we cannot seek this file */
00136    {
00137       nowav = TRUE;   /* -> Pretend this is no wav-file */
00138       chat("File not seekable: not checking for WAV-header.\n");
00139    }
00140    else
00141    {
00142       /* Expect four bytes "RIFF" and four bytes filelength */
00143       if (!fread(str, 1, 8, anyin)) {           /* 0 */
00144          return;
00145       }
00146       str[4] = '\0';
00147       if (strcmp(str, "RIFF") != 0) nowav = TRUE;
00148       /* Expect eight bytes "WAVEfmt " */
00149       if (!fread(str, 1, 8, anyin)) {           /* 8 */
00150          return;
00151       }
00152       str[8] = '\0';
00153       if (strcmp(str, "WAVEfmt ") != 0) nowav = TRUE;
00154       /* Expect length of fmt data, which should be 16 */
00155       if (!fread(&tempuint, 4, 1, anyin)) {  /* 16 */
00156          return;
00157       }
00158       if (tempuint != 16) nowav = TRUE;
00159       /* Expect format tag, which should be 1 for pcm */
00160       if (!fread(&tempushort, 2, 1, anyin)) { /* 20 */
00161          return;
00162       }
00163       if (tempushort != 1)
00164          nowav = TRUE;
00165       /* Expect number of channels */
00166       if (!fread(&cn, 2, 1, anyin)) { /* 20 */
00167          return;
00168       }
00169       if (cn != 1 && cn != 2) nowav = TRUE;
00170       /* Read samplefrequency */
00171       if (!fread(&sf, 4, 1, anyin)) {  /* 24 */
00172          return;
00173       }
00174       /* Read bytes per second: Should be samplefreq * channels * 2 */
00175       if (!fread(&tempuint, 4, 1, anyin)) {         /* 28 */
00176          return;
00177       }
00178       if (tempuint != sf * cn * 2) nowav = TRUE;
00179       /* read bytes per frame: Should be channels * 2 */
00180       if (!fread(&tempushort, 2, 1, anyin)) {       /* 32 */
00181          return;
00182       }
00183       if (tempushort != cn * 2) nowav = TRUE;
00184       /* Read bits per sample: Should be 16 */
00185       if (!fread(&tempushort, 2, 1, anyin)) {       /* 34 */
00186          return;
00187       }
00188       if (tempushort != 16) nowav = TRUE;
00189       if (!fread(str, 4, 1, anyin)) {            /* 36 */
00190          return;
00191       }
00192       str[4] = '\0';
00193       if (strcmp(str, "data") != 0) nowav = TRUE;
00194       if (!fread(&tempuint, 4, 1, anyin)) {   /* 40 */
00195          return;
00196       }
00197       if (nowav)
00198       {
00199          fseek(anyin, 0, SEEK_SET);   /* Back to beginning of file */
00200          chat("File has no WAV header.\n");
00201       }
00202       else
00203       {
00204          samplefrequency = sf;
00205          channels = cn;
00206          chat("Read WAV header: %d channels, samplefrequency %d.\n",
00207           channels, samplefrequency);
00208          iswav = TRUE;
00209       }
00210    }
00211    return;
00212 }
00213 
00214 
00215 
00216 /* -----------------------------------------------------------------------
00217    Write a .WAV header to 'out'. See header for details.
00218    -----------------------------------------------------------------------*/
00219 void makewavheader( void)
00220 {
00221    unsigned int tempuint, filelength;
00222    unsigned short tempushort;
00223 
00224    /* If fseek fails, don't create the header. */
00225    if (fseek(out, 0, SEEK_END) != -1)
00226    {
00227       filelength = ftell(out);
00228       chat("filelength %d, ", filelength);
00229       fseek(out, 0, SEEK_SET);
00230       if (!fwrite("RIFF", 1, 4, out)) { /* 0 */
00231          return;
00232       }
00233       tempuint = filelength - 8;
00234       if (!fwrite(&tempuint, 4, 1, out)) {    /* 4 */
00235          return;
00236       }
00237       if (!fwrite("WAVEfmt ", 1, 8, out)) {   /* 8 */
00238          return;
00239       }
00240       /* length of fmt data 16 bytes */
00241       tempuint = 16;
00242       if (!fwrite(&tempuint, 4, 1, out)) {   /* 16 */
00243          return;
00244       }
00245       /* Format tag: 1 for pcm */
00246       tempushort = 1;
00247       if (!fwrite(&tempushort, 2, 1, out)) { /* 20 */
00248          return;
00249       }
00250       chat("%d channels\n", channels);
00251       if (!fwrite(&channels, 2, 1, out)) {
00252          return;
00253       }
00254       chat("samplefrequency %d\n", samplefrequency);
00255       if (!fwrite(&samplefrequency, 4, 1, out)) {   /* 24 */
00256          return;
00257       }
00258       /* Bytes per second */
00259       tempuint = channels * samplefrequency * 2;
00260       if (!fwrite(&tempuint, 4, 1, out)) {         /* 28 */
00261          return;
00262       }
00263       /* Block align */
00264       tempushort = 2 * channels;
00265       if (!fwrite(&tempushort, 2, 1, out)) {       /* 32 */
00266          return;
00267       }
00268       /* Bits per sample */
00269       tempushort = 16;
00270       if (!fwrite(&tempushort, 2, 1, out)) {       /* 34 */
00271          return;
00272       }
00273       if (!fwrite("data", 4, 1, out)) {            /* 36 */
00274          return;
00275       }
00276       tempuint = filelength - 44;
00277       if (!fwrite(&tempuint, 4, 1, out)) {   /* 40 */
00278          return;
00279       }
00280    }
00281    return;
00282 }
00283 
00284 /* -----------------------------------------------------------------------
00285    After all is read and done, inform the inclined user of the elapsed time
00286    -----------------------------------------------------------------------*/
00287 static void statistics( void)
00288 {
00289    int temp;
00290 
00291    temp = time(NULL) - stopwatch;
00292    if (temp != 1)
00293    {
00294       inform ("\nTime: %d seconds\n", temp);
00295    }
00296    else
00297    {
00298       inform ("\nTime: 1 second\n");
00299    }
00300    return;
00301 }
00302 
00303 
00304 /* -----------------------------------------------------------------------
00305    Start the stopwatch and make sure the user is informed at end of program.
00306    -----------------------------------------------------------------------*/
00307 void startstopwatch(void)
00308 {
00309    stopwatch = time(NULL);       /* Remember time 'now' */
00310    atexit(statistics);           /* Call function statistics() at exit. */
00311 
00312    return;
00313 }
00314 
00315 /* --------------------------------------------------------------------
00316    Tests the character 'coal' for being a command line option character,
00317    momentarrily '-'.
00318    -------------------------------------------------------------------- */
00319 int isoptionchar (char coal)
00320 {
00321    return (coal =='-');
00322 }
00323 
00324 /* -----------------------------------------------------------------------
00325    Reads through the arguments on the lookout for an option starting
00326    with 'string'. The rest of the option is read as a time and passed
00327    to *result, where the result is meant to mean 'number of samples' in
00328    that time.
00329    On failure, *result is unchanged.
00330    return value is TRUE on success, FALSE otherwise.
00331    -----------------------------------------------------------------------*/
00332 int parsetimearg( int argcount, char *args[], char *string, int *result)
00333 {
00334     int i;
00335 
00336     if ((i = findoption( argcount, args, string)) > 0)
00337     {
00338    if (parsetime(args[i] + 1 + strlen( string), result))
00339        return TRUE;
00340    argerrornum(args[i]+1, ME_NOTIME);
00341     }
00342     return FALSE;
00343 }
00344 
00345 /* -----------------------------------------------------------------------
00346    The string argument is read as a time and passed
00347    to *result, where the result is meant to mean 'number of samples' in
00348    that time.
00349    On failure, *result is unchanged.
00350    return value is TRUE on success, FALSE otherwise.
00351    -----------------------------------------------------------------------*/
00352 int parsetime(char *string, int *result)
00353 {
00354     int k;
00355     double temp;
00356     char m, s, end;
00357 
00358     k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
00359     switch (k)
00360       {
00361       case 0: case EOF: case 4:
00362    return FALSE;
00363       case 1:
00364    *result = temp;
00365    break;
00366       case 2:
00367    if (m == 's')
00368      *result = temp * samplefrequency;
00369    else
00370      return FALSE;
00371    break;
00372       case 3:
00373    if (m == 'm' && s == 's')
00374      *result = temp * samplefrequency / 1000;
00375    else if (m == 'H' && s == 'z')
00376      *result = samplefrequency / temp;
00377    else
00378      return FALSE;
00379    break;
00380       default:
00381    argerrornum(NULL, ME_THISCANTHAPPEN);
00382       }
00383     return TRUE;
00384 }
00385 
00386 /* -----------------------------------------------------------------------
00387    The string argument is read as a frequency and passed
00388    to *result, where the result is meant to mean 'number of samples' in
00389    one cycle of that frequency.
00390    On failure, *result is unchanged.
00391    return value is TRUE on success, FALSE otherwise.
00392    -----------------------------------------------------------------------*/
00393 int parsefreq(char *string, double *result)
00394 {
00395     int k;
00396     double temp;
00397     char m, s, end;
00398 
00399     k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
00400     switch (k)
00401       {
00402       case 0: case EOF: case 2: case 4:
00403    return FALSE;
00404       case 1:
00405    *result = temp;
00406    break;
00407       case 3:
00408    if (m == 'H' && s == 'z')
00409      *result = samplefrequency / temp;
00410    else
00411      return FALSE;
00412    break;
00413       default:
00414    argerrornum(NULL, ME_THISCANTHAPPEN);
00415       }
00416     return TRUE;
00417 }
00418 
00419 char *parsefilearg( int argcount, char *args[])
00420 {
00421   int i;
00422   char *result = NULL;
00423 
00424    for (i = 1; i < argcount; i++)
00425    {
00426       if (args[i][0] != '\0' &&
00427      (!isoptionchar (args[i][0]) || args[i][1] == '\0' ))
00428       {
00429    /*---------------------------------------------*
00430     * The argument is a filename:                 *
00431     * it is either no dash followed by something, *
00432     * or it is a dash following by nothing.       *
00433     *---------------------------------------------*/
00434    result = malloc( strlen( args[i]) + 1);
00435    if (result == NULL)
00436        fatalperror( "Couldn't allocate memory for filename\n");
00437    strcpy( result, args[i]);
00438    args[i][0] = '\0';                    /* Mark as used up */
00439    break;
00440       }
00441    }
00442    return result;
00443 }
00444 
00445 int parseswitch( char *found, char *wanted)
00446 {
00447   if (strncmp( found, wanted, strlen( wanted)) == 0)
00448     {
00449       if (found[strlen( wanted)] == '\0')
00450    return TRUE;
00451       else
00452    argerrornum( found, ME_NOSWITCH);
00453     }
00454   return FALSE;
00455 }
00456 
00457 int parseswitcharg( int argcount, char *args[], char *string)
00458 {
00459   int i;
00460 
00461   if ((i = findoption( argcount, args, string)) > 0)
00462     {
00463       if (args[i][strlen( string) + 1] == '\0')
00464    return TRUE;
00465       else
00466    argerrornum( args[i] + 1, ME_NOSWITCH);
00467     }
00468   return FALSE;
00469 }
00470 
00471 int parseintarg( int argcount, char *args[], char *string, int *result)
00472 {
00473   int i, temp;
00474   char c;
00475 
00476   if ((i = findoption( argcount, args, string)) > 0)
00477    {
00478       switch (sscanf(args[i] + 1 + strlen( string),
00479            "%30d%1c", &temp, &c))
00480       {
00481    case 0: case EOF: case 2:
00482             argerrornum(args[i]+1, ME_NOINT);
00483             return FALSE;
00484          case 1:
00485       *result = temp;
00486             break;
00487          default:
00488             say("frame.c: This can't happen\n");
00489       }
00490       return TRUE;
00491    }
00492   else
00493     {
00494       return FALSE;
00495     }
00496 }
00497 
00498 /* --------------------------------------------------------------------
00499    Reads through the arguments on the lookout for an option starting
00500    with 'string'. The rest of the option is read as a double and
00501    passed to *result.
00502    On failure, *result is unchanged.
00503    return value is TRUE on success, FALSE otherwise.
00504    -------------------------------------------------------------------- */
00505 int parsedoublearg( int argcount, char *args[], char *string, double *result)
00506 {
00507   int i;
00508   double temp;
00509   char end;
00510 
00511   if ((i = findoption( argcount, args, string)) > 0)
00512     {
00513       switch (sscanf(args[i] + 1 + strlen( string), "%30lf%1c", &temp, &end))
00514    {
00515    case 0: case EOF: case 2:
00516      argerrornum(args[i]+1, ME_NODOUBLE);
00517      return FALSE;
00518    case 1:
00519      *result = temp;
00520      break;
00521    default:
00522      say("frame.c: This can't happen\n");
00523    }
00524       return TRUE;
00525     }
00526   else
00527     {
00528       return FALSE;
00529     }
00530 }
00531 
00532 /* --------------------------------------------------------------------
00533    Reads through the arguments on the lookout for an option starting
00534    with 'string'. The rest of the option is read as a volume, i.e.
00535    absolute, percent or db. The result is passed to *result.
00536    On failure, *result is unchanged.
00537    return value is TRUE on success, FALSE otherwise.
00538    -------------------------------------------------------------------- */
00539 int parsevolarg( int argcount, char *args[], char *string, double *result)
00540 {
00541   double vol = 1.0;
00542   char sbd, sbb, end;
00543   int i, weird = FALSE;
00544 
00545   if ((i = findoption( argcount, args, string)) > 0)
00546     {
00547       switch (sscanf(args[i] + 1 + strlen( string),
00548            "%30lf%1c%1c%1c", &vol, &sbd, &sbb, &end))
00549    {
00550      case 0: case EOF: case 4:
00551      weird = TRUE;
00552      break;    /* No number: error */
00553    case 1:
00554      *result = vol;
00555      break;
00556    case 2:
00557      if (sbd == '%')
00558        *result = vol / 100;
00559      else
00560        weird = TRUE;    /* One char but no percent: error */
00561      break;
00562    case 3:
00563      if (sbd =='d' && sbb == 'b')
00564        *result = pow(2, vol / 6.02);
00565      else
00566        weird = TRUE;    /* Two chars but not db: error */
00567      break;
00568    default:
00569      say("frame.c: This can't happen.\n");
00570    }
00571       if (weird)
00572    argerrornum( args[i] + 1, ME_NOVOL);
00573      /* ("Weird option: couldn't parse volume '%s'\n", args[i]+2); */
00574       return !weird;
00575     }
00576   else
00577     {
00578       return FALSE;
00579     }
00580 }
00581 
00582 
00583 /* --------------------------------------------------------------------
00584    Reads the specified string 's' and interprets it as a volume. The string
00585    would be of the form 1.8 or 180% or 5db.
00586    On success, the return value TRUE and *result is given result
00587    (i.e. the relative volume, i.e. 1.8). On failure, FALSE is returned and
00588    result is given value 1.0.
00589    -------------------------------------------------------------------- */
00590 int parsevolume(char *s, double *result)
00591 {
00592     int k;
00593     char sbd, sbb, end;
00594 
00595     *result = 1.0;
00596     k = sscanf(s, "%30lf%1c%1c%1c", result, &sbd, &sbb, &end);
00597     switch (k)
00598     {
00599       case 0:
00600       case EOF:
00601       case 4:
00602        return FALSE;
00603       case 1:
00604        break;
00605       case 2:
00606        if (sbd != '%')
00607       return FALSE;
00608        (*result) /=100;
00609        break;
00610       case 3:
00611        if (sbd !='d' || sbb != 'b')
00612       return FALSE;
00613        (*result) = pow(2, (*result) / 6.02);
00614        break;
00615       default:
00616        say("parsevolume: This can't happen (%d).\n", k);
00617     }
00618     return TRUE;
00619 }
00620 
00621 /* --------------------------------------------------------------------
00622    Reports an error due to parsing the string 's' encountered on the
00623    command line.
00624    -------------------------------------------------------------------- */
00625 void argerror(char *s)
00626 {
00627   error ("Error parsing command line. Unrecognized option:\n\t-%s\n", s);
00628   fatalerror("\nTry --help for help.\n");
00629 }
00630 
00631 /* --------------------------------------------------------------------
00632    Reports an error due to parsing the string 's' encountered on the
00633    command line. 'code' indicates the type of error.
00634    -------------------------------------------------------------------- */
00635 void argerrornum(char *s, Errornum code)
00636 {
00637   char *message;
00638 
00639   if (code == ME_TOOMANYFILES)
00640     {
00641       error("Too many files on command line: '%s'.\n", s);
00642     }
00643   else
00644     {
00645       if (s != NULL)
00646    error ("Error parsing option -%s:\n\t", s);
00647       switch( code)
00648    {
00649    case ME_NOINT:
00650      message = "Integer expected";
00651      break;
00652    case ME_NODOUBLE:
00653      message = "Floating point number expected";
00654      break;
00655    case ME_NOTIME:
00656      message = "Time argument expected";
00657      break;
00658    case ME_NOVOL:
00659      message = "Volume argument expected";
00660      break;
00661    case ME_NOSWITCH:
00662      message = "Garbage after switch-type option";
00663      break;
00664    case ME_HEADERONTEXTFILE:
00665      message = "Option -h is not useful for text-output";
00666      break;
00667    case ME_NOINFILE:
00668      message = "No input file specified";
00669      break;
00670    case ME_NOOUTFILE:
00671      message = "No output file specified";
00672      break;
00673    case ME_NOIOFILE:
00674      message = "No input/output file specified";
00675      break;
00676    case ME_NOSTDIN:
00677      message = "Standard in not supported here";
00678      break;
00679    case ME_NOSTDOUT:
00680      message = "Standard out not supported here";
00681      break;
00682    case ME_NOSTDIO:
00683      message = "Standard in/out not supported here";
00684      break;
00685    case ME_NOTENOUGHFILES:
00686      message = "Not enough files specified";
00687      break;
00688    case ME_THISCANTHAPPEN:
00689      fatalerror("\nThis can't happen. Report this as a bug\n");
00690      /* fatalerror does not return */
00691    default:
00692      error("Error code %d not implemented. Fix me!\n", code);
00693      message = "Error message not implemented. Fix me!";
00694    }
00695       error("%s\n", message);
00696     }
00697   fatalerror("\nTry --help for help.\n");
00698 }
00699 
00700 /* --------------------------------------------------------------------
00701    Reports an error due to parsing the string 's' encountered on the
00702    command line. 'message' explains the type of error.
00703    -------------------------------------------------------------------- */
00704 void argerrortxt(char *s, char *message)
00705 {
00706   if (s != NULL)
00707     error ("Error parsing option -%s:\n\t", s);
00708   else
00709     error ("Error parsing command line:\n\t");
00710   error ("%s\n", message);
00711   fatalerror("\nTry --help for help.\n");
00712 }
00713 
00714 /* --------------------------------------------------------------------
00715    Check for any remaining arguments and complain about their existence
00716    -------------------------------------------------------------------- */
00717 void checknoargs( int argcount, char *args[])
00718 {
00719   int i, errorcount = 0;
00720 
00721   for (i = 1; i < argcount; i++)
00722     {
00723       if (args[i][0] != '\0')   /* An unused argument! */
00724    {
00725      errorcount++;
00726      if (errorcount == 1)
00727        error("The following arguments were not recognized:\n");
00728      error("\t%s\n", args[i]);
00729    }
00730     }
00731   if (errorcount > 0)           /* Errors are fatal */
00732     fatalerror("\nTry --help for help.\n");
00733 
00734   return;                       /* No errors? Return. */
00735 }
00736 
00737 /* --------------------------------------------------------------------
00738    Parses the command line arguments as represented by the function
00739    arguments. Sets the global variables 'in', 'out', 'samplefrequency'
00740    and 'samplewidth' accordingly. Also verboselevel.
00741    The files 'in' and 'out' are even opened according to 'fileswitch'.
00742    See headerfile for details
00743    -------------------------------------------------------------------- */
00744 void parseargs( int argcount, char *args[], int fileswitch)
00745 {
00746    char *filename;
00747    int tempint = 0;
00748 
00749    if ((fileswitch & 1) != 0)     /* If getting infile  */
00750      in = NULL;
00751    if ((fileswitch & 4) != 0)     /* If getting outfile */
00752      out = NULL;
00753    wavout = FALSE;
00754    verboselevel = 5;
00755    samplefrequency = DEFAULTFREQ;
00756    samplewidth = 2;
00757    channels = 1;
00758 
00759    /*-----------------------------------------------*
00760     * First first check testcase, usage and version *
00761     *-----------------------------------------------*/
00762    test_usage = parseswitcharg( argcount, args, "-test-usage");
00763    if (parseswitcharg( argcount, args, "-help"))
00764        {
00765     printf("%s%s", usage, standardusage);
00766     exit(0);
00767        }
00768    if (parseswitcharg( argcount, args, "-version"))
00769        {
00770     printf("%s\n(%s)\n", version, standardversion);
00771     exit(0);
00772        }
00773    /*--------------------------------------*
00774     * Set verboselevel                     *
00775     *--------------------------------------*/
00776    while (parseswitcharg( argcount, args, "V"))
00777                verboselevel = 10;
00778    while (parseswitcharg( argcount, args, "Q"))
00779                verboselevel = 1;
00780    /*-------------------------------------------------*
00781     * Get filenames and open files *
00782     *-------------------------------------------------*/
00783    if ((fileswitch & 1) != 0)        /* Infile wanted */
00784      {
00785        infilename = parsefilearg( argcount, args);
00786        if (infilename == NULL)
00787     argerrornum( NULL, ME_NOINFILE);
00788        if (strcmp( infilename, "-") == 0)
00789     {
00790       infilename = "<stdin>";
00791       in = stdin;
00792       if ((fileswitch & 2) != 0)   /* Binfile wanted */
00793         readwavheader( in);
00794     }
00795        else
00796     {
00797       if ((fileswitch & 2) == 0)   /* Textfile wanted */
00798         in = fopen(infilename, "rt");
00799       else                         /* Binfile wanted */
00800         if ((in = fopen(infilename, "rb")) != NULL)
00801           readwavheader( in);
00802     }
00803        if (in == NULL)
00804     fatalerror("Error opening input file '%s': %s\n", infilename,strerror(errno));
00805        else
00806     inform("Using file '%s' as input\n", infilename);
00807      }
00808    if ((fileswitch & 4) != 0)        /* Outfile wanted */
00809      {
00810        outfilename = parsefilearg( argcount, args);
00811        if (outfilename == NULL)
00812     argerrornum( NULL, ME_NOOUTFILE);
00813        if (strcmp( outfilename, "-") == 0)
00814     {
00815       outfilename = "<stdout>";
00816       out = stdout;
00817     }
00818        else
00819     {
00820 
00821       if ((fileswitch & 8) == 0)   /* Textfile wanted */
00822         out = fopen(outfilename, "wt");
00823       else                         /* Binfile wanted */
00824         out = fopen(outfilename, "wb");
00825     }
00826        if (out == NULL)
00827     fatalerror("Error opening output file '%s': %s\n", outfilename,strerror(errno));
00828        else
00829     inform("Using file '%s' as output\n", outfilename);
00830      }
00831    if ((fileswitch & 32) != 0)      /* In-/Outfile wanted */
00832      {
00833        assert (in == NULL && out == NULL);
00834        infilename = outfilename = parsefilearg( argcount, args);
00835        if (outfilename == NULL)
00836     argerrornum( NULL, ME_NOIOFILE);
00837        if (strcmp( infilename, "-") == 0)
00838     argerrornum( infilename, ME_NOSTDIN);
00839        inform("Using file '%s' as input/output\n", outfilename);
00840        in = out = fopen(outfilename, "r+");
00841        if (out == NULL)
00842     fatalerror("Error opening input/output file '%s': %s\n", outfilename,strerror(errno));
00843 
00844        readwavheader( in);
00845      }
00846    if ((fileswitch & 16) == 0)  /* No additional files wanted */
00847      {
00848        if ((filename = parsefilearg( argcount, args)) != NULL)
00849     argerrornum( filename, ME_TOOMANYFILES);
00850      }
00851 
00852    /*-------------------------------------------------*
00853     * Set samplefrequency, width, wavout, 
00854     *-------------------------------------------------*/
00855    parseintarg( argcount, args, "f", &samplefrequency);
00856    wavout = parseswitcharg( argcount, args, "h");
00857    if (parseintarg( argcount, args, "w", &tempint))
00858      {
00859        if (tempint != 16)
00860     argerrortxt(NULL, "Option -w is only valid "
00861            "with value 16. Sorry.");
00862        else
00863     samplewidth = tempint;
00864      }
00865    if (parseintarg( argcount, args, "c", &tempint))
00866      {
00867        if (tempint != 1 && tempint != 2)
00868     argerrortxt(NULL, "Option -c is only valid "
00869            "with values 1 or 2. Sorry.");
00870        else
00871     channels = tempint;
00872      }
00873    /*-------------------------------------------------*
00874     * Create WAV-header on output if wanted.          *
00875     *-------------------------------------------------*/
00876    if (wavout)
00877      switch (fileswitch & (12))
00878        {
00879        case 4:   /* User wants header on textfile */
00880     argerrornum( NULL, ME_HEADERONTEXTFILE);
00881        case 12:  /* User wants header on binfile  */
00882     makewavheader();
00883     break;
00884        case 0:   /* User wants header, but there is no outfile */
00885     /* Problem: what about i/o-file, 32? You might want a header
00886        on that? Better ignore this case. */
00887     break;
00888        case 8:    /* An application musn't ask for this */
00889        default:   /* This can't happen */
00890     assert( FALSE);
00891        }
00892    return;
00893 }
00894 
00895 /* --------------------------------------------------------------------
00896    Returns the index 'i' of the first argument that IS an option, and
00897    which begins with the label 's'. If there is none, -1.
00898    We also mark that option as done with, i.e. we cross it out.
00899    -------------------------------------------------------------------- */
00900 int findoption( int argcount, char *args[], char *s)
00901 {
00902    int i;
00903 
00904    if (test_usage)
00905      printf("Checking for option -%s\n", s);
00906 
00907    for (i=1; i<argcount; i++)
00908    {
00909      if (isoptionchar (args[i][0]) &&
00910     strncmp( args[i] + 1, s, strlen( s)) == 0)
00911        {
00912     args[i][0] = '\0';
00913     return i;
00914        }
00915    }
00916    return -1;
00917 }
00918 
00919 /* --------------------------------------------------------------------
00920    Finishes off the .WAV header (if any) and exits correctly and formerly.
00921    -------------------------------------------------------------------- */
00922 int myexit (int value)
00923 {
00924   switch (value)
00925     {
00926     case 0:
00927       if (wavout)
00928    makewavheader();  /* Writes a fully informed .WAV header */
00929       chat("Success!\n");
00930       break;
00931     default:
00932       chat("Failure.\n");
00933       break;
00934     }
00935   exit (value);
00936 }
00937 
00938 /* --------------------------------------------------------------------
00939    Reads the stated input file bufferwise, calls the function 'work'
00940    with the proper values, and writes the result to the stated output file.
00941    Return value: TRUE on success, FALSE otherwise.
00942    -------------------------------------------------------------------- */
00943 int workloop( FILE *theinfile, FILE *theoutfile,
00944          int (*work)( short *buffer, int length) )
00945 {
00946   short *buffer;
00947   int length, nowlength;
00948 
00949   length = BUFFSIZE;
00950   if ((buffer = malloc( sizeof(short) * length)) == NULL)
00951     fatalperror ("");
00952   while (TRUE)
00953     {
00954       nowlength = fread(buffer, sizeof(short), length, theinfile);
00955       if (ferror( theinfile) != 0)
00956    fatalperror("Error reading input file");
00957       if (nowlength == 0)   /* Reached end of input file */
00958    break;
00959       /* Call the routine that does the work */
00960       if (!work (buffer, nowlength))         /* On error, stop. */
00961    return FALSE;
00962       if (!fwrite(buffer, sizeof(short), nowlength, theoutfile)) {
00963          return FALSE;
00964       }
00965       if (ferror( theoutfile) != 0)
00966    fatalperror("Error writing to output file");
00967     }
00968   return TRUE;      /* Input file done with, no errors. */
00969 }
00970 
00971 int __attribute__((format(printf,1,2))) chat( const char *format, ...)
00972 {
00973     va_list ap;
00974     int result = 0;
00975 
00976     if (verboselevel > 5)
00977     {
00978    va_start( ap, format);
00979    result = vfprintf( stderr, format, ap);
00980    va_end( ap);
00981     }
00982     return result;
00983 }
00984 
00985 int __attribute__((format(printf,1,2))) inform( const char *format, ...)
00986 {
00987     va_list ap;
00988     int result = 0;
00989 
00990     if (verboselevel > 1)
00991     {
00992    va_start( ap, format);
00993    result = vfprintf( stderr, format, ap);
00994    va_end( ap);
00995     }
00996     return result;
00997 }
00998 
00999 int __attribute__((format(printf,1,2))) error( const char *format, ...)
01000 {
01001     va_list ap;
01002     int result;
01003 
01004     va_start( ap, format);
01005     result = vfprintf( stderr, format, ap);
01006     va_end( ap);
01007     return result;
01008 }
01009 
01010 void __attribute__((format(printf,1,2))) fatalerror( const char *format, ...)
01011 {
01012     va_list ap;
01013 
01014     va_start( ap, format);
01015     vfprintf( stderr, format, ap);
01016     va_end( ap);
01017     myexit(1);
01018 }
01019 
01020 void fatalperror( const char *string)
01021 {
01022   perror( string);
01023   myexit( 1);
01024 }
01025 
01026 int __attribute__((format(printf,1,2))) say( const char *format, ...)
01027 {
01028     va_list ap;
01029     int result;
01030 
01031     va_start( ap, format);
01032     result = vfprintf( stdout, format, ap);
01033     va_end( ap);
01034     return result;
01035 }
01036 
01037 
01038 char *malloccopy( char *string)
01039 {
01040     char *result;
01041 
01042     result = malloc( strlen( string) + 1);
01043     if (result != NULL)
01044    strcpy( result, string);
01045     return result;
01046 }
01047 
01048 
01049 char *mallocconcat( char *one, char *two)
01050 {
01051     char *result;
01052 
01053     result = malloc( strlen( one) + strlen( two) + 1);
01054     if (result != NULL)
01055       {
01056    strcpy( result, one);
01057    strcat( result, two);
01058       }
01059     return result;
01060 }
01061 
01062 double double2db( double value)
01063 {
01064   if (value < 0)
01065     value = -value;
01066   return 6.0 * log( value / 32767) / log( 2);
01067 }
01068 
01069 void readawaysamples( FILE *input, size_t size)
01070 {
01071   short *buffer;
01072   int samplesread, count;
01073 
01074   buffer = malloc( sizeof( *buffer) * BUFFSIZE);
01075   if (buffer == NULL) fatalperror("Couldn't allocate buffer");
01076 
01077   while (size > 0)
01078     {
01079       if (size > BUFFSIZE)
01080    count = BUFFSIZE;
01081       else
01082    count = size;
01083 
01084       samplesread = fread( buffer, sizeof(*buffer), count, input);
01085       if (ferror( input) != 0)
01086    fatalperror("Error reading input file");
01087       size -= samplesread;
01088     }
01089   free( buffer);
01090 }
01091 

Generated on Thu Apr 16 06:27:35 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6