tomwalters@0: /* tomwalters@0: naptosai.c NAP to SAI format conversion. tomwalters@0: ------------ tomwalters@0: tomwalters@0: Read a NAP header and frame. tomwalters@0: Write a SAI header, (created from the NAP header). tomwalters@0: Write a succession of SAI frames. tomwalters@0: tomwalters@0: The options "start" and "length" specify the NAP which is input. tomwalters@0: The options "width" and "frstep" specify the SAI frames which are output. tomwalters@0: tomwalters@0: Special option values are: tomwalters@0: tomwalters@0: length=max Input all the NAP from the given start to its end. tomwalters@0: width=max Output framewidth is set equal to the given NAP length, tomwalters@0: and if this is also "max", then the framewidth is the tomwalters@0: remainder of the NAP. tomwalters@0: frstep=0 Output one frame of given width from the given start of tomwalters@0: the NAP. tomwalters@0: tomwalters@0: For example, use naptosai with width=max and frstep=0 to produce one SAI tomwalters@0: frame the same size as the input NAP. tomwalters@0: tomwalters@0: Examples: tomwalters@0: tomwalters@0: tomwalters@0: 1. To convert a nap or a bmm output to a single frame of sai output: tomwalters@0: tomwalters@0: gennap length=64 output=stdout file | naptosai width=32 frstep=0 > file.sai tomwalters@0: gensai top=1000 useprevious=on file tomwalters@0: tomwalters@0: genbmm output=stdout file | naptosai > file.sai tomwalters@0: gensai bottom=-100 useprevious=on file tomwalters@0: tomwalters@0: This uses special case of zero frstep to generate one frame of output with tomwalters@0: the given width. The default width is the given length, and the default tomwalters@0: length is the remainder of the input file. If the width=length, then the tomwalters@0: frstep is zero by default, and therefore the default process, (ie with no tomwalters@0: arguments), converts the whole of the input to a single SAI frame. tomwalters@0: tomwalters@0: Note, certain display parameters have different default values for different tomwalters@0: applications. The SAI display parameters should be set to the appropriate tomwalters@0: values, in order to plot the SAI on the same scale. For example: tomwalters@0: When the source application is NAP, set gensai top=1000 tomwalters@0: When the source application is BMM, set gensai bottom=-100 tomwalters@0: tomwalters@0: tomwalters@0: 2. To convert a nap output to multiple frames of sai output: tomwalters@0: tomwalters@0: gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai tomwalters@0: gensai top=1000 useprevious=on file tomwalters@0: tomwalters@0: The sai output can be plotted as a spiral, but it is best to set the tomwalters@0: display parameters as follows: tomwalters@0: tomwalters@0: gennap length=40 output=stdout dencf=1 width=500 height=500 file | \ tomwalters@0: naptosai width=32 frstep=0.2 > file.sai tomwalters@0: genspl useprevious=on pensize=2 file tomwalters@0: tomwalters@0: tomwalters@0: 3. To convert a nap output to a sai format bitmap, to display an animated tomwalters@0: stream: tomwalters@0: tomwalters@0: gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai tomwalters@0: gensai top=1000 useprevious=on bitmap=on file tomwalters@0: review file tomwalters@0: tomwalters@0: The same can be done for the spiral display: tomwalters@0: tomwalters@0: gennap length=40 output=stdout dencf=1 width=500 height=500 file | \ tomwalters@0: naptosai width=32 frstep=0.2 > file.sai tomwalters@0: genspl useprevious=on pensize=2 bitmap=on file tomwalters@0: review file tomwalters@0: tomwalters@0: The plots show the nap moving though 8ms (40-32), in steps of 0.2ms, tomwalters@0: first in rectangular display, then in spiral-mapped display. tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include "header.h" tomwalters@0: #include "options.h" tomwalters@0: #include "units.h" tomwalters@0: #include "strmatch.h" tomwalters@0: tomwalters@0: char applic[] = "NAP to SAI format conversion. " ; tomwalters@0: tomwalters@0: static char *helpstr, *debugstr, *startstr, *lengthstr, *widthstr, *shiftstr, *headerstr ; tomwalters@0: tomwalters@0: static Options option[] = { tomwalters@0: { "help" , "off" , &helpstr , "help" , DEBUG }, tomwalters@0: { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, tomwalters@0: { "start" , "0" , &startstr , "Start point in i/p NAP" , VAL }, tomwalters@0: { "length" , "max" , &lengthstr , "Length of i/p NAP to process." , VAL }, tomwalters@0: { "header" , "on" , &headerstr , "sai header" , VAL }, tomwalters@0: { "width" , "max" , &widthstr , "Width of o/p SAI frame." , VAL }, tomwalters@0: { "frstep" , "1ms" , &shiftstr , "Step between o/p frames of SAI.\n(frstep=0 gets 1 frame of given width)." , VAL }, tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: int frameheight, framewidth ; /* Nap parameters read from header */ tomwalters@0: int frames, samplerate ; tomwalters@0: tomwalters@0: int start, length ; tomwalters@0: tomwalters@0: int Newframeheight, Newframewidth ; /* Sai parameters to write */ tomwalters@0: int Newframes ; tomwalters@0: int Newframeshift ; tomwalters@0: int Newframebytes ; tomwalters@0: tomwalters@0: tomwalters@0: main(argc, argv) tomwalters@0: int argc ; tomwalters@0: char *argv[] ; tomwalters@0: { tomwalters@0: FILE *fp ; tomwalters@0: int i, framebytes, startbytes, frameshift; tomwalters@0: char *header, *SaiHeader(); tomwalters@0: short *nap, *frame, *endframe; tomwalters@0: tomwalters@0: fp = openopts( option,argc,argv ) ; tomwalters@0: if ( !isoff( helpstr ) ) tomwalters@0: helpopts( helpstr, argv[0], applic, option ) ; tomwalters@0: tomwalters@0: if ( ison( debugstr ) ) { tomwalters@0: printf("start=%s length=%s width=%s shift=%s\n", tomwalters@0: startstr, lengthstr, widthstr, shiftstr ); tomwalters@0: exit(0); tomwalters@0: } tomwalters@0: tomwalters@0: if ( (header = ReadHeader(fp)) == (char *) 0 ) { tomwalters@0: fprintf(stderr,"naptosai: header not found\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: frameheight = HeaderInt( header, "frameheight" ); tomwalters@0: framewidth = HeaderInt( header, "framewidth" ); tomwalters@0: frames = HeaderInt( header, "frames" ); tomwalters@0: samplerate = HeaderSamplerate( header, "samplerate" ); tomwalters@0: tomwalters@0: start = to_p( startstr, samplerate ); tomwalters@0: if ( ismax( lengthstr ) ) /* Special case for remainder of input */ tomwalters@0: length = frames - start ; tomwalters@0: else tomwalters@0: length = to_p( lengthstr, samplerate ); tomwalters@0: tomwalters@0: if ( start + length > frames ) { tomwalters@0: fprintf(stderr,"naptosai: nap too small (%d ms) for requested start and length \n", to_ms( frames, samplerate ) ); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: framebytes = frameheight * length * sizeof(short) ; tomwalters@0: startbytes = frameheight * start * sizeof(short) ; tomwalters@0: tomwalters@0: Newframeheight = frameheight ; tomwalters@0: if ( ismax( widthstr ) ) /* Special case for single frame of max width */ tomwalters@0: Newframewidth = length ; tomwalters@0: else tomwalters@0: Newframewidth = to_p( widthstr, samplerate ) ; tomwalters@0: Newframeshift = to_p( shiftstr, samplerate ) ; tomwalters@0: Newframebytes = Newframeheight * Newframewidth * sizeof(short) ; tomwalters@0: if ( Newframeshift > 0 ) tomwalters@0: Newframes = 1 + ( length - Newframewidth ) / Newframeshift ; tomwalters@0: else { /* Special case of zero shift */ tomwalters@0: Newframes = 1 ; tomwalters@0: Newframeshift = 1 ; tomwalters@0: } tomwalters@0: tomwalters@0: if ( length < Newframewidth ) { tomwalters@0: fprintf(stderr,"naptosai: nap too small (%d ms) for requested width\n", to_ms( length, samplerate ) ); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: fprintf(stderr,"Output %d sai frames, each %d bytes\n", Newframes, Newframebytes ); tomwalters@0: tomwalters@0: if ( ison( headerstr ) ) tomwalters@0: WriteHeader( SaiHeader(header), stdout ); tomwalters@0: tomwalters@0: /* Allocate space for framebytes of nap data */ tomwalters@0: tomwalters@0: if ( (nap = (short *)malloc( framebytes )) == NULL ) { tomwalters@0: fprintf(stderr,"naptosai: malloc out of space\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: /* Seek to start in blocks of framebytes */ tomwalters@0: tomwalters@0: for (i=framebytes ; i < startbytes ; i += framebytes) tomwalters@0: if ( fread( nap, framebytes, 1, fp ) == NULL ) { tomwalters@0: fprintf(stderr,"naptosai: missing data after header\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: if ( (startbytes -= (i - framebytes)) > 0 ) tomwalters@0: if ( fread( nap, startbytes, 1, fp ) == NULL ) { tomwalters@0: fprintf(stderr,"naptosai: missing data after header\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: /* Read framebytes of i/p nap data */ tomwalters@0: tomwalters@0: if ( fread( nap, framebytes, 1, fp ) == NULL ) { tomwalters@0: fprintf(stderr,"naptosai: missing data after header\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: frameshift = Newframeshift * Newframeheight ; tomwalters@0: endframe = nap + Newframes * frameshift ; tomwalters@0: tomwalters@0: for ( frame = nap ; frame < endframe ; frame += frameshift ) tomwalters@0: writeframe( frame, stdout ) ; tomwalters@0: tomwalters@0: fprintf(stderr,"naptosai done\n" ) ; tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* Write a frame in sai format */ tomwalters@0: tomwalters@0: writeframe( frame, fp ) tomwalters@0: short *frame ; tomwalters@0: FILE *fp ; tomwalters@0: { tomwalters@0: int i, row, col; tomwalters@0: tomwalters@0: for (row=0 ; row < Newframeheight ; row++) tomwalters@0: for (col=0 , i=row ; col < Newframewidth ; col++, i+=Newframeheight) tomwalters@0: fwrite( &frame[i], sizeof(short), 1, fp ); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /*********************** Read header and build new header *****************/ tomwalters@0: tomwalters@0: /* tomwalters@0: Copy the original nap header to a new sai header, changing in order: tomwalters@0: frames tomwalters@0: frameshift tomwalters@0: framewidth tomwalters@0: frameheight tomwalters@0: framebytes tomwalters@0: Then change applic name [gennap] to [gensai] in the Version string. tomwalters@0: Finally, update the new header_bytes, and return the new header. tomwalters@0: */ tomwalters@0: tomwalters@0: char *SaiHeader( napheader ) tomwalters@0: char *napheader ; tomwalters@0: { tomwalters@0: char *saiheader; tomwalters@0: char *p0, *p1, *p2, *s, str[64]; tomwalters@0: tomwalters@0: saiheader = (char *)malloc( strlen(napheader) + 64 ) ; tomwalters@0: tomwalters@0: p0 = saiheader ; tomwalters@0: p1 = napheader ; tomwalters@0: tomwalters@0: tomwalters@0: /** copy up to frames **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "frames" ) ; tomwalters@0: while( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: sprintf(str,"%d\n", Newframes); tomwalters@0: for (s = str ; *s != '\n' ; ) tomwalters@0: *p0++ = *s++; tomwalters@0: *p0++ = *s; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p1++; tomwalters@0: *p1++; tomwalters@0: tomwalters@0: tomwalters@0: /** copy up to frameshift **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "frameshift" ) ; tomwalters@0: while ( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: sprintf(str,"%d\n", Newframeshift); tomwalters@0: for (s = str ; *s != '\n' ; ) tomwalters@0: *p0++ = *s++; tomwalters@0: *p0++ = *s; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p1++; tomwalters@0: *p1++; tomwalters@0: tomwalters@0: tomwalters@0: /** copy up to framewidth **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "framewidth" ) ; tomwalters@0: while ( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: sprintf(str,"%d\n", Newframewidth); tomwalters@0: for (s = str ; *s != '\n' ; ) tomwalters@0: *p0++ = *s++; tomwalters@0: *p0++ = *s; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p1++; tomwalters@0: *p1++; tomwalters@0: tomwalters@0: tomwalters@0: /** copy up to frameheight **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "frameheight" ) ; tomwalters@0: while ( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: sprintf(str,"%d\n", Newframeheight); tomwalters@0: for (s = str ; *s != '\n' ; ) tomwalters@0: *p0++ = *s++; tomwalters@0: *p0++ = *s; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p1++; tomwalters@0: *p1++; tomwalters@0: tomwalters@0: tomwalters@0: /** copy up to framebytes **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "framebytes" ) ; tomwalters@0: while ( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: sprintf(str,"%d\n", Newframebytes); tomwalters@0: for (s = str ; *s != '\n' ; ) tomwalters@0: *p0++ = *s++; tomwalters@0: *p0++ = *s; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p1++; tomwalters@0: *p1++; tomwalters@0: tomwalters@0: tomwalters@0: /** copy rest of header **/ tomwalters@0: tomwalters@0: p2 = HeaderString( napheader , "Version" ) ; tomwalters@0: while ( p1 < p2 ) tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: while (*p1 != ']') /* change applic name [gennap] to [gensai] */ tomwalters@0: *p0++ = *p1++ ; tomwalters@0: *(p0-3) = 's' ; tomwalters@0: *(p0-2) = 'a' ; tomwalters@0: *(p0-1) = 'i' ; tomwalters@0: while (*p1 != '\n') tomwalters@0: *p0++ = *p1++ ; tomwalters@0: *p0++ = *p1++ ; tomwalters@0: tomwalters@0: tomwalters@0: /** update header_bytes **/ tomwalters@0: tomwalters@0: sprintf(str, "%0*d", 7, p0-saiheader); tomwalters@0: p0 = HeaderString( saiheader , "header_bytes" ) ; tomwalters@0: s = str; tomwalters@0: while(*p0 != '\n') tomwalters@0: *p0++ = *s++ ; tomwalters@0: tomwalters@0: tomwalters@0: return saiheader; tomwalters@0: } tomwalters@0: tomwalters@0: