view tools/header.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
/***************************************************************************
    Utilities for model output headers.

    A header is an ASCII desciption which summarises the state of
    a process by giving a list of parameter values etc etc..
    Each parameter is described on a separate line, and the header consists
    of several lines of the general form:

	<ASCII description> = <value>\n

    For example, the first five lines of the header generated by a command
    line "gensai -header fname" is as follows:

	header_bytes=0000532
	scale_sai=0.25
	imagedurn_sai=16
	decayrate_sai=10
	cgmdecay=24
	 ...
	date=Thu Jan 11 00:19:41 WET 1990\n
	\000

    This string is written onto the front of  the  file  with  padding  if
    desired  before  any data is written.  The header can be of any length
    and contain any combination of non null characters.  Header items  are
    identified  by  the  string on the left of the equals symbol and their
    value is represented by the string on the remainder of that line.

    The first line is always the HEADER_STRING (ie. header_bytes=....\n)
    which gives the length of the header.

Synopsis of utilities:
----------------------

char *ReadHeader( fp )
FILE *fp ;

WriteHeader(header,fp)
char  *header;
FILE  *fp;

char *HeaderString( header, name )
char *header, *name ;

char *HeaderStringOnly( header, name )
char *header, *name ;

double HeaderDouble( header, name )
char *header, *name ;

double HeaderInt( header, name )
char *header, *name ;

void FreeHeader( header )
char *header ;

ReadHeader() reads a header (if it exists ) from the  file  into
    memory  and  returns  a  pointer to the header in memory allocated for
    storing the header. It returns a null pointer if no header is found.
    It leaves the fp pointing to the data which follows the header.
WriteHeader() writes the given header on the given file stream.
HeaderString() simply searches through the header for values the  user
    requests  and  returns  a  pointer  to  the  beginning  of  the  value.
    It returns a null pointer if the required string is not found.
HeaderStringOnly() returns a pointer  to  an  allocated  string  that
    contains  only  the  value  rather  than  a  pointer  to a string that
    includes the all the rest of the header (which is what  HeaderString()
    returns). It returns a null pointer if the required string is not found.
HeaderDouble() converts values to Doubles.
HeaderInt() converts values to Ints.
FreeHeader() frees the space allocated for a header by ReadHeader.

Example:
-------
    A simple example of the use of the header utility routines to read the
    sai dimensions from a header would be:
    (This assumes a ".sai" file generated by a command like "gensai -header")

    #include <stdio.h>
    #include <math.h>
    #include "header.c"
    char *header = ReadHeader(fp);        fp is file-pointer to ".sai" file
    int   frameheight = HeaderInt(header,"frameheight");   num chans
    int   framewidth  = HeaderInt(header,"framewidth");    sai duration

    char *name = "frameheight";
    printf( "%s=%s\n", name, HeaderStringOnly( header, name ) ) ;

****************************************************************************/

#include <stdio.h>
/* #include <strings.h> */
#include <string.h>
#include <malloc.h>
#include "header.h"
#include "units.h"


/***************************************************************************
    ReadHeader() reads a header (if it exists ) from the  file  into
    memory  and  returns  a  pointer to the header in memory allocated for
    storing the header. It returns a null pointer if no header is found.
****************************************************************************/
char *ReadHeader( fp )
FILE *fp ;
{
    static char header_string[] = HEADER_STRING ;
    static char header_start[]  = HEADER_START  ;
    unsigned header_length ;
    char *header ;

    if( fread( header_string, sizeof ( *header_string ), STRSIZE( header_string ), fp ) == STRSIZE( header_string )
	  && strncmp( header_string, header_start, STRSIZE( header_start ) ) == 0 ) {

	/* header located - remove carriage return */

	header_length = atoi( header_string + STRSIZE( header_start ) ) ;

	header = malloc( header_length ) ;

	if( header != (char *) 0 ) {
	    (void) strcpy( header, header_string ) ;
	    (void) fread( header + STRSIZE( header_string ), sizeof ( *header_string ), (int) header_length - STRSIZE( header_string ), fp ) ;
	}

	return ( header ) ;
    }
    else {
	/* header not present */

	(void) fseek( fp, 0l, 0 ) ;

	return ( (char *) 0 ) ;
    }
}

/***************************************************************************
    WriteHeader() writes the given header on the given file stream.
****************************************************************************/
WriteHeader(header,fp)
char  *header;
FILE  *fp;
{
    int    header_length, HeaderInt();

    header_length = HeaderInt(header,"header_bytes");
    fwrite(header,sizeof(char),header_length,fp);
}


