Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
utils/frame.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Programs for processing sound files in raw- or WAV-format.
4  * -- Useful functions for parsing command line options and
5  * issuing errors, warnings, and chit chat.
6  *
7  * Name: frame.c
8  * Version: see static char *standardversion, below.
9  * Author: Mark Roberts <mark@manumark.de>
10  * Michael Labuschke <michael@labuschke.de> sys_errlist fixes
11  *
12  ****************************************************************************/
13 /****************************************************************************
14  * These are useful functions that all DSP programs might find handy
15  ****************************************************************************/
16 
17 #include <stdio.h>
18 #include <math.h>
19 #include <stdlib.h> /* for exit and malloc */
20 #include <string.h>
21 #include <time.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include "frame.h"
26 
27 time_t stopwatch; /* will hold time at start of calculation */
29 unsigned short samplewidth;
30 unsigned short channels;
31 int wavout; /* TRUE iff out file should be a .WAV file */
32 int iswav; /* TRUE iff in file was found to be a .WAV file */
33 FILE *in, *out;
36 char *version = "";
37 char *usage = "";
38 static int test_usage;
39 
40 static char *standardversion = "frame version 1.3, June 13th 2001";
41 static char *standardusage =
42 "\nOptions common to all mark-dsp programs:\n"
43 
44 "-h \t\t create a WAV-header on output files.\n"
45 "-c#\t\t set number of channels to # (1 or 2). Default: like input.\n"
46 "-w#\t\t set number of bits per sample (width) to # (only 16)\n"
47 "-f#\t\t set sample frequency to #. Default: like input.\n"
48 "-V \t\t verbose: talk a lot.\n"
49 "-Q \t\t quiet: talk as little as possible.\n\n"
50 "In most cases, a filename of '-' means stdin or stdout.\n\n"
51 "Bug-reports: mark@manumark.de\n"
52 ;
53 
54 /* -----------------------------------------------------------------------
55  Writes the number of samples to result that are yet to be read from anyin.
56  Return values are TRUE on success, FALSE on failure.
57  -----------------------------------------------------------------------*/
58 int getremainingfilelength( FILE *anyin, long *result)
59 {
60  long i;
61 
62  i = ftell(anyin);
63  if (i == -1) return FALSE;
64  if (fseek(anyin, 0, SEEK_END) == -1) return FALSE;
65  *result = ftell(anyin);
66  if (*result == -1) return FALSE;
67  (*result) -= i;
68  (*result) /= samplewidth;
69  if (fseek(anyin, i, SEEK_SET) == -1) return FALSE;
70  return TRUE;
71 }
72 
73 /* -----------------------------------------------------------------------
74  Read a .pk-header from 'anyin'.
75  -----------------------------------------------------------------------*/
76 void readpkheader( FILE *anyin)
77 {
78  unsigned short tempushort;
79  int tempint, i, x;
80  unsigned char blood[8];
81 
82  for (i = 0; i < 11; i++)
83  {
84  if (!fread( &tempint, 4, 1, anyin)) {
85  return;
86  }
87  printf( "%d: %d, ", i, tempint);
88  }
89  printf( "\n");
90  if (!fread( blood, 1, 8, anyin)) {
91  return;
92  }
93  for (i = 0; i < 8; i++)
94  printf( "%d ", blood[i]);
95  printf( "\n");
96  for (i = 0; i < 8; i++)
97  {
98  for (x = 128; x > 0; x /= 2)
99  printf((blood[i] & x) == 0? "0 ":"1 ");
100  printf(i%4==3? "\n":"| ");
101  }
102  printf( "\n");
103  for (i = 0; i < 2; i++)
104  {
105  if (!fread( &tempint, 4, 1, anyin)) {
106  return;
107  }
108  printf( "%d: %d, ", i, tempint);
109  }
110  printf( "\n");
111  for (i = 0; i < 2; i++)
112  {
113  if (!fread( &tempushort, 2, 1, anyin)) {
114  return;
115  }
116  printf( "%d: %d, ", i, tempushort);
117  }
118  printf( "\n");
119 }
120 
121 
122 
123 /* -----------------------------------------------------------------------
124  Read a .WAV header from 'anyin'. See header for details.
125  -----------------------------------------------------------------------*/
126 void readwavheader( FILE *anyin)
127 {
128  unsigned int tempuint, sf;
129  unsigned short tempushort, cn;
130  char str[9];
131  int nowav = FALSE;
132 
133  iswav = FALSE;
134 
135  if (ftell(anyin) == -1) /* If we cannot seek this file */
136  {
137  nowav = TRUE; /* -> Pretend this is no wav-file */
138  chat("File not seekable: not checking for WAV-header.\n");
139  }
140  else
141  {
142  /* Expect four bytes "RIFF" and four bytes filelength */
143  if (!fread(str, 1, 8, anyin)) { /* 0 */
144  return;
145  }
146  str[4] = '\0';
147  if (strcmp(str, "RIFF") != 0) nowav = TRUE;
148  /* Expect eight bytes "WAVEfmt " */
149  if (!fread(str, 1, 8, anyin)) { /* 8 */
150  return;
151  }
152  str[8] = '\0';
153  if (strcmp(str, "WAVEfmt ") != 0) nowav = TRUE;
154  /* Expect length of fmt data, which should be 16 */
155  if (!fread(&tempuint, 4, 1, anyin)) { /* 16 */
156  return;
157  }
158  if (tempuint != 16) nowav = TRUE;
159  /* Expect format tag, which should be 1 for pcm */
160  if (!fread(&tempushort, 2, 1, anyin)) { /* 20 */
161  return;
162  }
163  if (tempushort != 1)
164  nowav = TRUE;
165  /* Expect number of channels */
166  if (!fread(&cn, 2, 1, anyin)) { /* 20 */
167  return;
168  }
169  if (cn != 1 && cn != 2) nowav = TRUE;
170  /* Read samplefrequency */
171  if (!fread(&sf, 4, 1, anyin)) { /* 24 */
172  return;
173  }
174  /* Read bytes per second: Should be samplefreq * channels * 2 */
175  if (!fread(&tempuint, 4, 1, anyin)) { /* 28 */
176  return;
177  }
178  if (tempuint != sf * cn * 2) nowav = TRUE;
179  /* read bytes per frame: Should be channels * 2 */
180  if (!fread(&tempushort, 2, 1, anyin)) { /* 32 */
181  return;
182  }
183  if (tempushort != cn * 2) nowav = TRUE;
184  /* Read bits per sample: Should be 16 */
185  if (!fread(&tempushort, 2, 1, anyin)) { /* 34 */
186  return;
187  }
188  if (tempushort != 16) nowav = TRUE;
189  if (!fread(str, 4, 1, anyin)) { /* 36 */
190  return;
191  }
192  str[4] = '\0';
193  if (strcmp(str, "data") != 0) nowav = TRUE;
194  if (!fread(&tempuint, 4, 1, anyin)) { /* 40 */
195  return;
196  }
197  if (nowav)
198  {
199  fseek(anyin, 0, SEEK_SET); /* Back to beginning of file */
200  chat("File has no WAV header.\n");
201  }
202  else
203  {
204  samplefrequency = sf;
205  channels = cn;
206  chat("Read WAV header: %d channels, samplefrequency %d.\n",
208  iswav = TRUE;
209  }
210  }
211  return;
212 }
213 
214 
215 
216 /* -----------------------------------------------------------------------
217  Write a .WAV header to 'out'. See header for details.
218  -----------------------------------------------------------------------*/
219 void makewavheader( void)
220 {
221  unsigned int tempuint, filelength;
222  unsigned short tempushort;
223 
224  /* If fseek fails, don't create the header. */
225  if (fseek(out, 0, SEEK_END) != -1)
226  {
227  filelength = ftell(out);
228  chat("filelength %d, ", filelength);
229  fseek(out, 0, SEEK_SET);
230  if (!fwrite("RIFF", 1, 4, out)) { /* 0 */
231  return;
232  }
233  tempuint = filelength - 8;
234  if (!fwrite(&tempuint, 4, 1, out)) { /* 4 */
235  return;
236  }
237  if (!fwrite("WAVEfmt ", 1, 8, out)) { /* 8 */
238  return;
239  }
240  /* length of fmt data 16 bytes */
241  tempuint = 16;
242  if (!fwrite(&tempuint, 4, 1, out)) { /* 16 */
243  return;
244  }
245  /* Format tag: 1 for pcm */
246  tempushort = 1;
247  if (!fwrite(&tempushort, 2, 1, out)) { /* 20 */
248  return;
249  }
250  chat("%d channels\n", channels);
251  if (!fwrite(&channels, 2, 1, out)) {
252  return;
253  }
254  chat("samplefrequency %d\n", samplefrequency);
255  if (!fwrite(&samplefrequency, 4, 1, out)) { /* 24 */
256  return;
257  }
258  /* Bytes per second */
259  tempuint = channels * samplefrequency * 2;
260  if (!fwrite(&tempuint, 4, 1, out)) { /* 28 */
261  return;
262  }
263  /* Block align */
264  tempushort = 2 * channels;
265  if (!fwrite(&tempushort, 2, 1, out)) { /* 32 */
266  return;
267  }
268  /* Bits per sample */
269  tempushort = 16;
270  if (!fwrite(&tempushort, 2, 1, out)) { /* 34 */
271  return;
272  }
273  if (!fwrite("data", 4, 1, out)) { /* 36 */
274  return;
275  }
276  tempuint = filelength - 44;
277  if (!fwrite(&tempuint, 4, 1, out)) { /* 40 */
278  return;
279  }
280  }
281  return;
282 }
283 
284 /* -----------------------------------------------------------------------
285  After all is read and done, inform the inclined user of the elapsed time
286  -----------------------------------------------------------------------*/
287 static void statistics( void)
288 {
289  int temp;
290 
291  temp = time(NULL) - stopwatch;
292  if (temp != 1)
293  {
294  inform ("\nTime: %d seconds\n", temp);
295  }
296  else
297  {
298  inform ("\nTime: 1 second\n");
299  }
300  return;
301 }
302 
303 
304 /* -----------------------------------------------------------------------
305  Start the stopwatch and make sure the user is informed at end of program.
306  -----------------------------------------------------------------------*/
307 void startstopwatch(void)
308 {
309  stopwatch = time(NULL); /* Remember time 'now' */
310  atexit(statistics); /* Call function statistics() at exit. */
311 
312  return;
313 }
314 
315 /* --------------------------------------------------------------------
316  Tests the character 'coal' for being a command line option character,
317  momentarrily '-'.
318  -------------------------------------------------------------------- */
319 int isoptionchar (char coal)
320 {
321  return (coal =='-');
322 }
323 
324 /* -----------------------------------------------------------------------
325  Reads through the arguments on the lookout for an option starting
326  with 'string'. The rest of the option is read as a time and passed
327  to *result, where the result is meant to mean 'number of samples' in
328  that time.
329  On failure, *result is unchanged.
330  return value is TRUE on success, FALSE otherwise.
331  -----------------------------------------------------------------------*/
332 int parsetimearg( int argcount, char *args[], char *string, int *result)
333 {
334  int i;
335 
336  if ((i = findoption( argcount, args, string)) > 0)
337  {
338  if (parsetime(args[i] + 1 + strlen( string), result))
339  return TRUE;
340  argerrornum(args[i]+1, ME_NOTIME);
341  }
342  return FALSE;
343 }
344 
345 /* -----------------------------------------------------------------------
346  The string argument is read as a time and passed
347  to *result, where the result is meant to mean 'number of samples' in
348  that time.
349  On failure, *result is unchanged.
350  return value is TRUE on success, FALSE otherwise.
351  -----------------------------------------------------------------------*/
352 int parsetime(char *string, int *result)
353 {
354  int k;
355  double temp;
356  char m, s, end;
357 
358  k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
359  switch (k)
360  {
361  case 0: case EOF: case 4:
362  return FALSE;
363  case 1:
364  *result = temp;
365  break;
366  case 2:
367  if (m == 's')
368  *result = temp * samplefrequency;
369  else
370  return FALSE;
371  break;
372  case 3:
373  if (m == 'm' && s == 's')
374  *result = temp * samplefrequency / 1000;
375  else if (m == 'H' && s == 'z')
376  *result = samplefrequency / temp;
377  else
378  return FALSE;
379  break;
380  default:
382  }
383  return TRUE;
384 }
385 
386 /* -----------------------------------------------------------------------
387  The string argument is read as a frequency and passed
388  to *result, where the result is meant to mean 'number of samples' in
389  one cycle of that frequency.
390  On failure, *result is unchanged.
391  return value is TRUE on success, FALSE otherwise.
392  -----------------------------------------------------------------------*/
393 int parsefreq(char *string, double *result)
394 {
395  int k;
396  double temp;
397  char m, s, end;
398 
399  k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
400  switch (k)
401  {
402  case 0: case EOF: case 2: case 4:
403  return FALSE;
404  case 1:
405  *result = temp;
406  break;
407  case 3:
408  if (m == 'H' && s == 'z')
409  *result = samplefrequency / temp;
410  else
411  return FALSE;
412  break;
413  default:
415  }
416  return TRUE;
417 }
418 
419 char *parsefilearg( int argcount, char *args[])
420 {
421  int i;
422  char *result = NULL;
423 
424  for (i = 1; i < argcount; i++)
425  {
426  if (args[i][0] != '\0' &&
427  (!isoptionchar (args[i][0]) || args[i][1] == '\0' ))
428  {
429  /*---------------------------------------------*
430  * The argument is a filename: *
431  * it is either no dash followed by something, *
432  * or it is a dash following by nothing. *
433  *---------------------------------------------*/
434  result = malloc( strlen( args[i]) + 1);
435  if (result == NULL)
436  fatalperror( "Couldn't allocate memory for filename\n");
437  strcpy( result, args[i]);
438  args[i][0] = '\0'; /* Mark as used up */
439  break;
440  }
441  }
442  return result;
443 }
444 
445 int parseswitch( char *found, char *wanted)
446 {
447  if (strncmp( found, wanted, strlen( wanted)) == 0)
448  {
449  if (found[strlen( wanted)] == '\0')
450  return TRUE;
451  else
452  argerrornum( found, ME_NOSWITCH);
453  }
454  return FALSE;
455 }
456 
457 int parseswitcharg( int argcount, char *args[], char *string)
458 {
459  int i;
460 
461  if ((i = findoption( argcount, args, string)) > 0)
462  {
463  if (args[i][strlen( string) + 1] == '\0')
464  return TRUE;
465  else
466  argerrornum( args[i] + 1, ME_NOSWITCH);
467  }
468  return FALSE;
469 }
470 
471 int parseintarg( int argcount, char *args[], char *string, int *result)
472 {
473  int i, temp;
474  char c;
475 
476  if ((i = findoption( argcount, args, string)) > 0)
477  {
478  switch (sscanf(args[i] + 1 + strlen( string),
479  "%30d%1c", &temp, &c))
480  {
481  case 0: case EOF: case 2:
482  argerrornum(args[i]+1, ME_NOINT);
483  return FALSE;
484  case 1:
485  *result = temp;
486  break;
487  default:
488  say("frame.c: This can't happen\n");
489  }
490  return TRUE;
491  }
492  else
493  {
494  return FALSE;
495  }
496 }
497 
498 /* --------------------------------------------------------------------
499  Reads through the arguments on the lookout for an option starting
500  with 'string'. The rest of the option is read as a double and
501  passed to *result.
502  On failure, *result is unchanged.
503  return value is TRUE on success, FALSE otherwise.
504  -------------------------------------------------------------------- */
505 int parsedoublearg( int argcount, char *args[], char *string, double *result)
506 {
507  int i;
508  double temp;
509  char end;
510 
511  if ((i = findoption( argcount, args, string)) > 0)
512  {
513  switch (sscanf(args[i] + 1 + strlen( string), "%30lf%1c", &temp, &end))
514  {
515  case 0: case EOF: case 2:
516  argerrornum(args[i]+1, ME_NODOUBLE);
517  return FALSE;
518  case 1:
519  *result = temp;
520  break;
521  default:
522  say("frame.c: This can't happen\n");
523  }
524  return TRUE;
525  }
526  else
527  {
528  return FALSE;
529  }
530 }
531 
532 /* --------------------------------------------------------------------
533  Reads through the arguments on the lookout for an option starting
534  with 'string'. The rest of the option is read as a volume, i.e.
535  absolute, percent or db. The result is passed to *result.
536  On failure, *result is unchanged.
537  return value is TRUE on success, FALSE otherwise.
538  -------------------------------------------------------------------- */
539 int parsevolarg( int argcount, char *args[], char *string, double *result)
540 {
541  double vol = 1.0;
542  char sbd, sbb, end;
543  int i, weird = FALSE;
544 
545  if ((i = findoption( argcount, args, string)) > 0)
546  {
547  switch (sscanf(args[i] + 1 + strlen( string),
548  "%30lf%1c%1c%1c", &vol, &sbd, &sbb, &end))
549  {
550  case 0: case EOF: case 4:
551  weird = TRUE;
552  break; /* No number: error */
553  case 1:
554  *result = vol;
555  break;
556  case 2:
557  if (sbd == '%')
558  *result = vol / 100;
559  else
560  weird = TRUE; /* One char but no percent: error */
561  break;
562  case 3:
563  if (sbd =='d' && sbb == 'b')
564  *result = pow(2, vol / 6.02);
565  else
566  weird = TRUE; /* Two chars but not db: error */
567  break;
568  default:
569  say("frame.c: This can't happen.\n");
570  }
571  if (weird)
572  argerrornum( args[i] + 1, ME_NOVOL);
573  /* ("Weird option: couldn't parse volume '%s'\n", args[i]+2); */
574  return !weird;
575  }
576  else
577  {
578  return FALSE;
579  }
580 }
581 
582 
583 /* --------------------------------------------------------------------
584  Reads the specified string 's' and interprets it as a volume. The string
585  would be of the form 1.8 or 180% or 5db.
586  On success, the return value TRUE and *result is given result
587  (i.e. the relative volume, i.e. 1.8). On failure, FALSE is returned and
588  result is given value 1.0.
589  -------------------------------------------------------------------- */
590 int parsevolume(char *s, double *result)
591 {
592  int k;
593  char sbd, sbb, end;
594 
595  *result = 1.0;
596  k = sscanf(s, "%30lf%1c%1c%1c", result, &sbd, &sbb, &end);
597  switch (k)
598  {
599  case 0:
600  case EOF:
601  case 4:
602  return FALSE;
603  case 1:
604  break;
605  case 2:
606  if (sbd != '%')
607  return FALSE;
608  (*result) /=100;
609  break;
610  case 3:
611  if (sbd !='d' || sbb != 'b')
612  return FALSE;
613  (*result) = pow(2, (*result) / 6.02);
614  break;
615  default:
616  say("parsevolume: This can't happen (%d).\n", k);
617  }
618  return TRUE;
619 }
620 
621 /* --------------------------------------------------------------------
622  Reports an error due to parsing the string 's' encountered on the
623  command line.
624  -------------------------------------------------------------------- */
625 void argerror(char *s)
626 {
627  error ("Error parsing command line. Unrecognized option:\n\t-%s\n", s);
628  fatalerror("\nTry --help for help.\n");
629 }
630 
631 /* --------------------------------------------------------------------
632  Reports an error due to parsing the string 's' encountered on the
633  command line. 'code' indicates the type of error.
634  -------------------------------------------------------------------- */
635 void argerrornum(char *s, Errornum code)
636 {
637  char *message;
638 
639  if (code == ME_TOOMANYFILES)
640  {
641  error("Too many files on command line: '%s'.\n", s);
642  }
643  else
644  {
645  if (s != NULL)
646  error ("Error parsing option -%s:\n\t", s);
647  switch( code)
648  {
649  case ME_NOINT:
650  message = "Integer expected";
651  break;
652  case ME_NODOUBLE:
653  message = "Floating point number expected";
654  break;
655  case ME_NOTIME:
656  message = "Time argument expected";
657  break;
658  case ME_NOVOL:
659  message = "Volume argument expected";
660  break;
661  case ME_NOSWITCH:
662  message = "Garbage after switch-type option";
663  break;
664  case ME_HEADERONTEXTFILE:
665  message = "Option -h is not useful for text-output";
666  break;
667  case ME_NOINFILE:
668  message = "No input file specified";
669  break;
670  case ME_NOOUTFILE:
671  message = "No output file specified";
672  break;
673  case ME_NOIOFILE:
674  message = "No input/output file specified";
675  break;
676  case ME_NOSTDIN:
677  message = "Standard in not supported here";
678  break;
679  case ME_NOSTDOUT:
680  message = "Standard out not supported here";
681  break;
682  case ME_NOSTDIO:
683  message = "Standard in/out not supported here";
684  break;
685  case ME_NOTENOUGHFILES:
686  message = "Not enough files specified";
687  break;
688  case ME_THISCANTHAPPEN:
689  fatalerror("\nThis can't happen. Report this as a bug\n");
690  /* fatalerror does not return */
691  default:
692  error("Error code %d not implemented. Fix me!\n", code);
693  message = "Error message not implemented. Fix me!";
694  }
695  error("%s\n", message);
696  }
697  fatalerror("\nTry --help for help.\n");
698 }
699 
700 /* --------------------------------------------------------------------
701  Reports an error due to parsing the string 's' encountered on the
702  command line. 'message' explains the type of error.
703  -------------------------------------------------------------------- */
704 void argerrortxt(char *s, char *message)
705 {
706  if (s != NULL)
707  error ("Error parsing option -%s:\n\t", s);
708  else
709  error ("Error parsing command line:\n\t");
710  error ("%s\n", message);
711  fatalerror("\nTry --help for help.\n");
712 }
713 
714 /* --------------------------------------------------------------------
715  Check for any remaining arguments and complain about their existence
716  -------------------------------------------------------------------- */
717 void checknoargs( int argcount, char *args[])
718 {
719  int i, errorcount = 0;
720 
721  for (i = 1; i < argcount; i++)
722  {
723  if (args[i][0] != '\0') /* An unused argument! */
724  {
725  errorcount++;
726  if (errorcount == 1)
727  error("The following arguments were not recognized:\n");
728  error("\t%s\n", args[i]);
729  }
730  }
731  if (errorcount > 0) /* Errors are fatal */
732  fatalerror("\nTry --help for help.\n");
733 
734  return; /* No errors? Return. */
735 }
736 
737 /* --------------------------------------------------------------------
738  Parses the command line arguments as represented by the function
739  arguments. Sets the global variables 'in', 'out', 'samplefrequency'
740  and 'samplewidth' accordingly. Also verboselevel.
741  The files 'in' and 'out' are even opened according to 'fileswitch'.
742  See headerfile for details
743  -------------------------------------------------------------------- */
744 void parseargs( int argcount, char *args[], int fileswitch)
745 {
746  char *filename;
747  int tempint = 0;
748 
749  if ((fileswitch & 1) != 0) /* If getting infile */
750  in = NULL;
751  if ((fileswitch & 4) != 0) /* If getting outfile */
752  out = NULL;
753  wavout = FALSE;
754  verboselevel = 5;
756  samplewidth = 2;
757  channels = 1;
758 
759  /*-----------------------------------------------*
760  * First first check testcase, usage and version *
761  *-----------------------------------------------*/
762  test_usage = parseswitcharg( argcount, args, "-test-usage");
763  if (parseswitcharg( argcount, args, "-help"))
764  {
765  printf("%s%s", usage, standardusage);
766  exit(0);
767  }
768  if (parseswitcharg( argcount, args, "-version"))
769  {
770  printf("%s\n(%s)\n", version, standardversion);
771  exit(0);
772  }
773  /*--------------------------------------*
774  * Set verboselevel *
775  *--------------------------------------*/
776  while (parseswitcharg( argcount, args, "V"))
777  verboselevel = 10;
778  while (parseswitcharg( argcount, args, "Q"))
779  verboselevel = 1;
780  /*-------------------------------------------------*
781  * Get filenames and open files *
782  *-------------------------------------------------*/
783  if ((fileswitch & 1) != 0) /* Infile wanted */
784  {
785  infilename = parsefilearg( argcount, args);
786  if (infilename == NULL)
788  if (strcmp( infilename, "-") == 0)
789  {
790  infilename = "<stdin>";
791  in = stdin;
792  if ((fileswitch & 2) != 0) /* Binfile wanted */
793  readwavheader( in);
794  }
795  else
796  {
797  if ((fileswitch & 2) == 0) /* Textfile wanted */
798  in = fopen(infilename, "rt");
799  else /* Binfile wanted */
800  if ((in = fopen(infilename, "rb")) != NULL)
801  readwavheader( in);
802  }
803  if (in == NULL)
804  fatalerror("Error opening input file '%s': %s\n", infilename,strerror(errno));
805  else
806  inform("Using file '%s' as input\n", infilename);
807  }
808  if ((fileswitch & 4) != 0) /* Outfile wanted */
809  {
810  outfilename = parsefilearg( argcount, args);
811  if (outfilename == NULL)
813  if (strcmp( outfilename, "-") == 0)
814  {
815  outfilename = "<stdout>";
816  out = stdout;
817  }
818  else
819  {
820 
821  if ((fileswitch & 8) == 0) /* Textfile wanted */
822  out = fopen(outfilename, "wt");
823  else /* Binfile wanted */
824  out = fopen(outfilename, "wb");
825  }
826  if (out == NULL)
827  fatalerror("Error opening output file '%s': %s\n", outfilename,strerror(errno));
828  else
829  inform("Using file '%s' as output\n", outfilename);
830  }
831  if ((fileswitch & 32) != 0) /* In-/Outfile wanted */
832  {
833  assert (in == NULL && out == NULL);
834  infilename = outfilename = parsefilearg( argcount, args);
835  if (outfilename == NULL)
837  if (strcmp( infilename, "-") == 0)
839  inform("Using file '%s' as input/output\n", outfilename);
840  in = out = fopen(outfilename, "r+");
841  if (out == NULL)
842  fatalerror("Error opening input/output file '%s': %s\n", outfilename,strerror(errno));
843 
844  readwavheader( in);
845  }
846  if ((fileswitch & 16) == 0) /* No additional files wanted */
847  {
848  if ((filename = parsefilearg( argcount, args)) != NULL)
849  argerrornum( filename, ME_TOOMANYFILES);
850  }
851 
852  /*-------------------------------------------------*
853  * Set samplefrequency, width, wavout,
854  *-------------------------------------------------*/
855  parseintarg( argcount, args, "f", &samplefrequency);
856  wavout = parseswitcharg( argcount, args, "h");
857  if (parseintarg( argcount, args, "w", &tempint))
858  {
859  if (tempint != 16)
860  argerrortxt(NULL, "Option -w is only valid "
861  "with value 16. Sorry.");
862  else
863  samplewidth = tempint;
864  }
865  if (parseintarg( argcount, args, "c", &tempint))
866  {
867  if (tempint != 1 && tempint != 2)
868  argerrortxt(NULL, "Option -c is only valid "
869  "with values 1 or 2. Sorry.");
870  else
871  channels = tempint;
872  }
873  /*-------------------------------------------------*
874  * Create WAV-header on output if wanted. *
875  *-------------------------------------------------*/
876  if (wavout)
877  switch (fileswitch & (12))
878  {
879  case 4: /* User wants header on textfile */
881  case 12: /* User wants header on binfile */
882  makewavheader();
883  break;
884  case 0: /* User wants header, but there is no outfile */
885  /* Problem: what about i/o-file, 32? You might want a header
886  on that? Better ignore this case. */
887  break;
888  case 8: /* An application musn't ask for this */
889  default: /* This can't happen */
890  assert( FALSE);
891  }
892  return;
893 }
894 
895 /* --------------------------------------------------------------------
896  Returns the index 'i' of the first argument that IS an option, and
897  which begins with the label 's'. If there is none, -1.
898  We also mark that option as done with, i.e. we cross it out.
899  -------------------------------------------------------------------- */
900 int findoption( int argcount, char *args[], char *s)
901 {
902  int i;
903 
904  if (test_usage)
905  printf("Checking for option -%s\n", s);
906 
907  for (i=1; i<argcount; i++)
908  {
909  if (isoptionchar (args[i][0]) &&
910  strncmp( args[i] + 1, s, strlen( s)) == 0)
911  {
912  args[i][0] = '\0';
913  return i;
914  }
915  }
916  return -1;
917 }
918 
919 /* --------------------------------------------------------------------
920  Finishes off the .WAV header (if any) and exits correctly and formerly.
921  -------------------------------------------------------------------- */
922 int myexit (int value)
923 {
924  switch (value)
925  {
926  case 0:
927  if (wavout)
928  makewavheader(); /* Writes a fully informed .WAV header */
929  chat("Success!\n");
930  break;
931  default:
932  chat("Failure.\n");
933  break;
934  }
935  exit (value);
936 }
937 
938 /* --------------------------------------------------------------------
939  Reads the stated input file bufferwise, calls the function 'work'
940  with the proper values, and writes the result to the stated output file.
941  Return value: TRUE on success, FALSE otherwise.
942  -------------------------------------------------------------------- */
943 int workloop( FILE *theinfile, FILE *theoutfile,
944  int (*work)( short *buffer, int length) )
945 {
946  short *buffer;
947  int length, nowlength;
948 
949  length = BUFFSIZE;
950  if ((buffer = malloc( sizeof(short) * length)) == NULL)
951  fatalperror ("");
952  while (TRUE)
953  {
954  nowlength = fread(buffer, sizeof(short), length, theinfile);
955  if (ferror( theinfile) != 0)
956  fatalperror("Error reading input file");
957  if (nowlength == 0) /* Reached end of input file */
958  break;
959  /* Call the routine that does the work */
960  if (!work (buffer, nowlength)) /* On error, stop. */
961  return FALSE;
962  if (!fwrite(buffer, sizeof(short), nowlength, theoutfile)) {
963  return FALSE;
964  }
965  if (ferror( theoutfile) != 0)
966  fatalperror("Error writing to output file");
967  }
968  return TRUE; /* Input file done with, no errors. */
969 }
970 
971 int __attribute__((format(printf,1,2))) chat( const char *format, ...)
972 {
973  va_list ap;
974  int result = 0;
975 
976  if (verboselevel > 5)
977  {
978  va_start( ap, format);
979  result = vfprintf( stderr, format, ap);
980  va_end( ap);
981  }
982  return result;
983 }
984 
985 int __attribute__((format(printf,1,2))) inform( const char *format, ...)
986 {
987  va_list ap;
988  int result = 0;
989 
990  if (verboselevel > 1)
991  {
992  va_start( ap, format);
993  result = vfprintf( stderr, format, ap);
994  va_end( ap);
995  }
996  return result;
997 }
998 
999 int __attribute__((format(printf,1,2))) error( const char *format, ...)
1000 {
1001  va_list ap;
1002  int result;
1003 
1004  va_start( ap, format);
1005  result = vfprintf( stderr, format, ap);
1006  va_end( ap);
1007  return result;
1008 }
1009 
1010 void __attribute__((format(printf,1,2))) fatalerror( const char *format, ...)
1011 {
1012  va_list ap;
1013 
1014  va_start( ap, format);
1015  vfprintf( stderr, format, ap);
1016  va_end( ap);
1017  myexit(1);
1018 }
1019 
1020 void fatalperror( const char *string)
1021 {
1022  perror( string);
1023  myexit( 1);
1024 }
1025 
1026 int __attribute__((format(printf,1,2))) say( const char *format, ...)
1027 {
1028  va_list ap;
1029  int result;
1030 
1031  va_start( ap, format);
1032  result = vfprintf( stdout, format, ap);
1033  va_end( ap);
1034  return result;
1035 }
1036 
1037 
1038 char *malloccopy( char *string)
1039 {
1040  char *result;
1041 
1042  result = malloc( strlen( string) + 1);
1043  if (result != NULL)
1044  strcpy( result, string);
1045  return result;
1046 }
1047 
1048 
1049 char *mallocconcat( char *one, char *two)
1050 {
1051  char *result;
1052 
1053  result = malloc( strlen( one) + strlen( two) + 1);
1054  if (result != NULL)
1055  {
1056  strcpy( result, one);
1057  strcat( result, two);
1058  }
1059  return result;
1060 }
1061 
1062 double double2db( double value)
1063 {
1064  if (value < 0)
1065  value = -value;
1066  return 6.0 * log( value / 32767) / log( 2);
1067 }
1068 
1069 void readawaysamples( FILE *input, size_t size)
1070 {
1071  short *buffer;
1072  int samplesread, count;
1073 
1074  buffer = malloc( sizeof( *buffer) * BUFFSIZE);
1075  if (buffer == NULL) fatalperror("Couldn't allocate buffer");
1076 
1077  while (size > 0)
1078  {
1079  if (size > BUFFSIZE)
1080  count = BUFFSIZE;
1081  else
1082  count = size;
1083 
1084  samplesread = fread( buffer, sizeof(*buffer), count, input);
1085  if (ferror( input) != 0)
1086  fatalperror("Error reading input file");
1087  size -= samplesread;
1088  }
1089  free( buffer);
1090 }
static void statistics(void)
Definition: utils/frame.c:287
int myexit(int value)
Definition: utils/frame.c:922
#define FALSE
Definition: app_minivm.c:521
void fatalperror(const char *string)
Definition: utils/frame.c:1020
static char * standardversion
Definition: utils/frame.c:40
int samplefrequency
Definition: utils/frame.c:28
Time-related functions and macros.
void makewavheader(void)
Definition: utils/frame.c:219
void parseargs(int argcount, char *args[], int fileswitch)
Definition: utils/frame.c:744
unsigned short samplewidth
Definition: utils/frame.c:29
time_t stopwatch
Definition: utils/frame.c:27
void startstopwatch(void)
Definition: utils/frame.c:307
int isoptionchar(char coal)
Definition: utils/frame.c:319
int workloop(FILE *theinfile, FILE *theoutfile, int(*work)(short *buffer, int length))
Definition: utils/frame.c:943
double double2db(double value)
Definition: utils/frame.c:1062
int parsevolarg(int argcount, char *args[], char *string, double *result)
Definition: utils/frame.c:539
static struct test_val c
const char * str
Definition: app_jack.c:147
const char * args
#define NULL
Definition: resample.c:96
int parseswitcharg(int argcount, char *args[], char *string)
Definition: utils/frame.c:457
char * end
Definition: eagi_proxy.c:73
int value
Definition: syslog.c:37
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
char * malloccopy(char *string)
Definition: utils/frame.c:1038
int inform(const char *format,...)
Definition: utils/frame.c:985
char * infilename
Definition: utils/frame.c:34
char * malloc()
char * version
Definition: utils/frame.c:36
int findoption(int argcount, char *args[], char *s)
Definition: utils/frame.c:900
void free()
FILE * in
Definition: utils/frame.c:33
void fatalerror(const char *format,...)
Definition: utils/frame.c:1010
int iswav
Definition: utils/frame.c:32
int parsetimearg(int argcount, char *args[], char *string, int *result)
Definition: utils/frame.c:332
static int test_usage
Definition: utils/frame.c:38
int parseintarg(int argcount, char *args[], char *string, int *result)
Definition: utils/frame.c:471
char * usage
Definition: utils/frame.c:37
int wavout
Definition: utils/frame.c:31
int parseswitch(char *found, char *wanted)
Definition: utils/frame.c:445
Errornum
Definition: utils/frame.h:60
int errno
int say(const char *format,...)
Definition: utils/frame.c:1026
static char * standardusage
Definition: utils/frame.c:41
void readawaysamples(FILE *input, size_t size)
Definition: utils/frame.c:1069
char * mallocconcat(char *one, char *two)
Definition: utils/frame.c:1049
void argerror(char *s)
Definition: utils/frame.c:625
unsigned short channels
Definition: utils/frame.c:30
void readpkheader(FILE *anyin)
Definition: utils/frame.c:76
void argerrortxt(char *s, char *message)
Definition: utils/frame.c:704
int chat(const char *format,...)
Definition: utils/frame.c:971
int parsedoublearg(int argcount, char *args[], char *string, double *result)
Definition: utils/frame.c:505
int getremainingfilelength(FILE *anyin, long *result)
Definition: utils/frame.c:58
int parsevolume(char *s, double *result)
Definition: utils/frame.c:590
void readwavheader(FILE *anyin)
Definition: utils/frame.c:126
FILE * out
Definition: utils/frame.c:33
int parsetime(char *string, int *result)
Definition: utils/frame.c:352
#define TRUE
Definition: app_minivm.c:518
static PGresult * result
Definition: cel_pgsql.c:88
int error(const char *format,...)
Definition: utils/frame.c:999
#define DEFAULTFREQ
Definition: utils/frame.h:53
char * outfilename
Definition: utils/frame.c:34
void argerrornum(char *s, Errornum code)
Definition: utils/frame.c:635
static snd_pcm_format_t format
Definition: chan_alsa.c:102
void checknoargs(int argcount, char *args[])
Definition: utils/frame.c:717
int parsefreq(char *string, double *result)
Definition: utils/frame.c:393
char * parsefilearg(int argcount, char *args[])
Definition: utils/frame.c:419
#define BUFFSIZE
Definition: utils/frame.h:54
int verboselevel
Definition: utils/frame.c:35