⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 foo1

📁 speech signal process tools
💻
📖 第 1 页 / 共 3 页
字号:
       The type-specific portion of the	header is provided by a	union _h_d that       contains	 pointers to each possible type-specific structure.  They are       declared	in a union so that additional pointers can be  added  in  the       future  without	affecting  existing data files (since the size of the       pointers	themselves are the same).   Programmers	 can  tell  which  of       these  pointers	to  use	 by checking the item head->common.type.  The       pointer names are given in the following	table:		   _____________________________________________		   _|V_a_l_u_e__o_f____c__o__m__m__o__n__.__t__y__p__e___P_o_i_n_t_e_r__i_n____h__d_t_o__u_s_e__|		   |FT_SD		   _h_d_._s_d		|		   |FT_SPEC		   _h_d_._s_p_e_c		|		   |FT_FILT		   _h_d_._f_i_l_t		|		   |FT_SCBK		   _h_d_._s_c_b_k		|		   |FT_FEA		   _h_d_._f_e_a		|		   _|____________________________________________|       For example, the	sampling frequency from	the header of an  (old-style)       SD file is head->hd.sd->sf.       5 .1 .1 .  NIST (Sphere)	Headers       ESPS programs can read sample data files	containing  the	 NIST  Shpere       header  (such  as found on the TIMIT CD-ROM database).  This is imple-       mented by having	the ESPS file header access routines, detect an	input       file containing a NIST header and build an ESPS FEA_SD header from it.       All header information in the NIST header is saved as  generic  header       items in	the ESPS header.       Version 3.4			ERL			      9/11/91       ETM-S-86-13:rap/jtb					       page 7       5 .1 .2 .  Foreign Headers       It is often desirable to	maintain an existing file header  even	if  a       file  is	 converted to ESPS.   The non-ESPS header is called a foreign       header and it can be stored in the file between the  ESPS  header  and       the first data record.       Foreign headers are kept	in the ESPS header in the  following  manner:       The generic header item _f_o_r_e_i_g_n__h_d__l_e_n_g_t_h contains the size (in bytes)       of the foreign header.	If  this  item	is  present  (and  non-zero),       _r_e_a_d__h_e_a_d_e_r()  will  read  this	many additional	bytes of data, put it       into  the  header,  and	set  an	 additional   generic	header	 item       _f_o_r_e_i_g_n__h_d__p_t_r to point to it.  From that point on, the foreign header       is just part of the ESPS	header.       With this mechanism, it is possible to write  programs  that  use  the       ESPS  header and	record I/O functions while still having	access to the       foreign header.	The procedure is simple: use  _r_e_a_d__h_e_a_d_e_r()  to	 read       the  ESPS  header,  and	_g_e_t__g_e_n_h_d() to get the pointer to the foreign       header.       The conversion programs _b_t_o_s_p_s and _a_d_d_f_e_a_h_d would usually be  used  to       create such files.   See	reference [7].       5 .2 .  Header Access Routines       There are several ESPS library routines that  support  access  to  the       ESPS  data file headers.	These are described in detail in Section 3 of       [1].   Declarations   for   all	 these	 functions   are   found   in       <_e_s_p_s/_h_e_a_d_e_r._h>;	 the programmer	need not declare them if this file is       included.       The _r_e_a_d__h_e_a_d_e_r routine attempts	to read	a file header from  a  stream       (the  fd	 parameter  is typically one from a "fopen" call).  If an I/O       error occurs _r_e_a_d__h_e_a_d_e_r	returns	NULL. If the file does not begin with       a  valid	 ESPS  header,	then  _r_e_a_d__h_e_a_d_e_r  will	determine if the file       begins with a NIST header.  If a	NIST header is present,	then a FEA_SD       header is generated and filled in with the appropriate values from the       NIST header (sample rate, minimum  and  maximum	sample	values,	 data       type, etc).   _R_e_a_d__h_e_a_d_e_r then returns a	pointer	to this	FEA_SD header       in the usual way.  Programs which called	_r_e_a_d__h_e_a_d_e_r on	a  NIST	 file       will  operate  normally	and not	know that the file wasn't initially a       normal ESPS file.  If neither a valid ESPS header, or a NIST header in       present,	then _r_e_a_d__h_e_a_d_e_r will check for	the _u_n_i_x environment variable       DEF_HEADER.  If it is defined and points	to a file  containg  a	valid       ESPS  header,  then  that header	is used	instead.  If all of the	above       attempts	to find	a header fail, then NULL is returned.  Memory for the       file  header  is	 allocated  from  dynamic  memory.  After _r_e_a_d__h_e_a_d_e_r       returns,	the program should consult _c_o_m_m_o_n._t_y_p_e to determine the	 type       of the header that has been returned.       The _w_r_i_t_e__h_e_a_d_e_r	routine	attempts  to  write  a	file  header  onto  a       stream.	 It  computes  and  fills in values for	hsize, fixsiz, check,       Version 3.4			ERL			      9/11/91       ETM-S-86-13:rap/jtb					       page 8       date, and hdvers	and ensures that must-be-zero fields contain zero, by       clearing	 them.	 If an I/O error occurs, _w_r_i_t_e__h_e_a_d_e_r writes an	error       message and the program bombs.       The _n_e_w__h_e_a_d_e_r routine allocates	a new header from dynamic memory  and       returns	a  pointer  to	it.   Which type-specific header is allocated       depends on the value of the argument _t_y_p_e.    If	_t_y_p_e is	zero, then no       type-specific  header  is  allocated,  only the common part is.	 This       case is intended	for use	by the header access programs.       The _c_o_p_y__h_e_a_d_e_r routine accepts a pointer to a file header and returns       a  copy	of  the	 same  type in which all items except common.comment,       common.prog,   common.vers,    common.date,    common.progdate,	  and       common.hdvers  are  copied  from	the source header.  This routine par-       tially generates	a header for an	output file, given a  header  for  an       input  file  (any changed parameters must be filled in, along with the       program name and	version).  It is important to realize that this	func-       tion  can only be used when the output file is of the same type as the       input file.       The _a_d_d__s_o_u_r_c_e__f_i_l_e routine inserts a source file name and header into       the next	available positions in a header. The nnames and	nheads fields       are incremented.	Strictly speaking, only	pointers are copied,  so  the       source parameters must not be altered before _w_r_i_t_e__h_e_a_d_e_r is called.       The _a_d_d__c_o_m_m_e_n_t routine appends a character string  onto	 the  comment       field  of  a  header.   For  example,  with  the	 help of _g_e_t__c_m_d__l_i_n_e       (3-ESPS), the command line is added as a	comment. All ESPS programs by       convention add the command line as a comment in the output header.       For creating _z_f_u_n_c structures, the function _n_e_w__z_f_u_n_c is	supplied.  It       allocates  dynamic memory, builds a new zfunc structure,	and returns a       pointer to it. The zeros	and poles are also copied to dynamic  memory.       To  assist  in  storing	_z_f_u_n_cs	as generic header items	the functions       _a_d_d__g_e_n_z_f_u_n_c and	_g_e_t__g_e_n_z_f_u_n_c are provided.       Generic	header	items  are  added  to  an  existing  header  by	  the       _a_d_d__g_e_n_h_d_X (3-ESPS) routines ("X" stands for one of six	possible data       types).	Other generic-related header access routines are  _g_e_n_h_d__l_i_s_t,       which  returns a	list of	the defined generic header items, _g_e_n_h_d__t_y_p_e,       which returns  the  type	 of  a	specific  generic  header  item,  and       _g_e_t__g_e_n_h_d,  which returns a pointer to a	specific generic header	item.       These routines make it possible for programs to	process	 the  generic       header  items  in  ESPS	files without having to	know what they are in       advance.       5 .2 .1 .  Using	the Header Access Routines       The header access routines are easy to use.   The important  thing  to       remember	 is  that,  before _w_r_i_t_e__h_e_a_d_e_r	is called, _a_l_l _v_a_l_u_e_s _m_u_s_t _b_e       _s_e_t _i_n _t_h_e _h_e_a_d_e_r.  The easiest error  is  to  confuse  pointers	 that       might  be in use	pointing to several different headers, most often the       input and the output file.  The basic model of  use  is	to  open  the       Version 3.4			ERL			      9/11/91       ETM-S-86-13:rap/jtb					       page 9       input  file  and	call _r_e_a_d__h_e_a_d_e_r on this file.	This allocates memory       for the input file header, checks the header on the  input  file,  and       reads to	its end.  The next read	on this	file will return data, rather       than header, values.       If _r_e_a_d__h_e_a_d_e_r returns without error, then it has found a  valid	 ESPS       header.	   The	program	 should	now check _c_o_m_m_o_n._t_y_p_e to be sure that       the file	is of the type expected	by the program.	 If it is  not,	 then       an  error message should	be printed and the program should exit with a       non-zero	exit code (standard convention is to  use  exit(1)).	 Some       programs	 may  accept  several  (or any)	of the valid ESPS file types.       These programs should still consult  _c_o_m_m_o_n._t_y_p_e	 to  determine	which       pointer	in  the	union _h_d to use.    The	use of the wrong pointer will       cause unpredictable results (most often	a  harmless  bus  error,  but       worse could happen).       Since _r_e_a_d__h_e_a_d_e_r returns a pointer to the main	header	structure,  a       pointer must be declared	before _r_e_a_d__h_e_a_d_e_r is called:	   struct header *h;	   .	   .	   .	   h = read_header(file);       After the call to _r_e_a_d__h_e_a_d_e_r, items in the header  may	be  accessed.       Here are	some examples:	   char	*ref_file;	   float frequency, avg_zero;	   .	   .	   .	   if (h->common.type == FT_SD)	{      /*verify	file type*/	       fprintf(stderr, "Input file is not an SD	file.0);	       exit(1)	   }	   ref_file = h->variable.refer;       /*get name of reference file for	tags*/	   frequency = h->hd.sd.sf;	       /*sampling frequency of data*/	   avg_zero = *(float *) get_genhd("zero_crossing", h);       In some	ESPS  programs	(especially  newer  programs),	the  call  to       _r_e_a_d__h_e_a_d_e_r  and	the file type checking is done within a	library	func-       tion _e_o_p_e_n, which also opens the	file.  An example of  this  is	given       later.       If the output file of the program is the	same type as the  input	 file       then  _c_o_p_y__h_e_a_d_e_r  is useful for	creating the header of the new output       file and	filling	in most	values from the	input file.   Some  of	these       values  might have to be	changed	before _w_r_i_t_e__h_e_a_d_e_r is called, but in       many cases, the header of an output file	is  much  like	that  of  its       input  file.  If	the output file	is of a	different type than the	input       Version 3.4			ERL			      9/11/91       ETM-S-86-13:rap/jtb					      page 10       file, or	the programmer decides that none or very few values  will  be       in common, then _n_e_w__h_e_a_d_e_r should be used to create the header for the       new output file.	 A type	code must be  specified	 when  _n_e_w__h_e_a_d_e_r  is       called.	In either case,	when creating an output	ESPS file from source       ESPS files, the source headers should  be  saved	 in  the  new  output       header.	 This is done by calling _a_d_d__s_o_u_r_c_e__f_i_l_e.  Here	is an example       of reading values from the header of an input file, and	creating  and       writing an output file header.	   char	*speaker_name;	   float samp_freq, zero_crossing, *coh_thresh;	   long	num_samples;	   .	   .	   .	   ih =	read_header(in_file);	       /* get input header */	   speaker_name	= (char	*) get_genhd("speaker",	ih);  /*generic	example*/	   .	   .	   .	   oh =	new_header(FT_FEA)	       /* create new output header */	   (void) add_source_file(oh,in_file,ih);	/* save	input header */	   oh->variable.refer =	ih->variable.refer;   /*same refer file*/	   /*add the command line as a comment*/	   add_comment(oh, get_cmd_line(argc, argv));	   (void) strcpy (oh->common.prog, progname);	   (void) strcpy (oh->common.vers, Version);	   /*add generic header	items*/	   (void)add_genhd_f("avg. zero	crossing", &zero_crossing, 1, ih)	   coh_thresh =	add_genhd_d("voicing threshold", (double *)NULL, 1, ih);	   .	   .	   .	   zero_crossing = . . .;	   *coh_thresh = . . .;	   (void) write_header(oh, ostrm);     /*ostrm is output file stream*/       The call	to _a_d_d__s_o_u_r_c_e__f_i_l_e results in the input	header	being  stored       on  the	new  output file.   This is done (within _a_d_d__s_o_u_r_c_e__f_i_l_e ) by       setting a pointer (_v_a_r_i_a_b_l_e._s_r_c_h_e_a_d)  to	 point	to  the	 old  header.       There is	a limit	to the number of headers that can be embedded in this       way.  It	is defined as MAX_SOURCES and its current value	can be	found       in  <_e_s_p_s/_h_e_a_d_e_r._h>.	The  header  item  _v_a_r_i_a_b_l_e._n_h_e_a_d_s  should be       checked before calling _a_d_d__s_o_u_r_c_e__f_i_l_e  if  the	programmer  wants  to       avoid  the chance of a run-time error because of	exceeding this limit.       Of course, if the header	is being stored	in a new header	and only once       in  the	program,  then it is safe to store a header without checking.       This is the case	in the above example.       The example above includes both	"styles"  of  adding  generic  header       items  -	 the  _a_d_d__g_e_n_h_d_X  routines can	either allocate	space for the       item and	return a pointer to it,	 or  accept  a	pointer	 to  existing       Version 3.4			ERL			      9/11/91       ETM-S-86-13:rap/jtb					      page 11       space.	Note that the actual values written out	to the header are the       values that exist when _w_r_i_t_e__h_e_a_d_e_r is called,  _n_o_t  the	 values	 that       exist  when  the	 _a_d_d__g_e_n_h_d_X routines are called.  Thus, in the	above       example,	the two	lines prior to the _w_r_i_t_e__h_e_a_d_e_r	 call  determine  the       values  written	to the corresponding generic header items.  There is,       however,	a "Hi-C" way to	guarantee  that	 the  value  written  to  the       header  is  fixed  at  the time of the call to _a_d_d__g_e_n_h_d_X routine, as       follows:	   *add_genhd_f("avg. zero crossing", NULL, 1, ih) = zero_crossing;       When writing programs that exploit the generic  header  items  in  the       input  ESPS files, it may be the	case that the presence of those	items       is useful but not essential.  In	such  cases,  care  should  be	taken       allow  the  program to run on ESPS files	that do	not have the required       gereric header items.  This can be accomplished by  using  _g_e_n_h_d__l_i_s_t,       or by checking for a NULL return	value from _g_e_t__g_e_n_h_d.       6 .  Data Structures       The data	structures for data records in the different  types  of	 ESPS       files  are  specified  in the Section 5 manual pages that describe the       file formats.  The general approach is to define	a  C  structure	 that       represents  one	data record in the file.  Access functions are avail-       able to support reading and writing such	records, so that  programmers       can  deal with the C structure and ignore the issue of how that struc-       ture is stored in the file.       6 .1 .  Data Access Routines       In general a function named _g_e_t_xx__r_e_c and one  named  _p_u_t_xx__r_e_c  are       provided	 to  get  and  put  records  from/onto	an ESPS	file type xx.       There is	also  n_a_l_l_o_xx__r_e_c function that  allocates  memory  for  one       record.	In  most  cases,  the size of certain elements of the record,       depend on values	in the file header.       For example, here is an example of reading a SPEC record:	   FILE	*ifile;

⌨️ 快捷键说明

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