1 /****************************************************************************
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.
8 * Version: see static char *standardversion, below.
9 * Author: Mark Roberts <mark@manumark.de>
10 * Michael Labuschke <michael@labuschke.de> sys_errlist fixes
12 ****************************************************************************/
13 /****************************************************************************
14 * These are useful functions that all DSP programs might find handy
15 ****************************************************************************/
19 #include <stdlib.h> /* for exit and malloc */
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 */
34 char *infilename
, *outfilename
;
38 static int test_usage
;
40 static char *standardversion
= "frame version 1.3, June 13th 2001";
41 static char *standardusage
=
42 "\nOptions common to all mark-dsp programs:\n"
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"
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
)
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
;
68 (*result
) /= samplewidth
;
69 if (fseek (anyin
, i
, SEEK_SET
) == -1) return FALSE
;
73 /* -----------------------------------------------------------------------
74 Read a .pk-header from 'anyin'.
75 -----------------------------------------------------------------------*/
76 void readpkheader( FILE *anyin
)
78 unsigned short tempushort
;
80 unsigned char blood
[8];
82 for (i
= 0; i
< 11; i
++)
84 fread( &tempint
, 4, 1, anyin
);
85 printf( "%d: %d, ", i
, tempint
);
88 fread( blood
, 1, 8, anyin
);
89 for (i
= 0; i
< 8; i
++)
90 printf( "%d ", blood
[i
]);
92 for (i
= 0; i
< 8; i
++)
94 for (x
= 128; x
> 0; x
/= 2)
95 printf((blood
[i
] & x
) == 0? "0 ":"1 ");
96 printf(i
%4==3? "\n":"| ");
99 for (i
= 0; i
< 2; i
++)
101 fread( &tempint
, 4, 1, anyin
);
102 printf( "%d: %d, ", i
, tempint
);
105 for (i
= 0; i
< 2; i
++)
107 fread( &tempushort
, 2, 1, anyin
);
108 printf( "%d: %d, ", i
, tempushort
);
115 /* -----------------------------------------------------------------------
116 Read a .WAV header from 'anyin'. See header for details.
117 -----------------------------------------------------------------------*/
118 void readwavheader( FILE *anyin
)
120 unsigned int tempuint
, sf
;
121 unsigned short tempushort
, cn
;
127 if (ftell(anyin
) == -1) /* If we cannot seek this file */
129 nowav
= TRUE
; /* -> Pretend this is no wav-file */
130 chat("File not seekable: not checking for WAV-header.\n");
134 /* Expect four bytes "RIFF" and four bytes filelength */
135 fread (str
, 1, 8, anyin
); /* 0 */
137 if (strcmp(str
, "RIFF") != 0) nowav
= TRUE
;
138 /* Expect eight bytes "WAVEfmt " */
139 fread (str
, 1, 8, anyin
); /* 8 */
141 if (strcmp(str
, "WAVEfmt ") != 0) nowav
= TRUE
;
142 /* Expect length of fmt data, which should be 16 */
143 fread (&tempuint
, 4, 1, anyin
); /* 16 */
144 if (tempuint
!= 16) nowav
= TRUE
;
145 /* Expect format tag, which should be 1 for pcm */
146 fread (&tempushort
, 2, 1, anyin
); /* 20 */
149 /* Expect number of channels */
150 fread (&cn
, 2, 1, anyin
); /* 20 */
151 if (cn
!= 1 && cn
!= 2) nowav
= TRUE
;
152 /* Read samplefrequency */
153 fread (&sf
, 4, 1, anyin
); /* 24 */
154 /* Read bytes per second: Should be samplefreq * channels * 2 */
155 fread (&tempuint
, 4, 1, anyin
); /* 28 */
156 if (tempuint
!= sf
* cn
* 2) nowav
= TRUE
;
157 /* read bytes per frame: Should be channels * 2 */
158 fread (&tempushort
, 2, 1, anyin
); /* 32 */
159 if (tempushort
!= cn
* 2) nowav
= TRUE
;
160 /* Read bits per sample: Should be 16 */
161 fread (&tempushort
, 2, 1, anyin
); /* 34 */
162 if (tempushort
!= 16) nowav
= TRUE
;
163 fread (str
, 4, 1, anyin
); /* 36 */
165 if (strcmp(str
, "data") != 0) nowav
= TRUE
;
166 fread (&tempuint
, 4, 1, anyin
); /* 40 */
169 fseek (anyin
, 0, SEEK_SET
); /* Back to beginning of file */
170 chat("File has no WAV header.\n");
174 samplefrequency
= sf
;
176 chat ("Read WAV header: %d channels, samplefrequency %d.\n",
177 channels
, samplefrequency
);
186 /* -----------------------------------------------------------------------
187 Write a .WAV header to 'out'. See header for details.
188 -----------------------------------------------------------------------*/
189 void makewavheader( void)
191 unsigned int tempuint
, filelength
;
192 unsigned short tempushort
;
194 /* If fseek fails, don't create the header. */
195 if (fseek (out
, 0, SEEK_END
) != -1)
197 filelength
= ftell (out
);
198 chat ("filelength %d, ", filelength
);
199 fseek (out
, 0, SEEK_SET
);
200 fwrite ("RIFF", 1, 4, out
); /* 0 */
201 tempuint
= filelength
- 8; fwrite (&tempuint
, 4, 1, out
); /* 4 */
202 fwrite ("WAVEfmt ", 1, 8, out
); /* 8 */
203 /* length of fmt data 16 bytes */
205 fwrite (&tempuint
, 4, 1, out
); /* 16 */
206 /* Format tag: 1 for pcm */
208 fwrite (&tempushort
, 2, 1, out
); /* 20 */
209 chat ("%d channels\n", channels
);
210 fwrite (&channels
, 2, 1, out
);
211 chat ("samplefrequency %d\n", samplefrequency
);
212 fwrite (&samplefrequency
, 4, 1, out
); /* 24 */
213 /* Bytes per second */
214 tempuint
= channels
* samplefrequency
* 2;
215 fwrite (&tempuint
, 4, 1, out
); /* 28 */
217 tempushort
= 2 * channels
;
218 fwrite (&tempushort
, 2, 1, out
); /* 32 */
219 /* Bits per sample */
221 fwrite (&tempushort
, 2, 1, out
); /* 34 */
222 fwrite ("data", 4, 1, out
); /* 36 */
223 tempuint
= filelength
- 44; fwrite (&tempuint
, 4, 1, out
); /* 40 */
228 /* -----------------------------------------------------------------------
229 After all is read and done, inform the inclined user of the elapsed time
230 -----------------------------------------------------------------------*/
231 static void statistics( void)
235 temp
= time(NULL
) - stopwatch
;
238 inform ("\nTime: %d seconds\n", temp
);
242 inform ("\nTime: 1 second\n");
248 /* -----------------------------------------------------------------------
249 Start the stopwatch and make sure the user is informed at end of program.
250 -----------------------------------------------------------------------*/
251 void startstopwatch(void)
253 stopwatch
= time(NULL
); /* Remember time 'now' */
254 atexit(statistics
); /* Call function statistics() at exit. */
259 /* --------------------------------------------------------------------
260 Tests the character 'coal' for being a command line option character,
262 -------------------------------------------------------------------- */
263 int isoptionchar (char coal
)
268 /* -----------------------------------------------------------------------
269 Reads through the arguments on the lookout for an option starting
270 with 'string'. The rest of the option is read as a time and passed
271 to *result, where the result is meant to mean 'number of samples' in
273 On failure, *result is unchanged.
274 return value is TRUE on success, FALSE otherwise.
275 -----------------------------------------------------------------------*/
276 int parsetimearg( int argcount
, char *args
[], char *string
, int *result
)
280 if ((i
= findoption( argcount
, args
, string
)) > 0)
282 if (parsetime(args
[i
] + 1 + strlen( string
), result
))
284 argerrornum(args
[i
]+1, ME_NOTIME
);
289 /* -----------------------------------------------------------------------
290 The string argument is read as a time and passed
291 to *result, where the result is meant to mean 'number of samples' in
293 On failure, *result is unchanged.
294 return value is TRUE on success, FALSE otherwise.
295 -----------------------------------------------------------------------*/
296 int parsetime(char *string
, int *result
)
302 k
= sscanf(string
, "%lf%c%c%c", &temp
, &m
, &s
, &end
);
305 case 0: case EOF
: case 4:
312 *result
= temp
* samplefrequency
;
317 if (m
== 'm' && s
== 's')
318 *result
= temp
* samplefrequency
/ 1000;
319 else if (m
== 'H' && s
== 'z')
320 *result
= samplefrequency
/ temp
;
325 argerrornum(NULL
, ME_THISCANTHAPPEN
);
330 /* -----------------------------------------------------------------------
331 The string argument is read as a frequency and passed
332 to *result, where the result is meant to mean 'number of samples' in
333 one cycle of that frequency.
334 On failure, *result is unchanged.
335 return value is TRUE on success, FALSE otherwise.
336 -----------------------------------------------------------------------*/
337 int parsefreq(char *string
, double *result
)
343 k
= sscanf(string
, "%lf%c%c%c", &temp
, &m
, &s
, &end
);
346 case 0: case EOF
: case 2: case 4:
352 if (m
== 'H' && s
== 'z')
353 *result
= samplefrequency
/ temp
;
358 argerrornum(NULL
, ME_THISCANTHAPPEN
);
363 char *parsefilearg( int argcount
, char *args
[])
368 for (i
= 1; i
< argcount
; i
++)
370 if (args
[i
][0] != '\0' &&
371 (!isoptionchar (args
[i
][0]) || args
[i
][1] == '\0' ))
373 /*---------------------------------------------*
374 * The argument is a filename: *
375 * it is either no dash followed by something, *
376 * or it is a dash following by nothing. *
377 *---------------------------------------------*/
378 result
= malloc( strlen( args
[i
]) + 1);
380 fatalperror( "Couldn't allocate memory for filename\n");
381 strcpy( result
, args
[i
]);
382 args
[i
][0] = '\0'; /* Mark as used up */
389 int parseswitch( char *found
, char *wanted
)
391 if (strncmp( found
, wanted
, strlen( wanted
)) == 0)
393 if (found
[strlen( wanted
)] == '\0')
396 argerrornum( found
, ME_NOSWITCH
);
401 int parseswitcharg( int argcount
, char *args
[], char *string
)
405 if ((i
= findoption( argcount
, args
, string
)) > 0)
407 if (args
[i
][strlen( string
) + 1] == '\0')
410 argerrornum( args
[i
] + 1, ME_NOSWITCH
);
415 int parseintarg( int argcount
, char *args
[], char *string
, int *result
)
420 if ((i
= findoption( argcount
, args
, string
)) > 0)
422 switch (sscanf(args
[i
] + 1 + strlen( string
),
425 case 0: case EOF
: case 2:
426 argerrornum(args
[i
]+1, ME_NOINT
);
432 say("frame.c: This can't happen\n");
442 /* --------------------------------------------------------------------
443 Reads through the arguments on the lookout for an option starting
444 with 'string'. The rest of the option is read as a double and
446 On failure, *result is unchanged.
447 return value is TRUE on success, FALSE otherwise.
448 -------------------------------------------------------------------- */
449 int parsedoublearg( int argcount
, char *args
[], char *string
, double *result
)
455 if ((i
= findoption( argcount
, args
, string
)) > 0)
457 switch (sscanf(args
[i
] + 1 + strlen( string
), "%lf%c", &temp
, &end
))
459 case 0: case EOF
: case 2:
460 argerrornum(args
[i
]+1, ME_NODOUBLE
);
466 say("frame.c: This can't happen\n");
476 /* --------------------------------------------------------------------
477 Reads through the arguments on the lookout for an option starting
478 with 'string'. The rest of the option is read as a volume, i.e.
479 absolute, percent or db. The result is passed to *result.
480 On failure, *result is unchanged.
481 return value is TRUE on success, FALSE otherwise.
482 -------------------------------------------------------------------- */
483 int parsevolarg( int argcount
, char *args
[], char *string
, double *result
)
487 int i
, weird
= FALSE
;
489 if ((i
= findoption( argcount
, args
, string
)) > 0)
491 switch (sscanf(args
[i
] + 1 + strlen( string
),
492 "%lf%c%c%c", &vol
, &sbd
, &sbb
, &end
))
494 case 0: case EOF
: case 4:
496 break; /* No number: error */
504 weird
= TRUE
; /* One char but no percent: error */
507 if (sbd
=='d' && sbb
== 'b')
508 *result
= pow(2, vol
/ 6.02);
510 weird
= TRUE
; /* Two chars but not db: error */
513 say("frame.c: This can't happen.\n");
516 argerrornum( args
[i
] + 1, ME_NOVOL
);
517 /* ("Weird option: couldn't parse volume '%s'\n", args[i]+2); */
527 /* --------------------------------------------------------------------
528 Reads the specified string 's' and interprets it as a volume. The string
529 would be of the form 1.8 or 180% or 5db.
530 On success, the return value TRUE and *result is given result
531 (i.e. the relative volume, i.e. 1.8). On failure, FALSE is returned and
532 result is given value 1.0.
533 -------------------------------------------------------------------- */
534 int parsevolume(char *s
, double *result
)
540 k
= sscanf(s
, "%lf%c%c%c", result
, &sbd
, &sbb
, &end
);
555 if (sbd
!='d' || sbb
!= 'b')
557 (*result
) = pow(2, (*result
) / 6.02);
560 say("parsevolume: This can't happen (%d).\n", k
);
565 /* --------------------------------------------------------------------
566 Reports an error due to parsing the string 's' encountered on the
568 -------------------------------------------------------------------- */
569 void argerror(char *s
)
571 error ("Error parsing command line. Unrecognized option:\n\t-%s\n", s
);
572 fatalerror("\nTry --help for help.\n");
575 /* --------------------------------------------------------------------
576 Reports an error due to parsing the string 's' encountered on the
577 command line. 'code' indicates the type of error.
578 -------------------------------------------------------------------- */
579 void argerrornum(char *s
, Errornum code
)
583 if (code
== ME_TOOMANYFILES
)
585 error("Too many files on command line: '%s'.\n", s
);
590 error ("Error parsing option -%s:\n\t", s
);
594 message
= "Integer expected";
597 message
= "Floating point number expected";
600 message
= "Time argument expected";
603 message
= "Volume argument expected";
606 message
= "Garbage after switch-type option";
608 case ME_HEADERONTEXTFILE
:
609 message
= "Option -h is not useful for text-output";
612 message
= "No input file specified";
615 message
= "No output file specified";
618 message
= "No input/output file specified";
621 message
= "Standard in not supported here";
624 message
= "Standard out not supported here";
627 message
= "Standard in/out not supported here";
629 case ME_NOTENOUGHFILES
:
630 message
= "Not enough files specified";
632 case ME_THISCANTHAPPEN
:
633 fatalerror("\nThis can't happen. Report this as a bug\n");
634 /* fatalerror does not return */
636 error("Error code %d not implemented. Fix me!\n", code
);
637 message
= "Error message not implemented. Fix me!";
639 error("%s\n", message
);
641 fatalerror("\nTry --help for help.\n");
644 /* --------------------------------------------------------------------
645 Reports an error due to parsing the string 's' encountered on the
646 command line. 'message' explains the type of error.
647 -------------------------------------------------------------------- */
648 void argerrortxt(char *s
, char *message
)
651 error ("Error parsing option -%s:\n\t", s
);
653 error ("Error parsing command line:\n\t");
654 error ("%s\n", message
);
655 fatalerror("\nTry --help for help.\n");
658 /* --------------------------------------------------------------------
659 Check for any remaining arguments and complain about their existence
660 -------------------------------------------------------------------- */
661 void checknoargs( int argcount
, char *args
[])
663 int i
, errorcount
= 0;
665 for (i
= 1; i
< argcount
; i
++)
667 if (args
[i
][0] != '\0') /* An unused argument! */
671 error("The following arguments were not recognized:\n");
672 error("\t%s\n", args
[i
]);
675 if (errorcount
> 0) /* Errors are fatal */
676 fatalerror("\nTry --help for help.\n");
678 return; /* No errors? Return. */
681 /* --------------------------------------------------------------------
682 Parses the command line arguments as represented by the function
683 arguments. Sets the global variables 'in', 'out', 'samplefrequency'
684 and 'samplewidth' accordingly. Also verboselevel.
685 The files 'in' and 'out' are even opened according to 'fileswitch'.
686 See headerfile for details
687 -------------------------------------------------------------------- */
688 void parseargs( int argcount
, char *args
[], int fileswitch
)
693 if ((fileswitch
& 1) != 0) /* If getting infile */
695 if ((fileswitch
& 4) != 0) /* If getting outfile */
699 samplefrequency
= DEFAULTFREQ
;
703 /*-----------------------------------------------*
704 * First first check testcase, usage and version *
705 *-----------------------------------------------*/
706 test_usage
= parseswitcharg( argcount
, args
, "-test-usage");
707 if (parseswitcharg( argcount
, args
, "-help"))
709 printf("%s%s", usage
, standardusage
);
712 if (parseswitcharg( argcount
, args
, "-version"))
714 printf("%s\n(%s)\n", version
, standardversion
);
717 /*--------------------------------------*
719 *--------------------------------------*/
720 while (parseswitcharg( argcount
, args
, "V"))
722 while (parseswitcharg( argcount
, args
, "Q"))
724 /*-------------------------------------------------*
725 * Get filenames and open files *
726 *-------------------------------------------------*/
727 if ((fileswitch
& 1) != 0) /* Infile wanted */
729 infilename
= parsefilearg( argcount
, args
);
730 if (infilename
== NULL
)
731 argerrornum( NULL
, ME_NOINFILE
);
732 if (strcmp( infilename
, "-") == 0)
734 infilename
= "<stdin>";
736 if ((fileswitch
& 2) != 0) /* Binfile wanted */
741 if ((fileswitch
& 2) == 0) /* Textfile wanted */
742 in
= fopen(infilename
, "rt");
743 else /* Binfile wanted */
744 if ((in
= fopen(infilename
, "rb")) != NULL
)
748 fatalerror("Error opening input file '%s': %s\n", infilename
,strerror(errno
));
750 inform("Using file '%s' as input\n", infilename
);
752 if ((fileswitch
& 4) != 0) /* Outfile wanted */
754 outfilename
= parsefilearg( argcount
, args
);
755 if (outfilename
== NULL
)
756 argerrornum( NULL
, ME_NOOUTFILE
);
757 if (strcmp( outfilename
, "-") == 0)
759 outfilename
= "<stdout>";
765 if ((fileswitch
& 8) == 0) /* Textfile wanted */
766 out
= fopen(outfilename
, "wt");
767 else /* Binfile wanted */
768 out
= fopen(outfilename
, "wb");
771 fatalerror("Error opening output file '%s': %s\n", outfilename
,strerror(errno
));
773 inform("Using file '%s' as output\n", outfilename
);
775 if ((fileswitch
& 32) != 0) /* In-/Outfile wanted */
777 assert (in
== NULL
&& out
== NULL
);
778 infilename
= outfilename
= parsefilearg( argcount
, args
);
779 if (outfilename
== NULL
)
780 argerrornum( NULL
, ME_NOIOFILE
);
781 if (strcmp( infilename
, "-") == 0)
782 argerrornum( infilename
, ME_NOSTDIN
);
783 inform("Using file '%s' as input/output\n", outfilename
);
784 in
= out
= fopen(outfilename
, "r+");
786 fatalerror("Error opening input/output file '%s': %s\n", outfilename
,strerror(errno
));
790 if ((fileswitch
& 16) == 0) /* No additional files wanted */
792 if ((filename
= parsefilearg( argcount
, args
)) != NULL
)
793 argerrornum( filename
, ME_TOOMANYFILES
);
796 /*-------------------------------------------------*
797 * Set samplefrequency, width, wavout,
798 *-------------------------------------------------*/
799 parseintarg( argcount
, args
, "f", &samplefrequency
);
800 wavout
= parseswitcharg( argcount
, args
, "h");
801 if (parseintarg( argcount
, args
, "w", &tempint
))
804 argerrortxt(NULL
, "Option -w is only valid "
805 "with value 16. Sorry.");
807 samplewidth
= tempint
;
809 if (parseintarg( argcount
, args
, "c", &tempint
))
811 if (tempint
!= 1 && tempint
!= 2)
812 argerrortxt(NULL
, "Option -c is only valid "
813 "with values 1 or 2. Sorry.");
817 /*-------------------------------------------------*
818 * Create WAV-header on output if wanted. *
819 *-------------------------------------------------*/
821 switch (fileswitch
& (12))
823 case 4: /* User wants header on textfile */
824 argerrornum( NULL
, ME_HEADERONTEXTFILE
);
825 case 12: /* User wants header on binfile */
828 case 0: /* User wants header, but there is no outfile */
829 /* Problem: what about i/o-file, 32? You might want a header
830 on that? Better ignore this case. */
832 case 8: /* An application musn't ask for this */
833 default: /* This can't happen */
839 /* --------------------------------------------------------------------
840 Returns the index 'i' of the first argument that IS an option, and
841 which begins with the label 's'. If there is none, -1.
842 We also mark that option as done with, i.e. we cross it out.
843 -------------------------------------------------------------------- */
844 int findoption( int argcount
, char *args
[], char *s
)
849 printf("Checking for option -%s\n", s
);
851 for (i
=1; i
<argcount
; i
++)
853 if (isoptionchar (args
[i
][0]) &&
854 strncmp( args
[i
] + 1, s
, strlen( s
)) == 0)
863 /* --------------------------------------------------------------------
864 Finishes off the .WAV header (if any) and exits correctly and formerly.
865 -------------------------------------------------------------------- */
866 int myexit (int value
)
872 makewavheader(); /* Writes a fully informed .WAV header */
882 /* --------------------------------------------------------------------
883 Reads the stated input file bufferwise, calls the function 'work'
884 with the proper values, and writes the result to the stated output file.
885 Return value: TRUE on success, FALSE otherwise.
886 -------------------------------------------------------------------- */
887 int workloop( FILE *theinfile
, FILE *theoutfile
,
888 int (*work
)( short *buffer
, int length
) )
891 int length
, nowlength
;
894 if ((buffer
= malloc( sizeof(short) * length
)) == NULL
)
898 nowlength
= fread(buffer
, sizeof(short), length
, theinfile
);
899 if (ferror( theinfile
) != 0)
900 fatalperror("Error reading input file");
901 if (nowlength
== 0) /* Reached end of input file */
903 /* Call the routine that does the work */
904 if (!work (buffer
, nowlength
)) /* On error, stop. */
906 fwrite(buffer
, sizeof(short), nowlength
, theoutfile
);
907 if (ferror( theoutfile
) != 0)
908 fatalperror("Error writing to output file");
910 return TRUE
; /* Input file done with, no errors. */
913 int chat( const char *format
, ...)
918 if (verboselevel
> 5)
920 va_start( ap
, format
);
921 result
= vfprintf( stderr
, format
, ap
);
928 int inform( const char *format
, ...)
933 if (verboselevel
> 1)
935 va_start( ap
, format
);
936 result
= vfprintf( stderr
, format
, ap
);
942 int error( const char *format
, ...)
947 va_start( ap
, format
);
948 result
= vfprintf( stderr
, format
, ap
);
953 void fatalerror( const char *format
, ...)
957 va_start( ap
, format
);
958 vfprintf( stderr
, format
, ap
);
963 void fatalperror( const char *string
)
969 int say( const char *format
, ...)
974 va_start( ap
, format
);
975 result
= vfprintf( stdout
, format
, ap
);
981 char *malloccopy( char *string
)
985 result
= malloc( strlen( string
) + 1);
987 strcpy( result
, string
);
992 char *mallocconcat( char *one
, char *two
)
996 result
= malloc( strlen( one
) + strlen( two
) + 1);
999 strcpy( result
, one
);
1000 strcat( result
, two
);
1005 double double2db( double value
)
1009 return 6.0 * log( value
/ 32767) / log( 2);
1012 void readawaysamples( FILE *in
, size_t size
)
1015 int samplesread
, count
;
1017 buffer
= malloc( sizeof( *buffer
) * BUFFSIZE
);
1018 if (buffer
== NULL
) fatalperror("Couldn't allocate buffer");
1022 if (size
> BUFFSIZE
)
1027 samplesread
= fread( buffer
, sizeof(*buffer
), count
, in
);
1028 if (ferror( in
) != 0)
1029 fatalperror("Error reading input file");
1030 size
-= samplesread
;