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