bs_dist.c

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

C
1,029
字号
/* * 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) 1998 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:  Rod Johnson * Checked by: * Revised by: * * Brief description: *   compute Bark spectral distortion * * Ref:  S. Wang, A. Sekey, & A. Gersho, IEEE J Select Areas in Comm, * v.10, n.5 (June 1992) 819-829. */static char *sccs_id = "@(#)bs_dist.c	1.2	9/2/98	ERL";/* INCLUDE FILES */#include <stdlib.h>#include <math.h>#include <esps/esps.h>#include <esps/fea.h>#include <esps/feaspec.h>#include <esps/constants.h>/* LOCAL CONSTANTS */#define VERSION	"1.2"		/* must be 7 char or less */#define DATE	"9/2/98"	/* must be 25 char or less */#define PROG	"bs_dist"	/* must be 15 char or less */#define LOG2_OVER_10  (0.0693147180559945309417)    /* log(2)/10.0 *//* LOCAL MACROS */#define SYNTAX \USAGE("bs_dist [-a] [-e threshold] [-m distortionType]\n" \      "\t[-{pr} range1 [-{pr} range2]] [-x debug_level] [-A] [-P paramFile]\n" \      "\tinFile1.spec inFile2.spec [outFile.fea]")#define ERROR(text) \{(void) fprintf(stderr, "%s: %s - exiting\n", PROG, (text)); exit(1);}#define REQUIRE(test, text) {if (!(test)) ERROR(text)}#define TRYALLOC(type, num, var, txt) \{if (((var) = (type *) malloc((num)*sizeof(type))) == NULL) \ {(void) fprintf(stderr, "%s: can't allocate memory--%s - exiting\n", \		 PROG, (txt)); exit(1);}}#define GET_GENHD_CODED(name, hd, var, txt) \{if (genhd_type((name), NULL, (hd)) != CODED) \ {(void) fprintf(stderr, "%s: header item \"%s\" in %s undefined or" \		 " wrong type - exiting\n", PROG, (name), (txt)); exit(1);} \ {(var) = *get_genhd_s((name), (hd));}}#define STRCMP(a, op, b) (strcmp((a), (b)) op 0)/* SYSTEM FUNCTIONS AND VARIABLES */extern int	getopt();		/* parse command options */extern int	optind;			/* used by getopt */extern char	*optarg;		/* used by getopt *//* ESPS FUNCTIONS AND VARIABLES */char		*get_cmd_line(int argc, char **argv);int		debug_level = 0;/* LOCAL TYPEDEFS AND STRUCTURES *//* This enum type is common to bs_dist and mbs_dist. * Keep them consistent. */typedef enum {    BSD = 1,    MBSD}		d_type;			/* cf. d_types below *//* LOCAL FUNCTION DECLARATIONS */void	print_farray(int filenum, long recnum,		     char *text, long numelem, float *data);					/* for debug printouts *//* STATIC (LOCAL) GLOBAL VARIABLES *//* This string array definition is common to bs_dist and mbs_dist. * Keep them consistent. */static char	*d_types[] = {    "NONE", "BSD",  "MBSD",    NULL};					/* cf. d_type above *//* MAIN PROGRAM */intmain(int   argc,     char  **argv){    int		    ch;			/* command-line option letter */    long	    i, j, k, n;		/* loop counters and array indices */    int		    a_specified = NO;	/* a-option specified? (output only					 * average final distortion with no					 * output file?) */    char	    *e_arg = NULL;	/* e-option argument */    double	    threshold;		/* frame power threshold */    int		    check_thresh;	/* check input frame powers against					 * threshold? */    char	    *m_arg = NULL;	/* m-option argument */    char	    *distypesym; 	/* param file entry for					 * distortion_type */     d_type	    distortion_type;	/* BSD or MBSD */    char	    *r_arg1 = NULL;	/* first r-option argument */    char	    *r_arg2 = NULL;	/* second r-option argument */    long	    startrec1;		/* first record to process from					 * first input file */    long	    startrec2;		/* first record to process from					 * second input file */    int		    startrecs[2]; 	/* startrec1 and startrec2 as					 * an array */    long	    nan;		/* number of records to process,					 * but 0 means range extends to					 * end of file */    int		    A_specified = NO;	/* A-option specified? (output					 * average final distortion?) */    char	    *param_name = NULL;	/* parameter file name */    char	    *inname1;		/* first input file name */    FILE	    *infile1;		/* first input stream */    struct header   *inhd1;		/* first input file header */    struct feaspec  *inrec1;		/* input FEA_SPEC record from first					 * input file */    float	    *inbuf1;		/* input buffer--data from inrec1 */    long	    *intag1;		/* pointer to tag in input record */    int		    freq_format1;	/* freq_format of first input file */    int		    spec_type1;		/* spec_type of first input file */    int		    contin1;		/* is first input spectrum a					 * continuous density? */    double	    src_sf1;		/* src_sf in first input file */    int		    tot_power_defined1;	/* tot_power field defined in					 * first input file? */    float	    *tot_power1;	/* pointer to tot_power field					 * in inrec1 */    int		    num_freqs1;		/* num_freqs in first input file */    short	    frame_meth1;	/* frame_meth in first input file */    double	    record_freq1;	/* record_freq in first input file */    float	    *freqs1;		/* freqs in first input file header */    char	    *inname2;		/* second input file name */    FILE	    *infile2;		/* second input stream */    struct header   *inhd2;		/* second input file header */    struct feaspec  *inrec2;		/* input FEA_SPEC record from second					 * input file */    float	    *inbuf2;		/* input buffer--data from inrec2 */    long	    *intag2;		/* pointer to tag in input record */    int		    freq_format2;	/* freq_format of second input file */    int		    spec_type2;		/* spec_type of second input file */    int		    contin2;		/* is second input spectrum a					 * continuous density? */    double	    src_sf2;		/* src_sf in second input file */    int		    tot_power_defined2;	/* tot_power field defined in					 * second input file? */    float	    *tot_power2;	/* pointer to tot_power field					 * in inrec2 */    int		    num_freqs2;		/* num_freqs in second input file */    short	    frame_meth2;	/* frame_meth in second input file */    double	    record_freq2;	/* record_freq in second input file */    float	    *freqs2;		/* freqs in second input file header */    int		    num_freqs;		/* number of frequencies used in					 * computation */    int		    tag_match;	 	/* are input files tagged files with					 * the same src_sf? */    int		    rec_freq_match;	/* do input files have the same					 * non-zero record_freq? */    float	    *log_wts;		/* perceptual log weights (in dB) for					 * converting from dB to phones */    float	    *p_wts;		/* log_wts values in linear form					 * rather than logarithmic (dB) */    double	    frame_distortion;	/* distortion for one frame */    double	    sum_distortion;	/* distortion summed over frames */    double	    norm;		/* normalizing factor for					 * overall average distortion */    char	    *outname;		/* output file name */    FILE	    *outfile;		/* output stream */    struct header   *outhd;		/* output file header */    struct fea_data *outrec;		/* output file record */    char	    *outfld;		/* name of frame distortion */    float	    *outdata;		/* pointer to frame distortion field					 * in output record */    long	    *outtag;		/* pointer to tag in output record */    long	    *start;		/* pointer to "start" in output hdr */    /*     * PARSE COMMAND-LINE OPTIONS.     */    while ((ch = getopt(argc, argv, "ae:m:p:r:x:AP:")) != EOF)	switch (ch) {	case 'a':	    a_specified = YES;	    break;	case 'e':	    e_arg = optarg;	    break;	case 'm':	    m_arg = optarg;	    break;	case 'p':	/* -p is a synonym for -r */	    /* FALL THROUGH */	case 'r':	    if (r_arg1 == NULL) {		r_arg1 = optarg;	    } else if (r_arg2 == NULL) {		r_arg2 = optarg;	    } else {		fprintf(stderr, "%s: too may -r options.\n", PROG);		SYNTAX;	    }	    break;	case 'x':	    debug_level = atoi(optarg);	    break;	case 'A':	    A_specified = YES;	    break;	case 'P':	    param_name = optarg;	    break;	default:	    SYNTAX;	    break;	}    /*     * PROCESS FILE NAMES.     */    if (argc - optind > (a_specified ? 2 : 3)) {	fprintf(stderr, "%s: too many file names.\n", PROG);	SYNTAX;    }    if (argc - optind < (a_specified ? 2 : 3)) {	fprintf(stderr, "%s: not enough file names.\n", PROG);	SYNTAX;    }    inname1 = argv[optind++];    inname2 = argv[optind++];    REQUIRE(STRCMP(inname1, !=, "-") || STRCMP(inname2, !=, "-"),	    "input files both standard input");    if (!a_specified) {	outname = argv[optind++];	if (STRCMP(outname, !=, "-")) {	    REQUIRE(STRCMP(inname1, !=, outname),		    "output file same as first input file");	    REQUIRE(STRCMP(inname2, !=, outname),		    "output file same as second input file");	}	if (A_specified) {	    REQUIRE(STRCMP(outname, !=, "-"),		    "-A specified, but output file is standard output");	}    }    /*     * OPEN AND CHECK INPUT FILES.     */    inname1 = eopen(PROG, inname1, "r", FT_FEA, FEA_SPEC, &inhd1, &infile1);    inname2 = eopen(PROG, inname2, "r", FT_FEA, FEA_SPEC, &inhd2, &infile2);    if (debug_level >= 1) {	fprintf(stderr, "%s: first input file = \"%s\"\n", PROG, inname1);	fprintf(stderr, "%s: second input file = \"%s\"\n", PROG, inname2);    }    GET_GENHD_CODED("freq_format", inhd1, freq_format1, inname1);    REQUIRE(freq_format1 == SPFMT_ARB_FIXED,	    "freq_format in first input file is not ARB_FIXED");    GET_GENHD_CODED("freq_format", inhd2, freq_format2, inname2);    REQUIRE(freq_format1 == SPFMT_ARB_FIXED,	    "freq_format in second input file is not ARB_FIXED");    GET_GENHD_CODED("spec_type", inhd1, spec_type1, inname1);    REQUIRE(spec_type1 == ST_DB || spec_type1 == ST_PWR,	    "spec_type in first input file is not DB or PWR");    GET_GENHD_CODED("spec_type", inhd2, spec_type2, inname2);    REQUIRE(spec_type1 == ST_DB || spec_type1 == ST_PWR,	    "spec_type in second input file is not DB or PWR");    tot_power_defined1 = (get_fea_type("tot_power", inhd1) != UNDEF);    tot_power_defined2 = (get_fea_type("tot_power", inhd2) != UNDEF);    GET_GENHD_CODED("contin", inhd1, contin1, inname1);    GET_GENHD_CODED("contin", inhd2, contin2, inname2);    REQUIRE((contin1 && contin2) || (!contin1 && !contin2),	    "one input contains a spectral density, "	    "and one contains discrete powers");    num_freqs1 = (long) get_genhd_val("num_freqs", inhd1, -1.0);    REQUIRE(num_freqs1 > 0,	    "num_freqs missing or not positive in first input file");    num_freqs2 = (long) get_genhd_val("num_freqs", inhd2, -1.0);    REQUIRE(num_freqs2 > 0,	    "num_freqs missing or not positive in second input file");    GET_GENHD_CODED("frame_meth", inhd1, frame_meth1, inname1);    GET_GENHD_CODED("frame_meth", inhd2, frame_meth2, inname2);    record_freq1 = get_genhd_val("record_freq", inhd1, 0.0);    record_freq2 = get_genhd_val("record_freq", inhd2, 0.0);    REQUIRE(genhd_type("freqs", NULL, inhd1) == FLOAT,	    "header item \"freqs\" wrong type or missing "	    "in first input file");    freqs1 = get_genhd_f("freqs", inhd1);    REQUIRE(genhd_type("freqs", NULL, inhd2) == FLOAT,	    "header item \"freqs\" wrong type or missing "	    "in second input file");    freqs2 = get_genhd_f("freqs", inhd2);    src_sf1 = get_genhd_val("src_sf", inhd1, 0.0);    if (src_sf1 == 0.0)	src_sf1 = get_genhd_val("sf", inhd1, 0.0);    src_sf2 = get_genhd_val("src_sf", inhd2, 0.0);    if (src_sf2 == 0.0)	src_sf2 = get_genhd_val("sf", inhd2, 0.0);    if (debug_level >= 1)	fprintf(stderr, "%s: in %s---\n"		"\tspec_type = \"%s\", tot_power is%sdefined, contin = %d,\n"		"\tnum_freqs = %ld, frame_meth = %d (%s), record_freq = %g,\n"		"\tfile is%stagged, src_sf = %g\n",		PROG, inname1,		sptyp_names[spec_type1],		tot_power_defined1 ? " " : " not ",		contin1,		num_freqs1,		frame_meth1, (idx_ok(frame_meth1, spfrm_names)			      ? spfrm_names[frame_meth1] : "bad value"),		record_freq1,		(inhd1->common.tag) ? " " : " not ",		src_sf1);    if (debug_level >= 2) {	fprintf(stderr, "\tfreqs = {");	for (i = 0; i < num_freqs1; i++) {	    if (i%5 == 0)		fprintf(stderr, "\n\t [%2ld] ", i);	    fprintf(stderr, " %11.6g", freqs1[i]);	}	fprintf(stderr, "}\n");    }    if (debug_level >= 1)	fprintf(stderr, "%s: in %s---\n"		"\tspec_type = \"%s\", tot_power is%sdefined, contin = %d,\n"		"\tnum_freqs = %ld, frame_meth = %d (%s), record_freq = %g,\n"		"\tfile is%stagged, src_sf = %g\n",		PROG, inname2,		sptyp_names[spec_type2],		tot_power_defined2 ? " " : " not ",		contin2,		num_freqs2,		frame_meth2, (idx_ok(frame_meth2, spfrm_names)			      ? spfrm_names[frame_meth2] : "bad value"),		record_freq2,		(inhd2->common.tag) ? " " : " not ",		src_sf2);    if (debug_level >= 2) {	fprintf(stderr, "\tfreqs = {");	for (i = 0; i < num_freqs2; i++) {	    if (i%5 == 0)		fprintf(stderr, "\n\t [%2ld] ", i);	    fprintf(stderr, " %11.6g", freqs2[i]);	}	fprintf(stderr, "}\n");    }    tag_match = (inhd1->common.tag && inhd2->common.tag		 && src_sf1 > 0.0		 && src_sf2 > 0.9999*src_sf1		 && src_sf2 < 1.0001*src_sf1);    rec_freq_match = (record_freq1 > 0.0		      && record_freq2 > 0.9999*record_freq1		      && record_freq2 < 1.0001*record_freq1);    REQUIRE(tag_match || rec_freq_match,	    "input files are mismatched in record_freq "	    "and (if tagged) in src_sf");    for (i = 0;	 i < num_freqs1 && i < num_freqs2	 && freqs1[i] < 4000.0 && freqs2[i] < 4000.0;	 i++)    {	REQUIRE(freqs2[i] > 0.99*freqs1[i] && freqs2[i] < 1.01*freqs1[i],		"frequencies in the input file headers disagree");    }    num_freqs = i;    if (debug_level >= 1)	fprintf(stderr, "%s: using %d frequencies\n", PROG, num_freqs);    /*     * PROCESS OPTIONS AND PARAMETERS.     */    (void) read_params(param_name, SC_NOCOMMON, NULL);    /* OUTPUT SELECTION */    REQUIRE(!a_specified || !A_specified,	    "both -a and -A specified");    /* RECORD RANGE */    startrec1 = 1;    startrec2 = 1;    nan = 0;    if (r_arg1 != NULL) {	long	endrec;	endrec = LONG_MAX;	lrange_switch(r_arg1, &startrec1, &endrec, NO);	REQUIRE(endrec >= startrec1,		"empty range of records specified");	if (endrec != LONG_MAX)	    nan = endrec - startrec1 + 1;	if (r_arg2 != NULL) {	    endrec = LONG_MAX;	    lrange_switch(r_arg2, &startrec2, &endrec, NO);	    REQUIRE(endrec >= startrec2,		    "empty range of records specified");	    if (endrec != LONG_MAX) {		if (nan == 0)		    nan = endrec - startrec2 + 1;		else		    REQUIRE(nan == endrec - startrec2 + 1,			    "inconsistent range sizes specified");	    }	} else {	    startrec2 = startrec1;	}    } else {	switch (symtype("start")) {	case ST_INT:	    startrec1 = startrec2 = getsym_i("start");	    break;	case ST_IARRAY:	    REQUIRE(getsym_ia("start", startrecs, 2) == 2,		    "size of array parameter \"start\" is not 2");	    startrec1 = startrecs[0];	    startrec2 = startrecs[1];	    break;	case ST_UNDEF:	    break;	default:	    ERROR("type of symbol \"start\" is not int or int array");	}	switch (symtype("nan")) {	case ST_INT:	    nan = getsym_i("nan");	    break;	case ST_UNDEF:	    break;

⌨️ 快捷键说明

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