/***************************************************************************
    HeaderString() simply searches through the header for values the  user
    requests  and  returns  a  pointer  to  the  begining  of  the  value.
****************************************************************************/
char *HeaderString( header, name )
char *header, *name ;
{
    register char *next_line = header ;
    register int name_len = strlen( name ) ;

    do
	if( strncmp( next_line, name, name_len ) == 0 ) {

	    next_line+=name_len ;

	    if( *next_line++ == '=' )
		return ( next_line ) ;
	}

    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;

    return ( (char *) 0 ) ;
}


/***************************************************************************
    HeaderStringOnly() returns a pointer  to  an  allocated  string  that
    contains  only  the  value  rather  than  a  pointer  to a string that
    includes the all the rest of the header which is what  HeaderString()
    returns.
****************************************************************************/
char *HeaderStringOnly( header, name )
char *header, *name ;
{
    char *value = HeaderString( header, name ) ;
    unsigned value_length ;

    if( value != (char *) 0 ) {
	value_length = strchr( value, '\n' ) - value ;
	return ( strncpy( malloc( value_length+1 ), value, (int) value_length ) ) ;
    }
    else
	return ( (char *) 0 ) ;
}


/***************************************************************************
    HeaderStrings() searches through the header for values the  user
    requests  and  returns  a  pointer  to  the  begining  of  the  value.
    This is a version of HeaderString() which allows abbreviated names,
    return null ptr if not found or ambiguous.
****************************************************************************/
char *HeaderStrings( header, name )
char *header, *name ;
{
    register char *next_line = header ;
    register int name_len = strlen( name ) ;
    char *valptr ;
    int   count = 0 ;

    do
	if( strncmp( next_line, name, name_len ) == 0 ) {

	    next_line+=name_len ;

	    if ( ( valptr = strchr( next_line, '=' ) ) != (char *)0 ) {

		/* return directly if name matches exactly otherwise wait to check ambiguity */
		if ( valptr == next_line ) return ( valptr + 1 ) ;

		valptr++ ;
		count++ ;
	    }
	}

    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;

    if( count == 1 )
	return ( valptr ) ;
    else
	return ( (char *) 0 ) ; /* not found or ambiguous */
}


/***************************************************************************
    HeaderNameString() returns a pointer  to  an  allocated  string  that
    contains  the full name corresponding to the given name, which can be
    given in abbreviated form provided this is unambiguous.
    Return a null ptr if the name is not found or is ambiguous.
    (This is an amalgam of HeaderString() and HeaderStringOnly() which also
    checks for ambiguity)
****************************************************************************/

char *HeaderNameString( header, name )
char *header, *name ;
{
    register char *next_line = header ;
    register int name_len = strlen( name ) ;
    unsigned name_length ;
    char *nameptr ;
    int   count = 0 ;

    do
	if( strncmp( next_line, name, name_len ) == 0 ) {
	    if ( strchr( next_line, '=' ) != (char *)0 ) {
		nameptr = next_line ;

		/* return directly if name matches exactly otherwise wait to check ambiguity */
		if ( name_len == ( name_length = strchr( next_line, '=' ) - next_line ) )
		    return ( strncpy( malloc( name_length+1 ), nameptr, (int) name_length ) ) ;
		count++ ;
	    }
	}

    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;

    if( count == 1 ) {
	name_length = strchr( nameptr, '=' ) - nameptr ;
	return ( strncpy( malloc( name_length+1 ), nameptr, (int) name_length ) ) ;
    }
    else
	return ( (char *) 0 ) ; /* not found or ambiguous */
}


/***************************************************************************
    HeaderValueString() returns a pointer  to  an  allocated  string  that
    contains  the value corresponding to the given name, which can be given
    in abbreviated form provided this is unambiguous.
    Return a null ptr if the name is not found or is ambiguous.
    (This is an amalgam of HeaderString() and HeaderStringOnly() which also
    checks for ambiguity)
****************************************************************************/

char *HeaderValueString( header, name )
char *header, *name ;
{
    register char *next_line = header ;
    register int name_len = strlen( name ) ;
    unsigned value_length ;
    char *valptr ;
    int   count = 0 ;

    do
	if( strncmp( next_line, name, name_len ) == 0 ) {

	    next_line+=name_len ;

	    if ( ( valptr = strchr( next_line, '=' ) ) != (char *)0 ) {

		/* return directly if name matches exactly otherwise wait to check ambiguity */
		if ( valptr == next_line ) {
		    valptr++ ;
		    value_length = strchr( valptr, '\n' ) - valptr ;
		    return ( strncpy( malloc( value_length+1 ), valptr, (int) value_length ) ) ;
		}

		valptr++ ;
		count++ ;
	    }
	}

    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;

    if( count == 1 ) {
	value_length = strchr( valptr, '\n' ) - valptr ;
	return ( strncpy( malloc( value_length+1 ), valptr, (int) value_length ) ) ;
    }
    else
	return ( (char *) 0 ) ; /* not found or ambiguous */
}


