Mercurial > hg > aim92
diff tools/bufwave.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/bufwave.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,222 @@ +/* + bufwave.c a shifting waveform buffer. + --------- + + A buffer (or window) is shifted along the input, and the + contents of the buffer are written to the stdout on each shift. + + Input is buffered in frames of size `width' samples, and the buffer is + shifted along the input in steps of `frstep' samples. + Both `width' and `frstep' may be given with time units (s or ms), in which + case the they are converted to a number of samples using the given + `samplerate' option. + + The `type' option sets the size of a binary sample in bytes. + Standard type names are recognised (char, short, int, float, double). + For example, type=1 is synonymous with type=char, both specifying a + binary sample of 1 byte. + + The special case of type=ASCII sets a sample to be a line of ASCII text + (delimited by a CR), of size up to a maximum number of characters set by + the `length' option. + + The `frame' option selects a sequence of contiguous frames for output by: + frame=a[-b] + where `a' and `b' are frame numbers: 1,2,3,... + The upper limit `b' is optional, and when it is missing then the frame + sequence is a single frame, otherwise `a' and `b' are inclusive limits. + The strings "min" and "max" are recognised as extreme limits. + + The `start' option is an offset to the start of the first frame in samples. + If given with time units, the start is converted to samples using the + given `samplerate' option. + + The `reverse' option causes each buffer to be written out in reverse order + of its samples. + + For example, if a file foo contains a sequence of frames, each 75 samples + long, then to reverse the contents of each frame do: + + bufwave rev=on width=75 frstep=75 foo + +*/ + +#include <stdio.h> +#include <math.h> +#include "options.h" +#include "units.h" +#include "strmatch.h" + +char applic[] = "shifting waveform buffer." ; + +static char *helpstr, *debugstr, *fstr, *bstr, *nstr, *ostr, *sstr, *sampstr, *rstr, *lenstr ; + +static Options option[] = { + { "help" , "off" , &helpstr , "help" , DEBUG }, + { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, + { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, + { "frame" , "1-max" , &fstr , "select frames inclusively" , VAL }, + { "width" , "10ms" , &nstr , "frame width" , VAL }, + { "frstep" , "0" , &ostr , "frame step (ie. shift)" , VAL }, + { "start" , "0" , &sstr , "offset to start first frame" , VAL }, + { "type" , "short" , &bstr , "data type or size in bytes" , VAL }, + { "reverse" , "off" , &rstr , "write each frame in reverse" , SETFLAG }, + { "length" , "256" , &lenstr , "max line length in chars" , SVAL }, + ( char * ) 0 } ; + + +int samplerate ; +int width ; +int frstep ; +int overlap ; +int start ; +int reverse ; + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp ; + char *buf, **linebuf ; + int m, bytes ; + int a, b, f, i, j, k0, k1 ; + int helpdatatype() ; + + fp = openopts( option,argc,argv ) ; + if ( !isoff( helpstr ) ) + helpopts1( helpstr, argv[0], applic, option, helpdatatype ) ; + + samplerate = to_Hz( sampstr ) ; + width = to_p( nstr, samplerate ) ; + frstep = to_p( ostr, samplerate ) ; + start = to_p( sstr, samplerate ) ; + reverse = ison( rstr ) ; + overlap = width - frstep ; + + if ( ( bytes = databytes( bstr ) ) < 0 ) { + fprintf( stderr, "bufwave: bad type [%s]\n", bstr ) ; + exit( 1 ) ; + } + + if ( selector( fstr, &a, &b ) == 0 ) { + fprintf(stderr,"bufwave: bad frame selector [%s]\n", fstr ) ; + exit( 1 ) ; + } + + if ( ison( debugstr ) ) { + printf("width=%d frstep=%d start=%d bytes=%d samplerate=%d reverse=%d a=%d b=%d \n", + width, frstep, start, bytes, samplerate, reverse, a, b ); + exit(0); + } + + + if (bytes > 0) { /* binary objects of size `bytes' */ + + /* Allocate space for frame buffer */ + if ( ( buf = (char *)malloc( width*bytes ) ) == (char *)0 ) { + fprintf( stderr, "bufwave: cannot allocate %d * %d bytes\n", width, bytes ) ; + exit( 1 ) ; + } + + /* Seek to start, past start*bytes and a-1 frame shifts of frstep*bytes */ + + if ( start>0 && seekstart( start, bytes, fp ) < start ) { + fprintf(stderr,"bufwave: seek overshot end-of-file\n"); + exit(1); + } + for (f=1 ; f<a && fread(buf,bytes,frstep,fp) ; f++) + ; + + /* Buffer b-a+1 frames (or the remainder if b==0) */ + m = fread(buf, bytes, width, fp); /* m enables oversizing single frames for direct reversing */ + if ( reverse ) + for (k0=m-1 ; k0>=0 && fwrite(&buf[(k0)*bytes], bytes, 1, stdout) ; --k0) + ; + else + fwrite(buf, bytes, m, stdout); + + k0 = k1 = 0; + for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) { + for (k0=i, k1=i+frstep ; k0<k1 && fread(&buf[(k0%width)*bytes], bytes, 1, fp) ; k0++) + ; + i -= overlap ; + if (k0 == k1) { + if ( reverse ) /* write out in reverse */ + for (k0=i+width-1, k1=i-1 ; k0>k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; --k0) + ; + else /* write out correct order */ + for (k0=i, k1=i+width ; k0<k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; k0++) + ; + } + } + } + + else { /* ASCII objects of size lines up to lenstr chars */ + + /* Allocate space for `width' lines */ + bytes = atoi( lenstr ) ; + if ( ( linebuf = (char **)malloc( width * sizeof( char * ) ) ) == (char **)0 ) { + fprintf( stderr, "bufwave: cannot allocate %d * sizeof( char * )\n", width ) ; + exit( 1 ) ; + } + for ( i = 0 ; i < width ; i++) + if ( ( linebuf[i] = (char *)malloc( bytes ) ) == (char *)0 ) { + fprintf( stderr, "bufwave: cannot allocate %d bytes %d times\n", bytes, i+1 ) ; + exit( 1 ) ; + } + + /* Seek to start, past start*bytes and frstep*a-1 lines */ + for (i=0 ; i<start && fgets( *linebuf, bytes, fp ) ; i++) + ; + if (i<start) { + fprintf(stderr,"bufwave: seek overshot end-of-file\n"); + exit(1); + } + m = frstep * ( a-1 ) ; + for (i=0 ; i<m && fgets( *linebuf, bytes, fp ) ; i++) + ; + if ( m > 0 ) f = m/frstep + 1 ; + else f = 1 ; + + /* Buffer b-a+1 lines (or the remainder if b==0) */ + /* (m enables oversizing single frames for direct reversing) */ + for ( m = 0 ; m < width && fgets( linebuf[m], bytes, fp ) ; m++ ) + ; + if ( reverse ) + for (k0=m-1 ; k0>=0 ; --k0) + fputs( linebuf[k0], stdout ) ; + else + for (k0=0 ; k0<m ; k0++) + fputs( linebuf[k0], stdout ) ; + + k0 = k1 = 0; + for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) { + for (k0=i, k1=i+frstep ; k0<k1 && fgets( linebuf[k0%width], bytes, fp ) ; k0++) + ; + i -= overlap ; + if (k0 == k1) { + if ( reverse ) /* write out in reverse */ + for (k0=i+width-1, k1=i-1 ; k0>k1 ; --k0) + fputs( linebuf[k0%width], stdout ) ; + else /* write out correct order */ + for (k0=i, k1=i+width ; k0<k1 ; k0++) + fputs( linebuf[k0%width], stdout) ; + } + } + } + +} + + +helpdatatype() +{ + fprintf(stderr,"\ndata types: \n"); + fprintf(stderr," char \n"); + fprintf(stderr," short \n"); + fprintf(stderr," int \n"); + fprintf(stderr," float \n"); + fprintf(stderr," double \n"); + fprintf(stderr," <number> (sizeof binary object in bytes) \n" ) ; + fprintf(stderr," ASCII (lines of up to %d characters) \n", atoi( lenstr ) ) ; + exit( 1 ) ; +}