barkspec.c

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

C
1,075
字号
/* * 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-scaled critical-band spectra */static char *sccs_id = "@(#)barkspec.c	1.3\t9/2/98\tERL";/* INCLUDE FILES */#include <stdlib.h>#include <math.h>#include <esps/esps.h>#include <esps/fea.h>#include <esps/feaspec.h>/* LOCAL CONSTANTS */#define VERSION	"1.3"		/* must be 7 char or less */#define DATE	"9/2/98"	/* must be 25 char or less */#define PROG	"barkspec"	/* must be 15 char or less */#if !defined(HP700)#define ASINH_AVAILABLE		/* Define this if implementation provides				 * non-ANSI function "asinh"; else undefine				 * to get homebrew definition further down.				 */#endif#define LOG10_BY_10 0.230258509299404568402				/* log(10.0)/10.0 */#define LO_3DB	(-0.590f)	/* low edge of -3 dB band of filter */#define HI_3DB	( 0.410f)	/* high edge of -3 dB band of filter */#define LO_LIM	(-6.465f)	/* low cutoff (-60dB) of filter */#define HI_LIM	( 2.865f)	/* high cutoff (-60dB) of filter *//* LOCAL MACROS */#define SYNTAX \USAGE("barkspec [-a add_const] [-m mult_const] [-n num_freqs] [-r range]\n" \      "\t[-x debug_level] [-B  bark_range] [-H  freq_range]\n" \      "\t[-P  param_file] [-S spec_type] [-X] input.fspec output.fspec")#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 STRCMP(a, op, b) (strcmp((a), (b)) op 0)#define ABS(x) (((x) < 0) ? -(x) : (x))/* 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 */int		debug_level = 0;extern char	*get_cmd_line(int argc, char **argv);/* LOCAL TYPEDEFS AND STRUCTURES */struct filt {    long    start, end;			/* limits of range of summation */    double  *weights;			/* filter weights */};/* LOCAL FUNCTION DECLARATIONS */static double	bark_to_hz(double b);static double	hz_to_bark(double h);static double	filter_weight(double b);#ifndef ASINH_AVAILABLEstatic double	asinh(double x);#endif/* STATIC (LOCAL) GLOBAL VARIABLES *//* MAIN PROGRAM */intmain(int   argc,     char  **argv){    int		    ch;			/* command-line option letter */    long	    i, j, k, n;		/* loop counters and array indices */    char	    *a_arg = NULL;	/* a-option argument */    double	    add_const;		/* constant to be added					 * to output values */    char	    *m_arg = NULL;	/* m-option argument */    double	    mult_const;		/* constant by which output values					 * are to be multiplied */    char	    *n_arg = NULL;	/* n-option argument */    long	    out_nfreqs;		/* number of Bark values at which					 * to compute spectral values */    char	    *r_arg = NULL;	/* r-option argument */    long	    startrec;		/* first record to process */    long	    nan;		/* number of records to process,					 * but 0 means range extends to					 * end of file */    char	    *B_arg = NULL;	/* B-option argument */    double	    bark_low;		/* low limit of range of Bark-					 * scale values to be covered */    double	    bark_high;		/* high limit of range of Bark-					 * scale values to be covered */    char	    *H_arg = NULL;	/* H-option argument */    double	    band_low;		/* linear-scale frequency					 * equivalent to bark_low */    double	    band_high;		/* linear-scale frequency					 * equivalent to bark_high */    char	    *param_name = NULL;	/* parameter file name */    char	    *S_arg = NULL;	/* S-option argument */    char	    *sptypsym;		/* param file entry for spec_type */    int		    out_sptyp;		/* SPTYPE_PWR or SPTYPE_DB: ouput					 * spectral values directly or					 * convert to dB? */    int		    X_specified = NO;	/* output table of filter band					 * edges and peak freqs? */    char	    *inname;		/* input file name */    FILE	    *infile;		/* input stream */    struct header   *inhd;		/* input file header */    struct feaspec  *inrec;		/* input FEA_SPEC record */    float	    *inbuf;		/* input data buffer */    float	    *inbufim;		/* input data buffer (imag part) */    int		    in_sptyp;		/* input file spec_type */    long	    in_nfreqs;		/* number of frequencies in input					 * record */    int		    frame_meth;		/* input file frame_meth */    long	    frmlen;		/* input file frame length */    int		    tot_power_def; 	/* tot_power field defined? */    double	    record_freq;	/* input file record frequency */    char	    *outname;		/* output file name */    FILE	    *outfile;		/* output stream */    struct header   *outhd;		/* output file header */    struct feaspec  *outrec;		/* output FEA_SPEC record */    float	    *outbuf;		/* output data buffer */    float	    *bark_freqs;	/* bark_scale filter peak					 * frequencies */    double	    chan_sp;		/* spacing between values					 * in bark_freqs */    float	    *freqs;		/* linear-scale equivalents of					 * values in bark_freqs */    float	    sf;			/* sf/2 = upper limit of input					 * frequency range */    double	    df;			/* interval between frequencies					 * in input */    struct filt	    *filters;		/* filter structures */    /*     * PARSE COMMAND-LINE OPTIONS.     */    while ((ch = getopt(argc, argv, "a:m:n:r:x:B:H:P:S:X")) != EOF)	switch (ch) {	case 'a':	    a_arg = optarg;	    break;	case 'm':	    m_arg = optarg;	    break;	case 'n':	    n_arg = optarg;	    break;	case 'r':	    r_arg = optarg;	    break;	case 'x':	    debug_level = atoi(optarg);	    break;	case 'B':	    B_arg = optarg;	    break;	case 'H':	    H_arg = optarg;	    break;	case 'P':	    param_name = optarg;	    break;	case 'S':	    S_arg = optarg;	    break;	case 'X':	    X_specified = YES;	    break;	default:	    SYNTAX;	    break;	}    /*     * PROCESS FILE NAMES.     */    if (argc - optind > 2) {	fprintf(stderr, "%s: too many file names.\n", PROG);	SYNTAX;    }    if (argc - optind < 2) {	fprintf(stderr, "%s: not enough file names.\n", PROG);	SYNTAX;    }    inname = argv[optind++];    outname = argv[optind++];    REQUIRE(STRCMP(inname, ==, "-") || STRCMP(inname, != , outname),	    "output file same as input");    /*     * OPEN AND CHECK INPUT FILE.     */    inname = eopen(PROG, inname, "r", FT_FEA, FEA_SPEC, &inhd, &infile);    if (debug_level >= 1)	fprintf(stderr, "%s: input file = \"%s\".\n", PROG, inname);    REQUIRE(genhd_type("spec_type", NULL, inhd) == CODED,	    "header item \"spec_type\" undefined or wrong type");    in_sptyp = *get_genhd_s("spec_type", inhd);    REQUIRE(genhd_type("freq_format", NULL, inhd) == CODED,	    "header item \"freq_format\" undefined or wrong type");    REQUIRE(*get_genhd_s("freq_format", inhd) == SPFMT_SYM_EDGE,	    "input file freq_format is not SYM_EDGE");    REQUIRE(genhd_type("sf", NULL, inhd) == FLOAT,	    "header item \"sf\" undefined or wrong type");    sf = *get_genhd_f("sf", inhd);    REQUIRE(genhd_type("num_freqs", NULL, inhd) == LONG,	    "input header item \"num_freqs\" undefined or wrong type");    in_nfreqs = *get_genhd_l("num_freqs", inhd);    REQUIRE(genhd_type("frame_meth", NULL, inhd) == CODED,	    "header item \"frame_meth\" undefined or wrong type");    frame_meth = *get_genhd_s("frame_meth", inhd);    if (frame_meth == SPFRM_FIXED) {	REQUIRE(genhd_type("frmlen", NULL, inhd) == LONG,		"header item \"frmlen\" undefined or wrong type "		"in file with FIXED frame_meth");	frmlen = *get_genhd_l("frmlen", inhd);    } else {	frmlen = 0;    }    tot_power_def = (get_fea_type("tot_power", inhd) != UNDEF);    if (debug_level >= 1)	fprintf(stderr,		"%s: input spec_type = %d, sf = %g, num_freqs = %ld\n"		"%s: frame_meth = %d, frmlen = %ld, tot_power_def = %s\n",		PROG, in_sptyp, sf, in_nfreqs,		PROG, frame_meth, frmlen, (tot_power_def) ? "YES" : "NO");    /*     * READ PARAMETER FILE.     */    (void) read_params(param_name, SC_NOCOMMON, inname);    /*     * PROCESS OPTIONS.     */    /* RECORD RANGE */    startrec = 1;    nan = 0;    if (r_arg) {	long	    endrec;		/* last record to process */	endrec = LONG_MAX;	lrange_switch(r_arg, &startrec, &endrec, NO);	REQUIRE(endrec >= startrec,		"empty range of records specified");	if (endrec != LONG_MAX)	    nan = endrec - startrec + 1;    } else {	switch (symtype("start")) {	case ST_INT:	    startrec = getsym_i("start");	    break;	case ST_UNDEF:	    break;	default:	    ERROR("type of symbol \"start\" is not INT");	}	switch (symtype("nan")) {	case ST_INT:	    nan = getsym_i("nan");	    break;	case ST_UNDEF:	    break;	default:	    ERROR("type of symbol \"nan\" is not INT");	}    }    if (debug_level >= 1)	fprintf(stderr,		"%s: start = %ld, nan = %ld\n", PROG, startrec, nan);	    /* FREQUENCY RANGE */    REQUIRE(B_arg == NULL || H_arg == NULL,	    "both B and H options specified");    bark_low = 0.0;		/* default */    bark_high = 0.0;		/* 0 implies use default */    band_low = 0.0;		/* default */    band_high = 0.0;		/* 0 implies use default */    if (B_arg != NULL) {	frange_switch(B_arg, &bark_low, &bark_high);	band_low = bark_to_hz(bark_low);	band_high = bark_to_hz(bark_high);    } else if (H_arg != NULL) {	frange_switch(H_arg, &band_low, &band_high);	bark_low = hz_to_bark(band_low);	bark_high = hz_to_bark(band_high);    } else {	if (symtype("bark_high") != ST_UNDEF) {	    REQUIRE(symtype("bark_high") == ST_FLOAT,		    "type of symbol \"bark_high\" is not FLOAT");	    bark_high = getsym_d("bark_high");	    band_high = bark_to_hz(bark_high);	} else if (symtype("band_high") != ST_UNDEF) {	    REQUIRE(symtype("band_high") == ST_FLOAT,		    "type of symbol \"band_high\" is not FLOAT");	    band_high = getsym_d("band_high");	    bark_high = hz_to_bark(band_high);	}	if (symtype("bark_low") != ST_UNDEF) {	    REQUIRE(symtype("bark_low") == ST_FLOAT,		    "type of symbol \"bark_low\" is not FLOAT");	    bark_low = getsym_d("bark_low");	    band_low = bark_to_hz(bark_low);	} else if (symtype("band_low") != ST_UNDEF) {	    REQUIRE(symtype("band_low") == ST_FLOAT,		    "type of symbol \"band_low\" is not FLOAT");	    band_low = getsym_d("band_low");	    bark_low = hz_to_bark(band_low);	}    }    if (band_high == 0.0) {	/* If the initial 0 values haven't been changed by option or	 * param-file entry, or if an explicit 0 was specified, assign 	 * the default values to band_high and bark_high.  We could	 * have tested either one.  This depends on the fact that	 * bark_to_hz(0.0) == 0.0 and hz_to_bark(0.0) == 0.0.	 */	band_high = sf/2.0;	bark_high = hz_to_bark(band_high);    }    if (debug_level >= 1)	fprintf(stderr,		"%s: bark_low = %g, bark_high = %g,\n"		"\tband_low = %g, band_high = %g\n",		PROG, bark_low, bark_high, band_low, band_high);    REQUIRE(bark_high - bark_low >= 1.0,	    "Bark-scale range less than 1 bark");    REQUIRE(bark_low >= LO_3DB,	    "frequency range extends too far below 0");    REQUIRE(bark_high <= HI_3DB + hz_to_bark(sf/2.0),	    "frequency range extends too far above Nyquist");    /* NUMBER AND SPACING OF CHANNELS */    out_nfreqs = 0;			/* 0 implies use default */    if (n_arg != NULL) {	out_nfreqs = atol(n_arg);    } else if (symtype("num_freqs") != ST_UNDEF) {	REQUIRE(symtype("num_freqs") == ST_INT,		"type of symbol \"num_freqs\" is not INT");	out_nfreqs = getsym_i("num_freqs");    }    if (out_nfreqs == 0) {		/* use default */	out_nfreqs = LROUND(bark_high - bark_low);    }    if (out_nfreqs > 1) {	chan_sp = (bark_high - bark_low - 1.0)/(out_nfreqs - 1);	REQUIRE(chan_sp > 0.0,		"spacing between channels is not positive");    } else {	chan_sp = 1.0;			/* arbitrary valid numeric value */    }    if (debug_level >= 1)	fprintf(stderr,		"%s: output num_freqs = %ld, channel spacing = %g\n",		PROG, out_nfreqs, chan_sp);    /* SPEC TYPE */    if (S_arg != NULL) {	out_sptyp = lin_search(sptyp_names, S_arg);    } else if (symtype("spec_type") != ST_UNDEF) {	sptypsym = getsym_s("spec_type");		REQUIRE(sptypsym != NULL,		"type of symbol \"spec_type\" is not STRING");	out_sptyp = lin_search(sptyp_names, sptypsym);    } else {	out_sptyp = ST_DB;    }    REQUIRE(out_sptyp == ST_DB || out_sptyp == ST_PWR,	    "spec_type is not DB or PWR");    if (debug_level >= 1)	fprintf(stderr, "%s: output spec_type = \"%s\"\n",		PROG, sptyp_names[out_sptyp]);    /* ADDITIVE AND MULTIPLICATIVE CONSTANTS */    if (a_arg != NULL) {	add_const = atof(a_arg);    } else if (symtype("add_const") != ST_UNDEF) {	REQUIRE(symtype("add_const") == ST_FLOAT,		"type of symbol \"add_const\" is not FLOAT");	add_const = getsym_d("add_const");    } else {	add_const = 0;    }    if (m_arg != NULL) {	mult_const = atof(m_arg);    } else if (symtype("mult_const") != ST_UNDEF) {	REQUIRE(symtype("mult_const") == ST_FLOAT,		"type of symbol \"mult_const\" is not FLOAT");	mult_const = getsym_d("mult_const");    } else {	mult_const = 1;    }    if (debug_level >= 1)	fprintf(stderr, "%s: add_const = %g, mult_const = %g\n",		PROG, add_const, mult_const);    /*     * PREPARE FILTERS     */    /* FILTER PEAK FREQS */    TRYALLOC(float, out_nfreqs, bark_freqs, "bark_freqs");

⌨️ 快捷键说明

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