copysd.c

来自「speech signal process tools」· C语言 代码 · 共 486 行

C
486
字号
/* * 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) 1986-1990  Entropic Speech, Inc.  *    "Copyright (c) 1990-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:  Alan Parker * Checked by: * Revised by:  David Burton, John Shore * * Brief description: copies FEA_SD records to new file (with type change) * */static char *sccs_id = "@(#)copysd.c	3.15	1/18/97	ESI/ERL";#define VERSION "3.15"#define DATE "1/18/97"/* * system and ESPS include files */#include <stdio.h>#include <esps/esps.h>#include <esps/fea.h>#include <esps/feasd.h>#include <esps/unix.h>#include <sys/param.h>/* * private definitions */#define SYNTAX \USAGE("copysd [-a add_constant] [-d data_type] [-g] [-o] [-{pr} range] [-s scale]\n\t[-x debug_level] [-S time_range] [file1 [file2 ...]] outfile")#define ERROR_EXIT(text) \{(void) fprintf(stderr, "copysd: %s - exiting\n", text); exit(1);}#define REQUIRE(test, text) {if (!(test)) ERROR_EXIT(text)}#define SIZE 8192		/* size of copy buffer */#define MAX_IN_FILES 100	/* max number of input files *//* * system functions and variables */extern int  optind;char *optarg;double fabs();/* * external ESPS functions */char *eopen();char *get_cmd_line();void lrange_switch(), trange_switch();double_cplx realmult();double_cplx realadd();/* * global declarations */void get_range();int debug_level = 0;/* * main program */main (argc, argv)int     argc;char  **argv;{    int     getopt(), c;		/* for option processing */    FILE    *out_fd;			/* output stream */    FILE    *in_fd[MAX_IN_FILES];	/* input streams */    struct header *oh;			/* output file header */    struct header *ih[MAX_IN_FILES];	/* input file headers */    char    *ofile;			/* output file name */    char    *in_files[MAX_IN_FILES];	/* input file names */    struct feasd *sd_rec;		/* fea_sd data record */    int     i, j;			/* loop variables */    int	    oflag = 0, dflag = 0,	/* option flags */ 	    pflag = 0, Sflag = 0,	    sflag = 0, aflag = 0,	    gflag = 0;    int	    nofile = 0;			/* set if no input file on cmd line */    long    s_rec, e_rec;		/* start, and end point */    long    lrec[MAX_IN_FILES];		/* actual end point for each file */    char    *range = NULL;		/* string from -r option */    short   type;			/* output data type */    char    combuf[100 + MAXPATHLEN];	/* string for comment */    double  scale = 1.0;		/* scale factor from -s option */    double  add_constant = 0;	        /* additive constant from -a option */    int	    havestdin = 0;		/* flag set when one input is stdin */    int	    nfiles;			/* number of input files */    int     n;				/* number points wanted from 					   call to get_sd_rec */    int	    n_read;			/* number points from get_sd_rec */    long    n_to_go;			/* number left in range */    int	    tot_rec = 0;		/* total records read (all files)*/    int	    tot_rec_file;		/* total records read (current file)*/    int	    nan_first;			/* number points copied from 1st file*/    double  first_sf;			/* samp. freq. of first input file */    double_cplx *cdata;			/* pointer to input data records */    short   in_type;			/* input type for file 1 */    int	    num_channels;		/* number of channels in input files */    double  start_time = 0;		/* waves generic */    char    data_type;			/* pointer for output data type *//* * process command line options */    while ((c = getopt(argc, argv, "a:d:op:r:s:x:S:g")) != EOF) {	switch (c) {	case 'a': 	    add_constant = atof (optarg);	    aflag++;	    break;	case 'd': 	    dflag++;	    data_type = optarg[0];	    if((type = (short)lin_search(type_codes, optarg)) == -1){		switch (data_type) {		case 'b':		    type = BYTE;		    break;		case 's':		    type = SHORT;		    break;                case 'l':		    type = LONG;		    break;		case 'f':		    type = FLOAT;		    break;                case 'd':		    type = DOUBLE;		    break;		default:		    Fprintf(stderr,			    "copysd: invalid output data type (%s) specified\n",			    optarg);                    exit(1);		}	    }	    break;	case 'o': 	    oflag++;	    break;	case 'p': 	case 'r': 	    range = optarg;	    pflag++;	    break;	case 's': 	    scale = atof (optarg);	    if (strchr(optarg, ':')) Fprintf(stderr, 		"copysd: WARNING - `:' in argument for scale option -s; maybe you want -S\n");	    sflag++;	    break;	case 'x': 	    debug_level = atoi(optarg);	    break;	case 'S': 	    range = optarg;	    Sflag++;	    break;	case 'g':	    gflag = 1;		/* copy all generics from first input file */	    break;	default:	    SYNTAX;	}    }/* * check for multiple range specifications */    if (pflag + Sflag > 1) {	ERROR_EXIT("range should only be specified once");    }/* Determine and open output file */    if (argc - optind < 1) {	Fprintf(stderr, "copysd: no output file specified.\n");	SYNTAX;    }    ofile = eopen("copysd", argv[argc - 1], "w", NONE, NONE, &oh, &out_fd);    if (debug_level)	Fprintf(stderr, "copysd: output file is %s\n", ofile);/* * Determine input files and check them -- start by getting the first  * one; at the same time, we set up to create the output header */    if (argc - optind < 2) {	nofile = 1;  	in_files[0] = NULL;	if (debug_level)	    Fprintf(stderr, "copysd: no input file on command line\n");    }    else {	in_files[0] = eopen("copysd", argv[optind], "r", FT_FEA, FEA_SD, 	    &ih[0], &in_fd[0]);	optind++;	    }    /*     *  If command line has no input file name, then it might be in     *  ESPS common; we need to read_params anyway (provided stdin not     *  used), so we do it here (checking common only); However,     *  we don't check common if more than one input file is given     *  since this is error prone.       */    if (nofile || ((in_fd[0] != stdin) && (argc - optind < 2))) {	if (debug_level)	    Fprintf(stderr, "copysd: checking ESPS common\n");    	(void) read_params((char *)NULL,SC_CHECK_FILE,in_files[0]);	    }    if (nofile) {	if (symtype("filename") == ST_UNDEF) {	    ERROR_EXIT("no input file name on command line or in common");	}	else {	    if (debug_level)		Fprintf(stderr, 		    "copysd: input file name from common is %s\n",		    getsym_s("filename"));	    if (strcmp(ofile, getsym_s("filename")) == 0)		ERROR_EXIT("input name from common same as output file");	    in_files[0] = eopen("copysd", getsym_s("filename"), "r", 		FT_FEA, FEA_SD, &ih[0], &in_fd[0]);	}    }    if (in_fd[0] == stdin) havestdin = 1;    if (debug_level) 	Fprintf(stderr, "copysd: first input file is %s\n", in_files[0]);/* * create and write output header */    num_channels =          get_fea_siz("samples", ih[0], (short *) NULL, (long **) NULL);    first_sf = get_genhd_val("record_freq", ih[0], -1.0);    oh = new_header(FT_FEA);    (void) strcpy(oh->common.prog, "copysd");    (void) strcpy(oh->common.vers, VERSION);    (void) strcpy(oh->common.progdate, DATE);    oh->common.tag = NO;    in_type = get_fea_type("samples", ih[0]);    if (!oflag) add_source_file(oh, in_files[0], ih[0]);    if (aflag)         *add_genhd_d("add_constant", (double *) NULL, 1, oh) = add_constant;    if (sflag)         *add_genhd_d("scale_factor", (double *) NULL, 1, oh) = scale;    /*     * Now open the rest of the input files and process headers     */    nfiles = 1;    while(optind < argc - 1) {	in_files[nfiles] = eopen("copysd", argv[optind], "r", FT_FEA, FEA_SD, 	    &ih[nfiles], &in_fd[nfiles]);	if (debug_level) 	    Fprintf(stderr, "copysd: input file is %s\n", in_files[nfiles]);	if (in_fd[nfiles] == stdin) {	    if (havestdin) {		 ERROR_EXIT("only one stdin allowed");	    }	    else		havestdin = 1;	}	/*	 * Check input files for consistency	 */	if (get_fea_siz("samples", ih[nfiles], (short *) NULL, (long **) NULL)	    != num_channels)	{	    Fprintf(stderr, 		    "copysd: all files must have same number of channels\n");    	    Fprintf(stderr,		    "   first file has %d channels, %s has %d\n",		    num_channels, in_files[nfiles],		    get_fea_siz("samples",				ih[nfiles], (short *) NULL, (long **) NULL));	    exit(1);        } 	if (get_genhd_val("record_freq", ih[nfiles], 0.0) != first_sf) {    	    Fprintf(stderr,		    "copysd: all files must have same sampling frequency\n");    	    Fprintf(stderr,		    "   freq. in first file is %g, freq. in %s is %g\n",		    first_sf, in_files[nfiles],		    get_genhd_val("record_freq", ih[nfiles], 0.0));	    exit(1); 	}	if (!oflag) add_source_file(oh, in_files[nfiles], ih[nfiles]);	optind++;	nfiles++;	if (nfiles > MAX_IN_FILES) 	    ERROR_EXIT("can't handle more than %d files");    }    add_comment (oh, get_cmd_line(argc,argv));    /*     * determine range of records to copy     */    get_range(&s_rec, &e_rec, range, pflag, Sflag, ih[0]);     if (debug_level) Fprintf(stderr,  	 "copysd: full range is %ld to %ld\n", s_rec, e_rec);    /*     * determine copy range for each file and add comments accordingly;     * can do this exactly for each file that's not a pipe;     * at the same time, fill out start and nan based on first file     */    for (i=0; i < nfiles; i++) {	lrec[i] = e_rec;	if (ih[i]->common.ndrec > -1) {	    /*	     * not a pipe and record length fixed---can count on common.drec	     */	    if (lrec[i] > ih[i]->common.ndrec) 		lrec[i] = ih[i]->common.ndrec;	    if (s_rec > lrec[i]) Fprintf(stderr, 		"copysd: WARNING - no records in range for file %s\n",		in_files[i]);	}   /* else it's a pipe, or record length is variable---	     * go with e_rec, whatever it is	     */	(void) sprintf(combuf, "  Copied from %s, records %ld to %ld\n",		       in_files[i], s_rec, lrec[i]);	add_comment (oh, combuf);	if (debug_level)	    Fprintf(stderr, "copysd: range for %s is %ld to %ld\n", 			    in_files[i], s_rec, lrec[i]);    }    /*     * Allocate data record and set up pointer---same for all input files.     * This depends on the fact that nothing in the feasd record structure     * except the number of channels depends on the header, and we have     * checked that all the headers have the same number.     */    sd_rec = allo_feasd_recs(ih[0], DOUBLE_CPLX,			     (long) SIZE, (char *) NULL, NO);    cdata = (double_cplx *) sd_rec->data;    /*     * write the header     */    if (!dflag)	type = in_type;    REQUIRE(init_feasd_hd(oh, type,			  num_channels, &start_time, NO, first_sf) == 0,	    "Couldn't initialize output FEA_SD header")    if (gflag)	copy_genhd(oh, ih[0], NULL);    (void) update_waves_gen(ih[0], oh, (float)s_rec, (float)1);    write_header(oh, out_fd);/* * copy records from each input file */    for (i=0; i < nfiles; i++) {	if (debug_level)	    Fprintf(stderr, "copysd: copying file %s\n", in_files[i]);	tot_rec_file = 0;	(void) fea_skiprec (in_fd[i], s_rec - 1, ih[i]);	n = SIZE;	n_to_go = lrec[i] - s_rec + 1;	if (debug_level > 2)	    Fprintf(stderr, 		"copysd: need total of %ld in chunks of %d\n", n_to_go, SIZE);	while (n_to_go > 0)	{	    long    num_elements;	    if (n_to_go < n)		n = n_to_go;	    n_read = get_feasd_recs(sd_rec, 0L, (long)n, ih[i], in_fd[i]);	    if (debug_level > 2) 		Fprintf(stderr, 		    "copysd: asked for %ld samples, got %ld\n", n, n_read);	    if (n_read == 0) /*read all there is to read*/		break;	    num_elements = n_read * num_channels;	    if (sflag && aflag)		for (j = 0; j < num_elements; j++)		    cdata[j] = realadd(realmult(cdata[j], scale), add_constant);	    else if (sflag) 		for (j = 0; j < num_elements; j++)		    cdata[j] = realmult(cdata[j], scale);	    else if (aflag)		for (j = 0; j < num_elements; j++)		    cdata[j] = realadd(cdata[j], add_constant);	    REQUIRE(put_feasd_recs(sd_rec,				   0L, (long) n_read, oh, out_fd) == 0,		    "Couldn't write output data record")	    n_to_go -= n_read;	    tot_rec_file += n_read;    	    if (debug_level > 2)		Fprintf(stderr, 		    "copysd: %ld records so far, %ld to go\n",		    tot_rec_file, n_to_go);	    if (n_read < n) /*read all there is to read*/		break;	}	if (i == 0) nan_first = tot_rec_file;	tot_rec += tot_rec_file;	if (debug_level > 1) {	    Fprintf(stderr, 		    "copysd: copied %ld total records from file %s\n", 		    tot_rec_file, in_files[i]);	    Fprintf(stderr, 		    "copysd: grand total records so far = %ld\n", tot_rec);	}    	if (tot_rec_file == 0) Fprintf(stderr, 	    "copysd: WARNING - no records copied for file %s\n", in_files[i]);    }    (void) fclose (out_fd);/* * put output file info in ESPS common */    if (strcmp(ofile, "<stdout>") != 0) {	(void)putsym_s("filename",in_files[0]);        (void)putsym_s("prog",argv[0]);        (void)putsym_i("start",(int)s_rec);        (void)putsym_i("nan",(int) nan_first);    }    if (debug_level) Fprintf(stderr, "copysd: normal exit\n");    exit(0);}voidget_range(srec, erec, rng, pflag, Sflag, hd)/* * This function facilitates ESPS range processing.  It sets srec and erec * to their parameter/common values unless a range option has been used, in * which case it uses the range specification to set srec and erec.  If * there is no range option and if start and nan do not appear in the * parameter/common file, then srec and erec are set to 1 and LONG_MAX. * Get_range assumes that read_params has been called; If a command-line * range option (e.g., -r range) has been used, get_range should be called * with positive pflag and with rng equal to the range specification. */long *srec;			/* starting record */long *erec;			/* end record */char *rng;			/* range string from range option */int pflag;			/* flag for whether -r or -p used */int Sflag;			/* flag for whether -S used */struct header *hd;		/* input file header */{    long common_nan;    *srec = 1;    *erec = LONG_MAX;    if (pflag) 	lrange_switch (rng, srec, erec, 1);	    else if (Sflag) 	trange_switch (rng, hd, srec, erec);	    else {	if(symtype("start") != ST_UNDEF) {	    *srec = getsym_i("start");	}	if(symtype("nan") != ST_UNDEF) {	    common_nan = getsym_i("nan");	    if (common_nan != 0) 		*erec = *srec + common_nan - 1; 	}    }}

⌨️ 快捷键说明

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