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 + -
显示快捷键?