view 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 source
/*
  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 ) ;
}