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 if (!fread( &tempint, 4, 1, anyin)) {
87 printf( "%d: %d, ", i, tempint);
90 if (!fread( blood, 1, 8, anyin)) {
93 for (i = 0; i < 8; i++)
94 printf( "%d ", blood[i]);
96 for (i = 0; i < 8; i++)
98 for (x = 128; x > 0; x /= 2)
99 printf((blood[i] & x) == 0? "0 ":"1 ");
100 printf(i%4==3? "\n":"| ");
103 for (i = 0; i < 2; i++)
105 if (!fread( &tempint, 4, 1, anyin)) {
108 printf( "%d: %d, ", i, tempint);
111 for (i = 0; i < 2; i++)
113 if (!fread( &tempushort, 2, 1, anyin)) {
116 printf( "%d: %d, ", i, tempushort);
123 /* -----------------------------------------------------------------------
124 Read a .WAV header from 'anyin'. See header for details.
125 -----------------------------------------------------------------------*/
126 void readwavheader( FILE *anyin)
128 unsigned int tempuint, sf;
129 unsigned short tempushort, cn;
135 if (ftell(anyin) == -1) /* If we cannot seek this file */
137 nowav = TRUE; /* -> Pretend this is no wav-file */
138 chat("File not seekable: not checking for WAV-header.\n");
142 /* Expect four bytes "RIFF" and four bytes filelength */
143 if (!fread(str, 1, 8, anyin)) { /* 0 */
147 if (strcmp(str, "RIFF") != 0) nowav = TRUE;
148 /* Expect eight bytes "WAVEfmt " */
149 if (!fread(str, 1, 8, anyin)) { /* 8 */
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 */
158 if (tempuint != 16) nowav = TRUE;
159 /* Expect format tag, which should be 1 for pcm */
160 if (!fread(&tempushort, 2, 1, anyin)) { /* 20 */
165 /* Expect number of channels */
166 if (!fread(&cn, 2, 1, anyin)) { /* 20 */
169 if (cn != 1 && cn != 2) nowav = TRUE;
170 /* Read samplefrequency */
171 if (!fread(&sf, 4, 1, anyin)) { /* 24 */
174 /* Read bytes per second: Should be samplefreq * channels * 2 */
175 if (!fread(&tempuint, 4, 1, anyin)) { /* 28 */
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 */
183 if (tempushort != cn * 2) nowav = TRUE;
184 /* Read bits per sample: Should be 16 */
185 if (!fread(&tempushort, 2, 1, anyin)) { /* 34 */
188 if (tempushort != 16) nowav = TRUE;
189 if (!fread(str, 4, 1, anyin)) { /* 36 */
193 if (strcmp(str, "data") != 0) nowav = TRUE;
194 if (!fread(&tempuint, 4, 1, anyin)) { /* 40 */
199 fseek(anyin, 0, SEEK_SET); /* Back to beginning of file */
200 chat("File has no WAV header.\n");
204 samplefrequency = sf;
206 chat("Read WAV header: %d channels, samplefrequency %d.\n",
207 channels, samplefrequency);
216 /* -----------------------------------------------------------------------
217 Write a .WAV header to 'out'. See header for details.
218 -----------------------------------------------------------------------*/
219 void makewavheader( void)
221 unsigned int tempuint, filelength;
222 unsigned short tempushort;
224 /* If fseek fails, don't create the header. */
225 if (fseek(out, 0, SEEK_END) != -1)
227 filelength = ftell(out);
228 chat("filelength %d, ", filelength);
229 fseek(out, 0, SEEK_SET);
230 if (!fwrite("RIFF", 1, 4, out)) { /* 0 */
233 tempuint = filelength - 8;
234 if (!fwrite(&tempuint, 4, 1, out)) { /* 4 */
237 if (!fwrite("WAVEfmt ", 1, 8, out)) { /* 8 */
240 /* length of fmt data 16 bytes */
242 if (!fwrite(&tempuint, 4, 1, out)) { /* 16 */
245 /* Format tag: 1 for pcm */
247 if (!fwrite(&tempushort, 2, 1, out)) { /* 20 */
250 chat("%d channels\n", channels);
251 if (!fwrite(&channels, 2, 1, out)) {
254 chat("samplefrequency %d\n", samplefrequency);
255 if (!fwrite(&samplefrequency, 4, 1, out)) { /* 24 */
258 /* Bytes per second */
259 tempuint = channels * samplefrequency * 2;
260 if (!fwrite(&tempuint, 4, 1, out)) { /* 28 */
264 tempushort = 2 * channels;
265 if (!fwrite(&tempushort, 2, 1, out)) { /* 32 */
268 /* Bits per sample */
270 if (!fwrite(&tempushort, 2, 1, out)) { /* 34 */
273 if (!fwrite("data", 4, 1, out)) { /* 36 */
276 tempuint = filelength - 44;
277 if (!fwrite(&tempuint, 4, 1, out)) { /* 40 */
284 /* -----------------------------------------------------------------------
285 After all is read and done, inform the inclined user of the elapsed time
286 -----------------------------------------------------------------------*/
287 static void statistics( void)
291 temp = time(NULL) - stopwatch;
294 inform ("\nTime: %d seconds\n", temp);
298 inform ("\nTime: 1 second\n");
304 /* -----------------------------------------------------------------------
305 Start the stopwatch and make sure the user is informed at end of program.
306 -----------------------------------------------------------------------*/
307 void startstopwatch(void)
309 stopwatch = time(NULL); /* Remember time 'now' */
310 atexit(statistics); /* Call function statistics() at exit. */
315 /* --------------------------------------------------------------------
316 Tests the character 'coal' for being a command line option character,
318 -------------------------------------------------------------------- */
319 int isoptionchar (char coal)
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
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)
336 if ((i = findoption( argcount, args, string)) > 0)
338 if (parsetime(args[i] + 1 + strlen( string), result))
340 argerrornum(args[i]+1, ME_NOTIME);
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
349 On failure, *result is unchanged.
350 return value is TRUE on success, FALSE otherwise.
351 -----------------------------------------------------------------------*/
352 int parsetime(char *string, int *result)
358 k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
361 case 0: case EOF: case 4:
368 *result = temp * samplefrequency;
373 if (m == 'm' && s == 's')
374 *result = temp * samplefrequency / 1000;
375 else if (m == 'H' && s == 'z')
376 *result = samplefrequency / temp;
381 argerrornum(NULL, ME_THISCANTHAPPEN);
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)
399 k = sscanf(string, "%30lf%1c%1c%1c", &temp, &m, &s, &end);
402 case 0: case EOF: case 2: case 4:
408 if (m == 'H' && s == 'z')
409 *result = samplefrequency / temp;
414 argerrornum(NULL, ME_THISCANTHAPPEN);
419 char *parsefilearg( int argcount, char *args[])
424 for (i = 1; i < argcount; i++)
426 if (args[i][0] != '\0' &&
427 (!isoptionchar (args[i][0]) || args[i][1] == '\0' ))
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);
436 fatalperror( "Couldn't allocate memory for filename\n");
437 strcpy( result, args[i]);
438 args[i][0] = '\0'; /* Mark as used up */
445 int parseswitch( char *found, char *wanted)
447 if (strncmp( found, wanted, strlen( wanted)) == 0)
449 if (found[strlen( wanted)] == '\0')
452 argerrornum( found, ME_NOSWITCH);
457 int parseswitcharg( int argcount, char *args[], char *string)
461 if ((i = findoption( argcount, args, string)) > 0)
463 if (args[i][strlen( string) + 1] == '\0')
466 argerrornum( args[i] + 1, ME_NOSWITCH);
471 int parseintarg( int argcount, char *args[], char *string, int *result)
476 if ((i = findoption( argcount, args, string)) > 0)
478 switch (sscanf(args[i] + 1 + strlen( string),
479 "%30d%1c", &temp, &c))
481 case 0: case EOF: case 2:
482 argerrornum(args[i]+1, ME_NOINT);
488 say("frame.c: This can't happen\n");
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
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)
511 if ((i = findoption( argcount, args, string)) > 0)
513 switch (sscanf(args[i] + 1 + strlen( string), "%30lf%1c", &temp, &end))
515 case 0: case EOF: case 2:
516 argerrornum(args[i]+1, ME_NODOUBLE);
522 say("frame.c: This can't happen\n");
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)
543 int i, weird = FALSE;
545 if ((i = findoption( argcount, args, string)) > 0)
547 switch (sscanf(args[i] + 1 + strlen( string),
548 "%30lf%1c%1c%1c", &vol, &sbd, &sbb, &end))
550 case 0: case EOF: case 4:
552 break; /* No number: error */
560 weird = TRUE; /* One char but no percent: error */
563 if (sbd =='d' && sbb == 'b')
564 *result = pow(2, vol / 6.02);
566 weird = TRUE; /* Two chars but not db: error */
569 say("frame.c: This can't happen.\n");
572 argerrornum( args[i] + 1, ME_NOVOL);
573 /* ("Weird option: couldn't parse volume '%s'\n", args[i]+2); */
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)
596 k = sscanf(s, "%30lf%1c%1c%1c", result, &sbd, &sbb, &end);
611 if (sbd !='d' || sbb != 'b')
613 (*result) = pow(2, (*result) / 6.02);
616 say("parsevolume: This can't happen (%d).\n", k);
621 /* --------------------------------------------------------------------
622 Reports an error due to parsing the string 's' encountered on the
624 -------------------------------------------------------------------- */
625 void argerror(char *s)
627 error ("Error parsing command line. Unrecognized option:\n\t-%s\n", s);
628 fatalerror("\nTry --help for help.\n");
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)
639 if (code == ME_TOOMANYFILES)
641 error("Too many files on command line: '%s'.\n", s);
646 error ("Error parsing option -%s:\n\t", s);
650 message = "Integer expected";
653 message = "Floating point number expected";
656 message = "Time argument expected";
659 message = "Volume argument expected";
662 message = "Garbage after switch-type option";
664 case ME_HEADERONTEXTFILE:
665 message = "Option -h is not useful for text-output";
668 message = "No input file specified";
671 message = "No output file specified";
674 message = "No input/output file specified";
677 message = "Standard in not supported here";
680 message = "Standard out not supported here";
683 message = "Standard in/out not supported here";
685 case ME_NOTENOUGHFILES:
686 message = "Not enough files specified";
688 case ME_THISCANTHAPPEN:
689 fatalerror("\nThis can't happen. Report this as a bug\n");
690 /* fatalerror does not return */
692 error("Error code %d not implemented. Fix me!\n", code);
693 message = "Error message not implemented. Fix me!";
695 error("%s\n", message);
697 fatalerror("\nTry --help for help.\n");
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)
707 error ("Error parsing option -%s:\n\t", s);
709 error ("Error parsing command line:\n\t");
710 error ("%s\n", message);
711 fatalerror("\nTry --help for help.\n");
714 /* --------------------------------------------------------------------
715 Check for any remaining arguments and complain about their existence
716 -------------------------------------------------------------------- */
717 void checknoargs( int argcount, char *args[])
719 int i, errorcount = 0;
721 for (i = 1; i < argcount; i++)
723 if (args[i][0] != '\0') /* An unused argument! */
727 error("The following arguments were not recognized:\n");
728 error("\t%s\n", args[i]);
731 if (errorcount > 0) /* Errors are fatal */
732 fatalerror("\nTry --help for help.\n");
734 return; /* No errors? Return. */
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)
749 if ((fileswitch & 1) != 0) /* If getting infile */
751 if ((fileswitch & 4) != 0) /* If getting outfile */
755 samplefrequency = DEFAULTFREQ;
759 /*-----------------------------------------------*
760 * First first check testcase, usage and version *
761 *-----------------------------------------------*/
762 test_usage = parseswitcharg( argcount, args, "-test-usage");
763 if (parseswitcharg( argcount, args, "-help"))
765 printf("%s%s", usage, standardusage);
768 if (parseswitcharg( argcount, args, "-version"))
770 printf("%s\n(%s)\n", version, standardversion);
773 /*--------------------------------------*
775 *--------------------------------------*/
776 while (parseswitcharg( argcount, args, "V"))
778 while (parseswitcharg( argcount, args, "Q"))
780 /*-------------------------------------------------*
781 * Get filenames and open files *
782 *-------------------------------------------------*/
783 if ((fileswitch & 1) != 0) /* Infile wanted */
785 infilename = parsefilearg( argcount, args);
786 if (infilename == NULL)
787 argerrornum( NULL, ME_NOINFILE);
788 if (strcmp( infilename, "-") == 0)
790 infilename = "<stdin>";
792 if ((fileswitch & 2) != 0) /* Binfile wanted */
797 if ((fileswitch & 2) == 0) /* Textfile wanted */
798 in = fopen(infilename, "rt");
799 else /* Binfile wanted */
800 if ((in = fopen(infilename, "rb")) != NULL)
804 fatalerror("Error opening input file '%s': %s\n", infilename,strerror(errno));
806 inform("Using file '%s' as input\n", infilename);
808 if ((fileswitch & 4) != 0) /* Outfile wanted */
810 outfilename = parsefilearg( argcount, args);
811 if (outfilename == NULL)
812 argerrornum( NULL, ME_NOOUTFILE);
813 if (strcmp( outfilename, "-") == 0)
815 outfilename = "<stdout>";
821 if ((fileswitch & 8) == 0) /* Textfile wanted */
822 out = fopen(outfilename, "wt");
823 else /* Binfile wanted */
824 out = fopen(outfilename, "wb");
827 fatalerror("Error opening output file '%s': %s\n", outfilename,strerror(errno));
829 inform("Using file '%s' as output\n", outfilename);
831 if ((fileswitch & 32) != 0) /* In-/Outfile wanted */
833 assert (in == NULL && out == NULL);
834 infilename = outfilename = parsefilearg( argcount, args);
835 if (outfilename == NULL)
836 argerrornum( NULL, ME_NOIOFILE);
837 if (strcmp( infilename, "-") == 0)
838 argerrornum( infilename, ME_NOSTDIN);
839 inform("Using file '%s' as input/output\n", outfilename);
840 in = out = fopen(outfilename, "r+");
842 fatalerror("Error opening input/output file '%s': %s\n", outfilename,strerror(errno));
846 if ((fileswitch & 16) == 0) /* No additional files wanted */
848 if ((filename = parsefilearg( argcount, args)) != NULL)
849 argerrornum( filename, ME_TOOMANYFILES);
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))
860 argerrortxt(NULL, "Option -w is only valid "
861 "with value 16. Sorry.");
863 samplewidth = tempint;
865 if (parseintarg( argcount, args, "c", &tempint))
867 if (tempint != 1 && tempint != 2)
868 argerrortxt(NULL, "Option -c is only valid "
869 "with values 1 or 2. Sorry.");
873 /*-------------------------------------------------*
874 * Create WAV-header on output if wanted. *
875 *-------------------------------------------------*/
877 switch (fileswitch & (12))
879 case 4: /* User wants header on textfile */
880 argerrornum( NULL, ME_HEADERONTEXTFILE);
881 case 12: /* User wants header on binfile */
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. */
888 case 8: /* An application musn't ask for this */
889 default: /* This can't happen */
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)
905 printf("Checking for option -%s\n", s);
907 for (i=1; i<argcount; i++)
909 if (isoptionchar (args[i][0]) &&
910 strncmp( args[i] + 1, s, strlen( s)) == 0)
919 /* --------------------------------------------------------------------
920 Finishes off the .WAV header (if any) and exits correctly and formerly.
921 -------------------------------------------------------------------- */
922 int myexit (int value)
928 makewavheader(); /* Writes a fully informed .WAV header */
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) )
947 int length, nowlength;
950 if ((buffer = malloc( sizeof(short) * length)) == NULL)
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 */
959 /* Call the routine that does the work */
960 if (!work (buffer, nowlength)) /* On error, stop. */
962 if (!fwrite(buffer, sizeof(short), nowlength, theoutfile)) {
965 if (ferror( theoutfile) != 0)
966 fatalperror("Error writing to output file");
968 return TRUE; /* Input file done with, no errors. */
971 int __attribute__((format(printf,1,2))) chat( const char *format, ...)
976 if (verboselevel > 5)
978 va_start( ap, format);
979 result = vfprintf( stderr, format, ap);
985 int __attribute__((format(printf,1,2))) inform( const char *format, ...)
990 if (verboselevel > 1)
992 va_start( ap, format);
993 result = vfprintf( stderr, format, ap);
999 int __attribute__((format(printf,1,2))) error( const char *format, ...)
1004 va_start( ap, format);
1005 result = vfprintf( stderr, format, ap);
1010 void __attribute__((format(printf,1,2))) fatalerror( const char *format, ...)
1014 va_start( ap, format);
1015 vfprintf( stderr, format, ap);
1020 void fatalperror( const char *string)
1026 int __attribute__((format(printf,1,2))) say( const char *format, ...)
1031 va_start( ap, format);
1032 result = vfprintf( stdout, format, ap);
1038 char *malloccopy( char *string)
1042 result = malloc( strlen( string) + 1);
1044 strcpy( result, string);
1049 char *mallocconcat( char *one, char *two)
1053 result = malloc( strlen( one) + strlen( two) + 1);
1056 strcpy( result, one);
1057 strcat( result, two);
1062 double double2db( double value)
1066 return 6.0 * log( value / 32767) / log( 2);
1069 void readawaysamples( FILE *input, size_t size)
1072 int samplesread, count;
1074 buffer = malloc( sizeof( *buffer) * BUFFSIZE);
1075 if (buffer == NULL) fatalperror("Couldn't allocate buffer");
1079 if (size > BUFFSIZE)
1084 samplesread = fread( buffer, sizeof(*buffer), count, input);
1085 if (ferror( input) != 0)
1086 fatalperror("Error reading input file");
1087 size -= samplesread;