/***************************************************************************
    HeaderDouble() converts values to Doubles.
****************************************************************************/
double HeaderDouble( header, name )
char *header, *name ;
{
    char  *valuestr ;

    if ( (valuestr = HeaderString( header, name )) == (char *) 0) {
	fprintf(stderr,"option %s not found in header\n", name);
	exit(1);
    }
    return ( atof( HeaderString( header, name ) ) ) ;
}


/***************************************************************************
    HeaderInt() converts values to Ints.
****************************************************************************/
int HeaderInt( header, name )
char *header, *name ;
{
    char  *valuestr ;

    if ( (valuestr = HeaderString( header, name )) == (char *) 0) {
	fprintf(stderr,"option %s not found in header\n", name);
	exit(1);
    }
    return ( atoi( valuestr ) ) ;
}


/***************************************************************************
    HeaderSamplerate() returns the samplerate
****************************************************************************/
HeaderSamplerate( header )
char *header ;
{
    char  *valuestr ;

    if ( (valuestr = HeaderStringOnly( header, "samplerate" )) == (char *) 0) {
	fprintf(stderr,"samplerate not found in header\n");
	exit(1);
    }
    return ( (int)to_Hz( valuestr, 1 ) ) ;
}


/***************************************************************************
    FreeHeader frees the space allocated for a header by ReadHeader
****************************************************************************/
void FreeHeader( header )
char *header ;
{
    free( header ) ;
    return ;
}


/***************************************************************************
  ApplicString() return a ptr to the rest of the header which starts with
  the 3-char application name of the program.
***************************************************************************/

char *ApplicString( header )
char *header ;
{
    char *versionstr, *progname ;

    if ( ( versionstr = HeaderString( header, "Version" ) ) == (char *)0 )
	return (char *)( 0 ) ; /* version string not found in header           */

    if ( ( progname = strchr( versionstr, '[' ) ) == (char *)0 )
	return (char *)( 0 ) ; /* program name not found in version string     */
    if ( strchr( versionstr, ']' ) - ( progname += 4 ) != 3 )
	return (char *)( 0 ) ; /* application name not found in version string */

    return ( progname ) ;
}


/***************************************************************************
  Applic() returns the index number to the gen_applics list (see header.h)
  of the application name of the program (the last three letters of its name).
  This is assumed to be delimited by [ ] in the version string in the header.
  Return a -ve number on error.
***************************************************************************/

Applic( header )
char *header ;
{
    char *versionstr, *progname ;
    int   i ;

    if ( ( versionstr = HeaderStringOnly( header, "Version" ) ) == (char *)0 )
	return ( -2 ) ; /* version string not found in header           */

    if ( ( progname = strchr( versionstr, '[' ) ) == (char *)0 )
	return ( -3 ) ; /* program name not found in version string     */
    if ( strchr( versionstr, ']' ) - ( progname += 4 ) != 3 )
	return ( -4 ) ; /* application name not found in version string */
    for ( i = 0 ; gen_applics[i] != (char *)0 ; i++ )
	if ( strncmp( gen_applics[i], progname, 3 ) == 0 )
	    return i ;

    return ( -1 ) ;     /* application name not found in version string */
}


/**************************************************************************

The table below gives the meaning of the frame parameters for each gen
program. The frame parameters are frameheight, framewidth, and frames.
Depending upon the program and the "view", they can mean:

	chans      =  number of filterbank channels.
	length     =  duration in samples.
	num frames =  number of cartoon frames.
	pwidth     =  "positive width" of auditory image.
	nwidth     =  "negative width" of auditory image.

In all cases framebytes = frameheight * framewidth * sizeof(short)

The table also shows how the frame parameters relate to the format of the
display, where each of "num frames" frames of a cartoon is described as a
matrix of "rows" * "cols". The number of rows describes the vertical direction
and the number of cols describes the horizontal direction.


gen         Frame parameters in header                    Format of display matrix
---     -------------------------------------        ----------------------------------
	view         height  width     frames        rows        cols        num frames
	----         ------  -----     ------        ----        ----        ----------

wav     wave         1       1         length        frameheight frames      1

bmm     landscape    chans   1         length        frameheight frames      1
nap     landscape    chans   1         length        frameheight frames      1

sgm     greyscale    chans   1         length        frameheight frames      1
cgm     greyscale    chans   1         length        frameheight frames      1
sas     greyscale    chans   1         length        frameheight frames      1

asa     excitation   chans   1         num frames    framewidth  frameheight frames
epn     excitation   chans   1         num frames    framewidth  frameheight frames
sep     excitation   chans   1         num frames    framewidth  frameheight frames

sai     landscape    chans   p+nwidth  num frames    frameheight framewidth  frames

spl     spiral       chans   pwidth    num frames    frameheight framewidth  frames


The table below shows the format of the AIM output array for each gen program
in terms of the frame parameters.


gen  Output array format                          Comment
---  ----------------------------------   -----------------------------
wav  frames sets of frameheight (=1)      array of time samples.

					  -----------------------------
bmm  frames sets of frameheight           2-D array by columns,
nap  frames sets of frameheight             with lowest centre-frequency
					    first in each column.
sgm  frames sets of frameheight
cgm  frames sets of frameheight
sas  frames sets of frameheight

					  -----------------------------
asa  frameheight sets of framewidth (=1)  array of frequency samples.
epn  frameheight sets of framewidth (=1)
sep  frameheight sets of framewidth (=1)

					  -----------------------------
sai  frameheight sets of framewidth       2-D array by rows,
					    with lowest centre-frequency
spl  frameheight sets of framewidth         row first in each frame.


The gen programs group into five format types each with a particular
interpretation of it's frame parameters, it's output array format, and it's
"view". These are defined (in header.h) as:

Format  gen programs
------  --------------
WAV     wav
NAP     bmm, nap
SGM     sgm, cgm, sas
EPN     asa, epn, sep
SAI     sai, spl





***************************************************************************/





