view tools/naptosai.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
/*
  naptosai.c            NAP to SAI format conversion.
 ------------

    Read a NAP header and frame.
    Write a SAI header, (created from the NAP header).
    Write a succession of SAI frames.

    The options "start" and "length" specify the NAP which is input.
    The options "width" and "frstep"  specify the SAI frames which are output.

    Special option values are:

      length=max      Input all the NAP from the given start to its end.
      width=max       Output framewidth is set equal to the given NAP length,
		      and if this is also "max", then the framewidth is the
		      remainder of the NAP.
      frstep=0        Output one frame of given width from the given start of
		      the NAP.

    For example, use naptosai with width=max and frstep=0 to produce one SAI
    frame the same size as the input NAP.

Examples:


1. To convert a nap or a bmm output to a single frame of sai output:

gennap length=64 output=stdout file | naptosai width=32 frstep=0 > file.sai
gensai top=1000 useprevious=on file

genbmm output=stdout file | naptosai  > file.sai
gensai bottom=-100 useprevious=on file

  This uses special case of zero frstep to generate one frame of output with
  the given width. The default width is the given length, and the default
  length is the remainder of the input file. If the width=length, then the
  frstep is zero by default, and therefore the default process, (ie with no
  arguments), converts the whole of the input to a single SAI frame.

  Note, certain display parameters have different default values for different
  applications. The SAI display parameters should be set to the appropriate
  values, in order to plot the SAI on the same scale. For example:
    When the source application is NAP, set gensai top=1000
    When the source application is BMM, set gensai bottom=-100


2. To convert a nap output to multiple frames of sai output:

gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai
gensai top=1000 useprevious=on file

   The sai output can be plotted as a spiral, but it is best to set the
   display parameters as follows:

gennap length=40 output=stdout dencf=1 width=500 height=500 file | \
				naptosai width=32 frstep=0.2 > file.sai
genspl useprevious=on pensize=2 file


3. To convert a nap output to a sai format bitmap, to display an animated
   stream:

gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai
gensai top=1000 useprevious=on bitmap=on file
review file

  The same can be done for the spiral display:

gennap length=40 output=stdout dencf=1 width=500 height=500 file | \
				naptosai width=32 frstep=0.2 > file.sai
genspl useprevious=on pensize=2 bitmap=on file
review file

  The plots show the nap moving though 8ms (40-32), in steps of 0.2ms,
  first in rectangular display, then in spiral-mapped display.

*/


#include <stdio.h>
#include <math.h>
#include "header.h"
#include "options.h"
#include "units.h"
#include "strmatch.h"

char applic[]     = "NAP to SAI format conversion. " ;

static char *helpstr, *debugstr, *startstr, *lengthstr, *widthstr, *shiftstr, *headerstr ;

static Options option[] = {
    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p NAP"        , VAL     },
    {   "length"    ,   "max"       ,  &lengthstr   ,   "Length of i/p NAP to process." , VAL     },
    {   "header"    ,   "on"        ,  &headerstr   ,   "sai header"                    , VAL     },
    {   "width"     ,   "max"       ,  &widthstr    ,   "Width of o/p SAI frame."       , VAL     },
    {   "frstep"    ,   "1ms"       ,  &shiftstr    ,   "Step between o/p frames of SAI.\n(frstep=0 gets 1 frame of given width)." , VAL },
   ( char * ) 0 } ;


int     frameheight, framewidth ;       /* Nap parameters read from header */
int     frames, samplerate ;

int     start, length ;

int     Newframeheight, Newframewidth ; /* Sai parameters to write  */
int     Newframes ;
int     Newframeshift ;
int     Newframebytes ;


main(argc, argv)
int   argc ;
char *argv[] ;
{
    FILE   *fp ;
    int     i, framebytes, startbytes, frameshift;
    char   *header, *SaiHeader();
    short  *nap, *frame, *endframe;

    fp = openopts( option,argc,argv ) ;
    if ( !isoff( helpstr ) )
	helpopts( helpstr, argv[0], applic, option ) ;

    if ( ison( debugstr ) ) {
	printf("start=%s length=%s width=%s shift=%s\n",
		startstr, lengthstr, widthstr, shiftstr );
	exit(0);
    }

    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
	fprintf(stderr,"naptosai: header not found\n");
	exit(1);
    }

    frameheight = HeaderInt( header, "frameheight" );
    framewidth =  HeaderInt( header, "framewidth"  );
    frames =      HeaderInt( header, "frames"      );
    samplerate =  HeaderSamplerate( header, "samplerate"  );

    start =  to_p( startstr,  samplerate );
    if ( ismax( lengthstr ) )   /* Special case for remainder of input */
	length = frames - start ;
    else
	length = to_p( lengthstr, samplerate );

    if ( start + length > frames ) {
	fprintf(stderr,"naptosai: nap too small (%d ms) for requested start and length \n", to_ms( frames, samplerate ) );
	exit(1);
    }

    framebytes = frameheight * length * sizeof(short) ;
    startbytes = frameheight * start  * sizeof(short) ;

    Newframeheight = frameheight ;
    if ( ismax( widthstr ) )    /* Special case for single frame of max width */
	Newframewidth = length ;
    else
	Newframewidth = to_p( widthstr, samplerate ) ;
    Newframeshift = to_p( shiftstr, samplerate ) ;
    Newframebytes =  Newframeheight * Newframewidth * sizeof(short) ;
    if ( Newframeshift > 0 )
	Newframes = 1 + ( length - Newframewidth ) / Newframeshift ;
    else {              /* Special case of zero shift */
	Newframes = 1 ;
	Newframeshift = 1 ;
    }

    if ( length < Newframewidth ) {
	fprintf(stderr,"naptosai: nap too small (%d ms) for requested width\n", to_ms( length, samplerate ) );
	exit(1);
    }

    fprintf(stderr,"Output %d sai frames, each %d bytes\n", Newframes, Newframebytes );

    if ( ison( headerstr ) )
	WriteHeader( SaiHeader(header), stdout );

    /* Allocate space for framebytes of nap data */

    if ( (nap = (short *)malloc( framebytes )) == NULL ) {
	fprintf(stderr,"naptosai: malloc out of space\n");
	exit(1);
    }

    /* Seek to start in blocks of framebytes */

    for (i=framebytes ; i < startbytes ; i += framebytes)
	if ( fread( nap, framebytes, 1, fp ) == NULL ) {
	    fprintf(stderr,"naptosai: missing data after header\n");
	    exit(1);
	}
    if ( (startbytes -= (i - framebytes)) > 0 )
	if ( fread( nap, startbytes, 1, fp ) == NULL ) {
	    fprintf(stderr,"naptosai: missing data after header\n");
	    exit(1);
	}

    /* Read framebytes of i/p nap data */

    if ( fread( nap, framebytes, 1, fp ) == NULL ) {
	fprintf(stderr,"naptosai: missing data after header\n");
	exit(1);
    }

    frameshift = Newframeshift * Newframeheight ;
    endframe = nap + Newframes * frameshift ;

    for ( frame = nap ; frame < endframe ; frame += frameshift )
	writeframe( frame, stdout ) ;

    fprintf(stderr,"naptosai done\n" ) ;

}



/* Write a frame in sai format */

writeframe( frame, fp )
short  *frame ;
FILE   *fp ;
{
    int    i, row, col;

    for (row=0 ; row < Newframeheight ; row++)
	for (col=0 , i=row ; col < Newframewidth ; col++, i+=Newframeheight)
	    fwrite( &frame[i], sizeof(short), 1, fp );
}


/*********************** Read header and build new header *****************/

/*
   Copy the original nap header to a new sai header, changing in order:
     frames
     frameshift
     framewidth
     frameheight
     framebytes
   Then change applic name [gennap] to [gensai] in the Version string.
   Finally, update the new header_bytes, and return the new header.
*/

char *SaiHeader( napheader )
char *napheader ;
{
    char *saiheader;
    char *p0, *p1, *p2, *s, str[64];

    saiheader = (char *)malloc( strlen(napheader) + 64 ) ;

    p0 = saiheader ;
    p1 = napheader ;


    /** copy up to frames **/

    p2 = HeaderString( napheader , "frames" ) ;
    while( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframes);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to frameshift **/

    p2 = HeaderString( napheader , "frameshift" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframeshift);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to framewidth **/

    p2 = HeaderString( napheader , "framewidth" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframewidth);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to frameheight **/

    p2 = HeaderString( napheader , "frameheight" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframeheight);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to framebytes **/

    p2 = HeaderString( napheader , "framebytes" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframebytes);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy rest of header **/

    p2 = HeaderString( napheader , "Version" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    while (*p1 != ']')          /* change applic name [gennap] to [gensai] */
	*p0++ = *p1++ ;
    *(p0-3) = 's' ;
    *(p0-2) = 'a' ;
    *(p0-1) = 'i' ;
    while (*p1 != '\n')
	*p0++ = *p1++ ;
    *p0++ = *p1++ ;


    /** update header_bytes **/

    sprintf(str, "%0*d", 7, p0-saiheader);
    p0 = HeaderString( saiheader , "header_bytes" ) ;
    s = str;
    while(*p0 != '\n')
	*p0++ = *s++ ;


    return saiheader;
}