melspec.c

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

C
1,061
字号
/* * 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 mel-scaled spectra */static char *sccs_id = "@(#)melspec.c	1.1\t7/12/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.1"		/* must be 7 char or less */#define DATE	"7/12/98"	/* must be 25 char or less */#define PROG	"melspec"	/* must be 15 char or less */#define LOG10_BY_10 0.230258509299404568402				/* log(10.0)/10.0 */#define MEL_CONST   1127.01048033415743865				/* 1000.0/log(1700.0/700.0),				 * chosen to make hz_to_mel(1000.0)				 * equal to 1000.0.				 *//* LOCAL MACROS */#define SYNTAX \USAGE("melspec [-a add_const] [-m mult_const] [-n num_freqs] [-r range]\n" \      "\t[-x debug_level] [-H  freq_range] [-M  mel_range]\n" \      "\t[-P  param_file] [-S spec_type] [-W channel_width] [-X]\n" \      "\tinput.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	mel_to_hz(double m);	/* convert mel scale to linear */static double	hz_to_mel(double h);	/* convert linear scale to mel */static double	filter_weight(double m, double h);					/* compute filter weights *//* 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 mel 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	    *H_arg = NULL;	/* H-option argument */    double	    band_low;		/* linear-scale frequency					 * equivalent to mel_low */    double	    band_high;		/* linear-scale frequency					 * equivalent to mel_high */    char	    *M_arg = NULL;	/* M-option argument */    double	    mel_low;		/* low limit of range of mel-					 * scale values to be covered */    double	    mel_high;		/* high limit of range of mel-					 * scale values to be covered */    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? */    char	    *W_arg = NULL; 	/* W-option argument */    double	    channel_width;	/* width in mel of triangular					 * filters */    double	    half_width;		/* 0.5*channel_width */    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	    *mel_freqs;		/* filter mel-scale center					 * frequencies */    double	    chan_sp;		/* spacing between values					 * in mel_freqs */    float	    *freqs;		/* linear-scale equivalents of					 * values in mel_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:H:M:P:S:W: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 'H':	    H_arg = optarg;	    break;	case 'M':	    M_arg = optarg;	    break;	case 'P':	    param_name = optarg;	    break;	case 'S':	    S_arg = optarg;	    break;	case 'W':	    W_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 spec_type 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(M_arg == NULL || H_arg == NULL,	    "both M and H options specified");    mel_low = 0.0;		/* default */    mel_high = 0.0;		/* 0 implies use default */    band_low = 0.0;		/* default */    band_high = 0.0;		/* 0 implies use default */    if (M_arg != NULL) {	frange_switch(M_arg, &mel_low, &mel_high);	band_low = mel_to_hz(mel_low);	band_high = mel_to_hz(mel_high);    } else if (H_arg != NULL) {	frange_switch(H_arg, &band_low, &band_high);	mel_low = hz_to_mel(band_low);	mel_high = hz_to_mel(band_high);    } else {	if (symtype("mel_high") != ST_UNDEF) {	    REQUIRE(symtype("mel_high") == ST_FLOAT,		    "type of symbol \"mel_high\" is not FLOAT");	    mel_high = getsym_d("mel_high");	    band_high = mel_to_hz(mel_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");	    mel_high = hz_to_mel(band_high);	}	if (symtype("mel_low") != ST_UNDEF) {	    REQUIRE(symtype("mel_low") == ST_FLOAT,		    "type of symbol \"mel_low\" is not FLOAT");	    mel_low = getsym_d("mel_low");	    band_low = mel_to_hz(mel_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");	    mel_low = hz_to_mel(band_low);	}    }    if (mel_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 mel_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;	mel_high = hz_to_mel(band_high);    }    if (debug_level >= 1)	fprintf(stderr,		"%s: mel_low = %g, mel_high = %g,\n"		"\tband_low = %g, band_high = %g\n",		PROG, mel_low, mel_high, band_low, band_high);    /* NUMBER AND SPACING OF CHANNELS */    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");    } else {	out_nfreqs = 0;			/* invalid value to indicate need					 * to compute default from					 * channel_width */    }    if (W_arg != NULL) {	channel_width = atof(W_arg);    } else if (symtype("channel_width") != ST_UNDEF) {	REQUIRE(symtype("channel_width") == ST_FLOAT,		"type of symbol \"channel_width\" is not FLOAT");	channel_width = getsym_d("channel_width");    } else {	channel_width = 0.0;		/* invalid value to indicate need					 * to compute default from					 * output num_freqs */    }    if (channel_width > 0.0) {	if (out_nfreqs == 0)	    out_nfreqs = LROUND(2.0*(mel_high - mel_low)/channel_width) - 1;    } else if (out_nfreqs > 0) {	if (channel_width == 0.0)	    channel_width = 2.0*(mel_high - mel_low)/(out_nfreqs + 1);    } else {	ERROR("both num_freqs and channel_width are unspecified or invalid");    }    REQUIRE(channel_width > 0.0,	    "channel_width not positive");    REQUIRE(mel_high - mel_low >= channel_width,	    "single channel bandwidth exceeds total mel-scale range");    REQUIRE(out_nfreqs > 0,	    "output num_freqs not positive");    half_width = 0.5*channel_width;    if (out_nfreqs > 1) {	chan_sp = (mel_high - mel_low - channel_width)/(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: %ld channels, width = %g, spacing = %g\n",		PROG, out_nfreqs, channel_width, 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 */

⌨️ 快捷键说明

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