/**************************************************************************
  Format() returns the index number to the gen_formats list (see header.h)
  of the given application number (eg returned by Applic()).
   0 = wave format (array of time points)
   1 = nap format  (by columns, lowest centre-frequency first in each column)
   2 = sgm format  (by columns, lowest centre-frequency first in each column)
   3 = epn format  (array of frequency points per frame)
   4 = sai format  (by rows, lowest centre-frequency row first per frame)
***************************************************************************/

Format( applic )
int  applic ;
{
    switch ( applic ) {

	case 0 :                        return ( 0 ) ;

	case 1 :  case 2 :  case 3 :
	case 4 :  case 5 :  case 6 :
	case 7 :                        return ( 1 ) ;

	case 8 :  case 9 :  case 10:    return ( 2 ) ;

	case 11:  case 12:  case 13:    return ( 3 ) ;

	case 14:  case 15:              return ( 4 ) ;

	default : fprintf( stderr,"unknown application index number\n" ) ;
		  exit( 1 ) ;
    }
}


/**************************************************************************
  frame_to_matrix()
  Given the format number (see: Format(), Applic() and the gen_formats list
  in header.h), and the frameheight, framewidth, and frames,
  return the format of the frames in terms of the number of rows
  (ie. channels) and columns (ie. samples) per frame, and the number of
  such frames, via the given addresses.
  The number of bytes per frame is then = rows * cols * 2.
***************************************************************************/

frame_to_matrix( format, rows, cols, numframes, frameheight, framewidth, frames )
int format, *rows, *cols, *numframes, frameheight, framewidth, frames ;
{
    switch ( format ) {
	case 0 :        *rows      = 1           ;      /* wav format */
			*cols      = frames      ;
			*numframes = 1           ;
			break ;

	case 1 :        *rows      = frameheight ;      /* nap format */
			*cols      = frames      ;
			*numframes = 1           ;
			break ;

	case 2 :        *rows      = frameheight ;      /* sgm format */
			*cols      = frames      ;
			*numframes = 1           ;
			break ;

	case 3 :        *rows      = 1           ;      /* epn format */
			*cols      = frameheight ;
			*numframes = frames      ;
			break ;

	case 4 :        *rows      = frameheight ;      /* sai format */
			*cols      = framewidth  ;
			*numframes = frames      ;
			break ;

	default :       fprintf( stderr,"unknown format number\n" ) ;
			exit( 1 ) ;
    }
}


/**************************************************************************
  matrix_to_frame()
  Inverse of frame_to_matrix().
  Given the format number and the format in terms of the number of rows and
  columns per frame and the number of such frames, return the frameheight,
  framewidth and frames via the given addresses.
***************************************************************************/

matrix_to_frame( format, rows, cols, numframes, frameheight, framewidth, frames )
int format, rows, cols, numframes, *frameheight, *framewidth, *frames ;
{
    switch ( format ) {
	case 0 :        *frameheight = 1         ;      /* wav format */
			*framewidth  = 1         ;
			*frames      = cols      ;
			break ;

	case 1 :        *frameheight = rows      ;      /* nap format */
			*framewidth  = 1         ;
			*frames      = cols      ;
			break ;

	case 2 :        *frameheight = rows      ;      /* sgm format */
			*framewidth  = 1         ;
			*frames      = cols      ;
			break ;

	case 3 :        *frameheight = cols      ;      /* epn format */
			*framewidth  = 1         ;
			*frames      = numframes ;
			break ;

	case 4 :        *frameheight = rows      ;      /* sai format */
			*framewidth  = cols      ;
			*frames      = numframes ;
			break ;

	default :       fprintf( stderr,"unknown format number\n" ) ;
			exit( 1 ) ;
    }
}