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