esignal_fea.c

来自「speech signal process tools」· C语言 代码 · 共 1,315 行 · 第 1/3 页

C
1,315
字号
/* * This material contains unpublished, proprietary software of  * Entropic Research Laboratory, Inc. Any reproduction, distribution,  * or publication of this work must be authorized in writing by Entropic  * Research Laboratory, Inc., and must bear the notice:  * *    "Copyright (c) 1996 Entropic Research Laboratory, Inc.  *                   All rights reserved." * * The copyright notice above does not evidence any actual or intended  * publication of this source code.      * * Written by:  Rodney Johnson * Checked by: * Revised by: * * Brief description:  Functions for use by ESPS I/O routine in dealing * with files in Esignal format. * */static char *sccs_id = "@(#)esignal_fea.c	1.4	10/6/97	ERL";#include <esps/esps.h>#include <esps/fea.h>/* * NAME CONFLICT:  The ESPS data-type codes named * DOUBLE, FLOAT, LONG, SHORT, and CHAR * are different from the Esignal data-type codes with the same names. * While the ESPS definitions are in effect, declare variables so that * the ESPS codes can be referred to as  * FDOUBLE, FFLOAT, FLONG, FSHORT, and FCHAR * instead.  (Think of "fea-double", "fea-float", etc.) * After the inclusion of <esignal.h> below, the Esignal definitions of * DOUBLE, FLOAT, LONG, SHORT, and CHAR * take effect. */static int FDOUBLE = DOUBLE;#undef	DOUBLEstatic int FFLOAT = FLOAT;#undef	FLOATstatic int FLONG = LONG;#undef	LONGstatic int FSHORT = SHORT;#undef	SHORTstatic int FCHAR = CHAR;#undef	CHAR#undef FLT_MAX#undef FLT_MIN#undef BOOL#include <esignal.h>#include <esps/esignal_fea.h>char	    *savestring(char *); /* ESPS library function.  Could replace				  * with "strdup" if available. */long	    get_genhd_val_l(char *, struct header *, long); /* See genhd.c */extern int  EspsDebug;		/* set in headers.c for header debugging */int	    EsignalPrefixSize = sizeof MAGIC;/* * LOCAL TYPEDEFS AND STRUCTURES */struct esignal_hd {    int		    arch;	/* format: ASCII, NATIVE, EDR1, or EDR2 */    long	    pre_size;	/* preamble size */    long	    hdr_size;	/* header size (bytes) */    long	    rec_size;	/* record size (or -1 for "variable") */    FieldList	    fields;	/* field list */    FieldSpec	    **lin_list;	/* input fields in field or type order */    int		    one_fld;	/* just one input field? */    long	    *fea_tag_ptr;				/* pointer to "tag" in last FEA record read */    struct fea_data fea_rec;	/* copy of pointers in last FEA record read */};/* *  LOCAL FUNCTION DECLARATIONS *//* used by esignal_to_fea */FieldList		GetHeader(char **version, int *arch, long *pre_size,				  long *hdr_size, long *rec_size,				  char *prefix, int num_read, FILE *file);static struct header	*FieldList_to_fea(FieldList list,					  struct fea_data **rec,					  char **fnames, int copy_sources);/* used by GetHeader */static int		GetPreamble(char **version, char **arch,				    long *pre_size, long *hdr_size,				    long *rec_size, char *str);/* used by GetPreamble */static int		GetLine(char *buf, int len, char **src);static int		GetLong(long *val, int len, char **src);/* used by FieldList_to_fea */static int		FindStr(char *str, char **arr);static char		**StrArrayFromRect(long *dim, void *data);static int		FieldIsTag(FieldSpec *fld);static int		FieldIsFeaSubtype(FieldSpec *fld);static int		ElibTypeToEsps(int type);/* * Check whether "prefix" points to a correct sequence of bytes for * the beginning of an Esignal file preamble.  If so, return TRUE; * otherwise return FALSE. */intesignal_check_prefix(char *prefix){    return (prefix != NULL	    && strncmp(prefix, MAGIC, (sizeof MAGIC) - 1) == 0	    && prefix[(sizeof MAGIC) - 1] == '\n');}/* * Assume "prefix" contains "num_read" bytes read from the beginning of * file "file" and that "file" is positioned for reading the following * characters.  If the catenation of "prefix"  with the remainder of "file" * begins with an Esignal file header, and if the part in "prefix" does * not go beyond the end of the preamble, the function reads the rest * of the header, converts it to an ESPS header insofar as is possible, * and leaves the file positioned at the end of the header, ready for * reading of any data records that follow.  The return value is a * pointer to the ESPS header, or NULL in case of error. * This function is intended for use when it has been necessary to read * a number of characters at the beginning of a file to determine whether * it is in an Esignal external format or some other (such as ESPS or NIST). * If "file" were known to be seekable, we could just rewind, call * ReadHeader, and convert the result.  However, this function is * intended to work on pipes. */struct header *esignal_to_fea(char *prefix,	       int  num_read,	       FILE *file){    FieldList	    list;	    /* input field list */    char	    *version;	    /* version from input preamble */    int		    arch;	    /* architecture from input preamble */    long	    pre_size;	    /* preamble size */    long	    hdr_size;	    /* header size (bytes) from preamble */    long	    rec_size;	    /* record size from preamble */    int		    inord;	    /* input: field order or type order? */    FieldSpec       **ifields;	    /* input fields in field or type order */    FieldSpec	    *fld;    struct header   *ohd;	    /* output ESPS file header */    double	    rec_freq;    double	    start_time;    esignal_hd	    *hd_ptr;    DebugMsgLevel = EspsDebug;    DebugMsgFunc = DebugPrint;    /*     * Get Esignal field list and other header information from prefix     * and file.     */    list = GetHeader(&version, &arch, &pre_size, &hdr_size, &rec_size,		     prefix, num_read, file);    if (list == NULL)    {	DebugMsg(1, "esignal_to_fea: get header failed.");	return NULL;    }    /*     * Check that record size in preamble is consistent with field     * list.     */    if (RecordSize(list, arch) != rec_size)    {	DebugMsg(1, "esignal_to_fea: inconsistent record size.");	return NULL;    }    /*     * Make linear list of REQUIRED and OPTIONAL fields in the order     * (type order or field order) in which they occur in records.     */    if (!GetFieldOrdering(list, &inord))    {	DebugMsg(1, "esignal_to_fea: can't get field ordering of input.");	return NULL;    }    switch (inord)    {    case TYPE_ORDER:	if (DebugMsgLevel)	    fprintf(stderr, "making type-ordered field array.\n");	ifields = TypeOrder(list);	break;    case FIELD_ORDER:	if (DebugMsgLevel)	    fprintf(stderr, "making field-ordered field array.\n");	ifields = FieldOrder(list);	break;    default:	DebugMsg(1, "input order neither TYPE_ORDER nor FIELD_ORDER");	return NULL;    }    /*     * Convert Esignal field list to ESPS FEA file header.     */    ohd = FieldList_to_fea(list, NULL, (char **) NULL, TRUE);    if (ohd == NULL)    {	DebugMsg(1, "failure converting Esignal field list to ESPS header.");	return NULL;    }    /*     * Set field_order flag.     */    if (inord == FIELD_ORDER)	ohd->hd.fea->field_order = TRUE;    /*     * Set FEA subtype code if (1) GLOBAL field "FeaSubtype" so indicates     * or (2) REQUIRED field "samples" implies FEA_SD.     */    if ((fld = FindField(list, "FeaSubtype")) != NULL	&& fld->occurrence == GLOBAL	&& fld->type == SHORT	&& fld->data != NULL)    {	ohd->hd.fea->fea_type = *(short *) fld->data;    }    else if ((fld = FindField(list, "samples")) != NULL	     && fld->occurrence == REQUIRED	     && is_type_numeric(ElibTypeToEsps(fld->type)))    {	ohd->hd.fea->fea_type = FEA_SD;    }    /*     * Set generics "record_freq" and "start_time"     */    if ((fld = FindField(list, "recordFreq")) != NULL	&& fld->occurrence == GLOBAL	&& fld->data != NULL)    {	(void) type_convert(1L, (char *) fld->data, ElibTypeToEsps(fld->type),			    (char *) &rec_freq, FDOUBLE, (void (*)()) NULL);	*add_genhd_d("record_freq", NULL, 1, ohd) = rec_freq;    }    if ((fld = FindField(list, "startTime")) != NULL	&& fld->occurrence == GLOBAL	&& fld->data != NULL)    {	(void) type_convert(1L, (char *) fld->data, ElibTypeToEsps(fld->type),			    (char *) &start_time, FDOUBLE, (void (*)()) NULL);	*add_genhd_d("start_time", NULL, 1, ohd) = start_time;    }    /*     * Show conversion from Esignal in program field and comment.     */    strcpy(ohd->common.prog, "esignal_to_fea");    add_comment(ohd, "Converted from Esignal header");    /*     * Make a generic "esignal_hd_ptr" containing a pointer to a     * structure containing the Esignal field list and other     * information needed for reading data.     */    hd_ptr = (esignal_hd *) malloc(sizeof(esignal_hd));    hd_ptr->arch = arch;    hd_ptr->pre_size = pre_size;    hd_ptr->hdr_size = hdr_size;    hd_ptr->rec_size = rec_size;    hd_ptr->fields = list;    hd_ptr->lin_list = ifields;    hd_ptr->one_fld =	(ifields != NULL && ifields[0] != NULL	 && ifields[1] == NULL && ifields[0]->occurrence == REQUIRED);    hd_ptr->fea_tag_ptr = NULL;    {	static struct fea_data	nulls;	/* Initialized to zeros and NULLs. */	hd_ptr->fea_rec = nulls;    }    *add_genhd_l("esignal_hd_ptr", (long *) NULL, 1, ohd) = (long) hd_ptr;    return ohd;}/* * Under the same assumptions on "prefix", "num_read", and "file" as * are made for "esignal_to_fea", read the remainder of the Esignal * header from "file", and leave the file positioned at the end of the * header, ready for reading of any data records that follow.  Return * value is the field list (NULL on failure).  Information from the * preamble is returned via pointer arguments.  This function is * similar to "ReadHeader", but is for use when it has been necessary * to read ahead some number of characters in the file. */#define PRE_SIZE ((size_t) 48)	/* preamble size: 6 lines of 8 characters				 * each, including terminal '\n' characters */FieldListGetHeader(char	**version,	/* version (output) */	  int	*arch,		/* architecture (output) */	  long	*pre_size,	/* preamble size  (output) */	  long	*hdr_size,	/* header size (output) */	  long	*rec_size,	/* record size (output) */	  char	*prefix,	/* initial bytes of preamble */	  int	num_read,	/* number of initial bytes */	  FILE	*file)		/* input file */{    FieldList	list;    char	*arch_string;    int		architecture;    char	*pre;		/* characters of full preamble */    if (num_read > PRE_SIZE)    {	DebugMsg(1, "GetHeader: read too far ahead.");	return NULL;    }    pre = malloc(PRE_SIZE);    memcpy(pre, prefix, (size_t) num_read);    if (num_read < PRE_SIZE	&& fread(pre + num_read, PRE_SIZE - num_read, 1, file) == 0)    {	DebugMsg(1, "GetHeader: couldn't read rest of Esignal preamble.");	return NULL;    }    if (!GetPreamble(version,		     &arch_string, pre_size, hdr_size, rec_size, pre))	return NULL;	/* Bad preamble. */    if (strcmp(arch_string, EsignalArch) == 0)    /* native architecture */	architecture = NATIVE;    else if (strcmp(arch_string, "EDR1") == 0)	architecture = EDR1;    else if (strcmp(arch_string, "EDR2") == 0)	architecture = EDR2;    else if (strcmp(arch_string, "ASCII") == 0)	architecture = ASCII;    else    {	if (arch != NULL)	    *arch = UNKNOWN;	return NULL;		/* Unsupported architecture. */    }    if (arch != NULL)	*arch = architecture;    if (!ReadFieldList(&list, architecture, file))	return NULL;    return list;}/* * Retrieve a pointer "hd_ptr" to an "esignal_hd" structure that has * been converted to long and added as a generic to a ESPS header by * code like the following: * *   *add_genhd_l("esignal_hd_ptr", (long *) NULL, 1, hdr) = (long) hd_ptr; * * where "hd_ptr" has type (esignal_hd *) (as in "esignal_to_fea" * above).  Return the pointer, or NULL if the input is NULL. */esignal_hd *get_esignal_hdr(struct header *hdr){    long    gen;    if (hdr == NULL)	return NULL;    else    {	gen = get_genhd_val_l("esignal_hd_ptr", hdr, 0L);	if (gen == 0)	    return NULL;	else	    return (esignal_hd *) gen;    }}/* * Get the size, in bytes, of a record of a file in an Esignal external * format.  This is the value stored in the rec_size member of the * esignal_hd structure after checking consistency of the value in the * preamble with the result of RecordSize.  This value is -1 for Esignal * files with variable-sized records.  The return value is also -1 in case * of error (NULL argument), though size_rec and size_rec2 won't call * this function in that case. *//*!*//* Current ESPS and waves don't check for the -1 return from * size_rec or size_rec2.  Check all uses of those functions. * Put a note in the man page. */longesignal_rec_size(esignal_hd *esig_hd){    if (esig_hd == NULL)    {	DebugMsg(1, "esignal_rec_size: Esignal header pointer is NULL.");	return -1;    }    return esig_hd->rec_size;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?