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 + -
显示快捷键?