esignal_fea.c

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

C
1,315
字号
/* * Skip forward "nrec" records in a file "strm" in the Esignal external * format specified by the field list and other header information in the * esignal_hd structure indicated by "esig_hd".  For fixed-sized records, * just use the ESPS function "skiprec".  For variable-sized records * (indicated by a return of -1 from esignal_rec_size) read and discard * records one at a time. */voidesignal_skip_recs(FILE *strm, long nrec, esignal_hd *hd){    long	size;    if (hd == NULL)    {	DebugMsg(1, "esignal_skip_recs: Esignal header pointer is NULL.");	return;    }    if (nrec == 0)	return;    size = hd->rec_size;    if (size != -1)	skiprec(strm, nrec, (int) size);    else    {	FieldSpec   **lin_list = hd->lin_list;	int	    arch = hd->arch;	int	    i;	if (nrec < 0)	    DebugMsg(1, "esignal_skip_recs: "		     "Can't back up in file with variable record size.");	/* Avoid reading to possibly freed memory. */	for (i = 0; lin_list[i]; i++)	    lin_list[i]->data = NULL;/*!*//* Consider using ReadSamples when possible */	for ( ; nrec > 0 && ReadRecord(lin_list, arch, strm); nrec--)	{ }	if (nrec > 0)	    DebugMsg(1, "esignal_skip_recs: ReadRecord failed.");    }}/* * Read a record from an Esignal file and store the contents (or some * of the contents) in an ESPS FEA record structure.  The file "file" * should be in Esignal format and positioned at the beginning of the * record to be read, and "rec" should point to the record structure. * The argument "hd" should point to an esignal_hd structure such as * "esignal_to_fea" creates when reading the Esignal file header. * The argument "fea_hd" should point to an ESPS FEA header structure * whose fields correspond in name, data type, rank, and dimensions * to some of the REQUIRED fields of the Esignal file.  (Such a header * is returned by "esigal_to_fea".)  The record record structure must * be compatible with the FEA header.  The typical sequence of events * is: * *	fea_hd = esignal_to_fea( ..., file); *	hd = get_esignal_hdr(fea_hd); *	rec = allo_fea_rec(fea_hd); * * followed by a loop that repeatedly executes: * *	esignal_get_rec(rec, hd, fea_hd, file); *  * The contents of Esignal fields that do not correspond to fields in * the FEA header are read and discarded.  The function returns 1 upon * success and EOF upon error or end of file. *//*!*//* MEMORY LEAK: if the Esignal file contains fields of type ARRAY, * memory for the contents will be allocated and abandoned unfreed. * Should save a list of such fields and free them, or make provisions * not to create the array values in the first place. */intesignal_get_rec(struct fea_data	*rec,		esignal_hd	*hd,		struct header	*fea_hd,		FILE		*file){    if (!rec || !hd || !file)    {	DebugMsg(1, "esignal_get_rec: NULL argument.");	return EOF;    }    /* Setup code to make the "data" members of the field specs of the     * fields to be read point to the right locations in the FEA     * record to receive the data.  Since get_fea_rec for a given     * input file is typically called repeatedly with the same     * fea_data structure, we want to avoid repeating the setup for     * every call.  We save a copy of *rec (i.e. the actual data pointers     * in the fea_data structure, not the pointer "rec") and a pointer     * to the "tag" member.  If these pointers are unchanged from     * the previous call we skip the setup.     * Things will BREAK if the contents of the "data" member of an input     * field spec are changed.  Code that does so should first null out     * "fea_tag_ptr" or part of "fea_rec" in the esignal_hd structure     * so that the next call of this function will redo the setup.     * Cf. "esignal_getsd_recs".     */    /* Here we rely on the fact that the data pointers in a fea_data     * structure comprise the part following the tag, which is a long     * and is the first member.     */    if (hd->fea_tag_ptr != &rec->tag	|| memcmp((char *) &hd->fea_rec + sizeof(long),		  (char *) rec + sizeof(long),		  sizeof(struct fea_data) - sizeof(long)))    {	FieldSpec	    *fld;	int		    i, fld_count;	char		    *name, **fld_names;/*!*//* Essentially the same code near the end of FieldList_to_fea  * (this file and esig2fea.c).  Consolidate?  */	hd->fea_tag_ptr = &rec->tag;	hd->fea_rec = *rec;	if (fea_hd->common.tag)	{	    fld = FindField(hd->lin_list, ESPS_TAG);	    fld->data = &rec->tag;	}	fld_count = fea_hd->hd.fea->field_count;	fld_names = fea_hd->hd.fea->names;	for (i = 0; i < fld_count; i++)	{	    name = fld_names[i];	    fld = FindField(hd->lin_list, name);	    fld->data = get_fea_ptr(rec, name, fea_hd);	}    }    if (ReadRecord(hd->lin_list, hd->arch, file))	return 1;    else	return EOF;}/* * Read sampled data from an Esignal file and store the samples in a buffer * array.  The file "file" should be in Esignal format and positioned at * the beginning of the sequence of records to be read, and "buffer" * should point to the beginning of the buffer array.  The number of * records be read is given by "num_records".  The argument "hd" * should point to an esignal_hd structure such as "esignal_to_fea" * creates when reading the Esignal file header.  If the file has just * one REQUIRED field, and no OPTIONAL fields, the contents of that field * are read.  If it has more than one field, one field must be named * "samples", and its contents are used; the contents of other fields are * discarded.  The number of records actually read is returned; this * will be less than "num_records" in case of error or end of file. */longesignal_getsd_recs(char		*buffer,		   long		num_records,		   esignal_hd	*hd,		   FILE		*file){    FieldSpec   **lin_list;    int		arch;    if (buffer == NULL || hd == NULL || file == NULL)    {	DebugMsg(1, "esignal_getsd_recs: NULL arguments.");	return 0;    }    if (num_records == 0)	return 0;    lin_list = hd->lin_list;    if (lin_list == NULL)    {	DebugMsg(1, "esignal_getsd_recs: no fields to be read.");	return 0;    }    arch = hd->arch;        if (hd->one_fld)		/* Can read with ReadSamples. */    {	return ReadSamples(buffer, num_records, lin_list, arch, file);    }    else			/* Read single records repeateldy. */    {	FieldSpec   *spec;	long	    step;	long	    num_read;		/*	 * We are about to invalidate hd->fea_rec by changing the "data"	 * pointer in a field spec that may point into the fea_data	 * structure.  (See comment in esignal_get_rec.)  Null part of	 * hd->fea_rec to avoid fouling up the next call of esignal_get_rec.	 */	hd->fea_tag_ptr = NULL;	hd->fea_rec.d_data = NULL;	spec = FindField(hd->fields, "samples");	if (spec == NULL)	{	    DebugMsg(1, "esignal_getsd_recs: "		     "couldn't find field \"samples\".");	}	spec->data = buffer;	step = InternTypeSize(spec->type);    	for (num_read = 0;	     num_read < num_records && ReadRecord(lin_list, arch, file);	     num_read++, spec->data = (char *) spec->data + step)	{ }	return num_read;    }}/* LOCAL FUNCTION DEFINITIONS *//* * Similar to ReadPreamble, but takes input from a character string in * memory instead of a file.  Return Esignal preamble information via * pointer arguments.  Return TRUE on success, FALSE on failure. */static intGetPreamble(char    **version,	/* version (output) */	    char    **arch,	/* architecture (output) */	    long    *pre_size,	/* preamble size (output) */	    long    *hdr_size,	/* header size (output) */	    long    *rec_size,	/* record size (output) */	    char    *str)	/* start of input characters */{    char	    buf[PREAM_MAX + 1]; /* preamble line + null */    /* Check magic number, MAGIC. */    if (!GetLine(buf, 8, &str))	return FALSE;    if (strcmp(buf, MAGIC) != 0)	return FALSE;    if (!GetLine(buf, 8, &str))	return FALSE;    if (version != NULL)	*version = StrDup(buf);    /* Get architecture. */    if (!GetLine(buf, 8, &str))	return FALSE;    if (arch != NULL)	*arch = StrDup(buf);    /* Get preamble size */    if (!GetLong(pre_size, 8, &str))	return FALSE;    /* Could check *pre_size here. */    /* Get header size */    if (!GetLong(hdr_size, 8, &str))	return FALSE;    /* Get record size */    if (!GetLong(rec_size, 8, &str))	return FALSE;    return TRUE;		/* success */}/* * Extract a line of length len (including '\n') into buf from * the string indicated by the variable whose addresss is "src". * Increment the variable to point to the next character after * the extracted substring. * Check length of line, presence of terminating newline, * and absence of trailing blanks. * Trim newline and leading blanks and supply terminating null. * Return TRUE on success, FALSE on failure. * This is like the function "GetLine" in esignal.c, but takes * characters from a string in memory rather than a file. */static intGetLine(char    *buf,	int     len,	char    **src){    int		i, j;    if (src == NULL || *src == NULL)	return FALSE;    memcpy(buf, *src, (size_t) len);    buf[len] = '\0';    *src += len;    if (strlen(buf) != len || buf[len-1] != '\n')	return FALSE;    buf[len-1] = '\0';    /* count leading blanks */    for (j = 0; buf[j] == ' '; j++)    { }    if (j < len - 1 && buf[len-2] == ' ')	return FALSE;		/* not right justified */    if (j == 0)	return TRUE;    /* remove leading blanks */    for (i = 0; buf[j] != '\0'; i++,j++)	buf[i] = buf[j];    buf[i] = '\0';    return TRUE;		/* success */}/* * Extract a line of length len (including '\n') from the string * indicated by the variable whose addresss is "src".  Increment the * variable to point to the next character after the extracted * substring.  Check length of line and presence of terminating * newline.  Convert to long integer, assign result through pointer * "val" if non-NULL.  Check for garbage characters following the * constant.  Return TRUE on success, FALSE on failure. */static intGetLong(long    *val,	int     len,	char    **src){    char    *buf;    char    *ptr;		/* end-of-scan pointer from strtol */    long    value;		/* converted value */    buf = (char *) malloc(len+1);   /* len + 1 for terminating null */    if (buf == NULL)	return FALSE;		/* Allocation failure. */    /* Get line; check length. */    if (src == NULL || *src == NULL)	return FALSE;    memcpy(buf, *src, (size_t) len);    buf[len] = '\0';    *src += len;    if (strlen(buf) != len || buf[len-1] != '\n')    {	free(buf);	return FALSE;    }    /* Convert; check for bad format. */    value = strtol(buf, &ptr, 10);    if (ptr != buf + (len-1))    {	free(buf);	return FALSE;    }    /* Clean up; return. */    free(buf);    if (val != NULL)	*val = value;    return TRUE;		/* success */}/*!*//* The functions "FieldList_to_fea", "FindStr", "StrArrayFromRect", * "FieldIsTag", "FieldIsFeaSubtype", and "ElibTypeToEsps" are verbatim * copies of functions in esig2fea.c (except for the conditions that * control printing of debug messages).  Move to a separate file that * can be shared by the ESPS library and esig2fea. *//* * Convert an Esignal field list "list" to an ESPS FEA file header * that contains, generally speaking (1) a field definition for each * top-level REQUIRED field whose type corresponds to a possible FEA * field data type, and (2) a generic header item for each top-level * GLOBAL field whose type corresponds to a possible ESPS generic * header-item data type.  However, if "fnames" is non-NULL, it is a * NULL-terminated string array that specifies names of a subset of * the REQUIRED and GLOBAL fields to be represented in the output; * other fields in "list" are ignored.  If "copy_sources" is TRUE, * VIRTUAL fields in "list" with names of the form "source_<n>", are * translated into embedded source headers in the resulting FEA * header; otherwise the FEA header contains no embedded headers.  The * return value is a pointer to the ESPS header, or NULL in case of * error.  If "rec" is non-NULL, it gives the address of a variable in * which to return a pointer to an ESPS fea_data structure allocated * by calling "allo_fea_rec" on the returned header.  In the Esignal * REQUIRED field specs that correspond to FEA fields in the ESPS * header, the "data" members are made to point to corresponding * locations in the fea_data structure (found with "get_fea_ptr"), so * that calling ReadRecord will read a record in Esignal format and * store valuse from its REQUIRED fields appropriately in the fea_data * structure.

⌨️ 快捷键说明

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