Asterisk - The Open Source Telephony Project GIT-master-f36a736
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
27time_t stopwatch; /* will hold time at start of calculation */
29unsigned short samplewidth;
30unsigned short channels;
31int wavout; /* TRUE iff out file should be a .WAV file */
32int iswav; /* TRUE iff in file was found to be a .WAV file */
33FILE *in, *out;
36char *version = "";
37char *usage = "";
38static int test_usage;
39
40static char *standardversion = "frame version 1.3, June 13th 2001";
41static 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 -----------------------------------------------------------------------*/
58int 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 -----------------------------------------------------------------------*/
76void 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 -----------------------------------------------------------------------*/
126void 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 -----------------------------------------------------------------------*/
219void 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 -----------------------------------------------------------------------*/
287static 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 -----------------------------------------------------------------------*/
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 momentarily '-'.
318 -------------------------------------------------------------------- */
319int 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 -----------------------------------------------------------------------*/
332int 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;
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 -----------------------------------------------------------------------*/
352int 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 -----------------------------------------------------------------------*/
393int 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
419char *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
445int 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
457int 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
471int 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:
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 -------------------------------------------------------------------- */
505int 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:
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 -------------------------------------------------------------------- */
539int 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 -------------------------------------------------------------------- */
590int 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 -------------------------------------------------------------------- */
625void 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 -------------------------------------------------------------------- */
635void 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;
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;
686 message = "Not enough files specified";
687 break;
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 -------------------------------------------------------------------- */
704void 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 -------------------------------------------------------------------- */
717void 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 -------------------------------------------------------------------- */
744void 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 */
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)
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
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 */
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 mustn'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 -------------------------------------------------------------------- */
900int 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 -------------------------------------------------------------------- */
922int 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 -------------------------------------------------------------------- */
943int 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
971int __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
985int __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
999int __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
1010void __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
1020void fatalperror( const char *string)
1021{
1022 perror( string);
1023 myexit( 1);
1024}
1025
1026int __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
1038char *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
1049char *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
1062double double2db( double value)
1063{
1064 if (value < 0)
1065 value = -value;
1066 return 6.0 * log( value / 32767) / log( 2);
1067}
1068
1069void 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}
const char * str
Definition: app_jack.c:147
#define TRUE
Definition: app_minivm.c:524
#define FALSE
Definition: app_minivm.c:527
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570
static PGresult * result
Definition: cel_pgsql.c:84
char * end
Definition: eagi_proxy.c:73
char * malloc()
void free()
int errno
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
const char * args
static struct test_val c
Time-related functions and macros.
char * mallocconcat(char *one, char *two)
Definition: utils/frame.c:1049
double double2db(double value)
Definition: utils/frame.c:1062
int verboselevel
Definition: utils/frame.c:35
void argerrornum(char *s, Errornum code)
Definition: utils/frame.c:635
time_t stopwatch
Definition: utils/frame.c:27
void fatalperror(const char *string)
Definition: utils/frame.c:1020
int myexit(int value)
Definition: utils/frame.c:922
int say(const char *format,...)
Definition: utils/frame.c:1026
char * malloccopy(char *string)
Definition: utils/frame.c:1038
static char * standardversion
Definition: utils/frame.c:40
int parsetimearg(int argcount, char *args[], char *string, int *result)
Definition: utils/frame.c:332
FILE * out
Definition: utils/frame.c:33
int error(const char *format,...)
Definition: utils/frame.c:999
void argerror(char *s)
Definition: utils/frame.c:625
static int test_usage
Definition: utils/frame.c:38
char * version
Definition: utils/frame.c:36
int iswav
Definition: utils/frame.c:32
void readwavheader(FILE *anyin)
Definition: utils/frame.c:126
int wavout
Definition: utils/frame.c:31
int getremainingfilelength(FILE *anyin, long *result)
Definition: utils/frame.c:58
void argerrortxt(char *s, char *message)
Definition: utils/frame.c:704
int samplefrequency
Definition: utils/frame.c:28
int parsetime(char *string, int *result)
Definition: utils/frame.c:352
static char * standardusage
Definition: utils/frame.c:41
void readawaysamples(FILE *input, size_t size)
Definition: utils/frame.c:1069
int parsevolarg(int argcount, char *args[], char *string, double *result)
Definition: utils/frame.c:539
int findoption(int argcount, char *args[], char *s)
Definition: utils/frame.c:900
static void statistics(void)
Definition: utils/frame.c:287
unsigned short channels
Definition: utils/frame.c:30
void fatalerror(const char *format,...)
Definition: utils/frame.c:1010
int parseswitch(char *found, char *wanted)
Definition: utils/frame.c:445
int isoptionchar(char coal)
Definition: utils/frame.c:319
char * usage
Definition: utils/frame.c:37
int chat(const char *format,...)
Definition: utils/frame.c:971
int parsevolume(char *s, double *result)
Definition: utils/frame.c:590
int inform(const char *format,...)
Definition: utils/frame.c:985
void checknoargs(int argcount, char *args[])
Definition: utils/frame.c:717
int workloop(FILE *theinfile, FILE *theoutfile, int(*work)(short *buffer, int length))
Definition: utils/frame.c:943
FILE * in
Definition: utils/frame.c:33
char * infilename
Definition: utils/frame.c:34
int parsedoublearg(int argcount, char *args[], char *string, double *result)
Definition: utils/frame.c:505
char * outfilename
Definition: utils/frame.c:34
int parsefreq(char *string, double *result)
Definition: utils/frame.c:393
unsigned short samplewidth
Definition: utils/frame.c:29
int parseintarg(int argcount, char *args[], char *string, int *result)
Definition: utils/frame.c:471
void readpkheader(FILE *anyin)
Definition: utils/frame.c:76
int parseswitcharg(int argcount, char *args[], char *string)
Definition: utils/frame.c:457
char * parsefilearg(int argcount, char *args[])
Definition: utils/frame.c:419
void parseargs(int argcount, char *args[], int fileswitch)
Definition: utils/frame.c:744
void startstopwatch(void)
Definition: utils/frame.c:307
void makewavheader(void)
Definition: utils/frame.c:219
#define BUFFSIZE
Definition: utils/frame.h:54
#define DEFAULTFREQ
Definition: utils/frame.h:53
Errornum
Definition: utils/frame.h:61
@ ME_THISCANTHAPPEN
Definition: utils/frame.h:76
@ ME_NOSWITCH
Definition: utils/frame.h:66
@ ME_NOIOFILE
Definition: utils/frame.h:71
@ ME_NOSTDOUT
Definition: utils/frame.h:73
@ ME_NOINFILE
Definition: utils/frame.h:69
@ ME_NOVOL
Definition: utils/frame.h:65
@ ME_NOSTDIN
Definition: utils/frame.h:72
@ ME_TOOMANYFILES
Definition: utils/frame.h:67
@ ME_HEADERONTEXTFILE
Definition: utils/frame.h:68
@ ME_NOINT
Definition: utils/frame.h:62
@ ME_NODOUBLE
Definition: utils/frame.h:63
@ ME_NOOUTFILE
Definition: utils/frame.h:70
@ ME_NOSTDIO
Definition: utils/frame.h:74
@ ME_NOTIME
Definition: utils/frame.h:64
@ ME_NOTENOUGHFILES
Definition: utils/frame.h:75