barkspec.c
来自「speech signal process tools」· C语言 代码 · 共 1,075 行 · 第 1/2 页
C
1,075 行
TRYALLOC(float, out_nfreqs, freqs, "freqs"); for (i = 0; i < out_nfreqs; i++) { bark_freqs[i] = bark_low - LO_3DB + i*chan_sp; freqs[i] = bark_to_hz(bark_freqs[i]); } if (X_specified || debug_level >= 2) { fprintf(stderr, "-------------bark_freqs------------ " "---------------freqs---------------\n"); fprintf(stderr, " low edge peak high edge " " low edge peak high edge \n"); for (i = 0; i < out_nfreqs; i++) fprintf(stderr, "%11.3f %11.3f %11.3f %11.1f %11.1f %11.1f\n", bark_freqs[i] + LO_3DB, bark_freqs[i], bark_freqs[i] + HI_3DB, bark_to_hz(bark_freqs[i] + LO_3DB), freqs[i], bark_to_hz(bark_freqs[i] + HI_3DB)); } /* ALLOCATE STORAGE */ TRYALLOC(struct filt, out_nfreqs, filters, "filters"); for (i = 0; i < out_nfreqs; i++) TRYALLOC(double, in_nfreqs, filters[i].weights, "filter weights"); if (debug_level >= 1) fprintf(stderr, "%s: allocated space for filter structs and weights\n", PROG); /* COMPUTE SUMMATION LIMITS AND WEIGHTS */ { long N = in_nfreqs - 1; /* input spectral points are * indexed from 0 thru N. * Indices wrap mod 2N so that * -N is equivalent to N. * E.g. for spectra from a 256-point * FFT, we would have in_nfreqs = 129, * N = 128 */ df = sf/(2*N); /* interval between frequencies * in input; Nyquist is N*df */ for (i = 0; i < out_nfreqs; i++) { long lo, hi; /* indices of input frequencies * spanning range from low filter * cutoff to high cutoff */ long start, end; /* indexing limits (for filt * structure) */ double peak; /* peak Bark-scale frequency * of filter */ if (debug_level >= 3) fprintf(stderr, "%s: computing filter for channel %ld\n", PROG, i); for (k = 0; k <= N; k++) filters[i].weights[k] = 0.0; peak = bark_freqs[i]; lo = ceil(bark_to_hz(peak + LO_LIM)/df); hi = floor(bark_to_hz(peak + HI_LIM)/df); if (debug_level >= 3) fprintf(stderr, "%s: low index = %ld, high index = %ld\n", PROG, lo, hi); start = LONG_MAX; end = LONG_MIN; for (j = lo; j <= hi; j++) { /* wrap index into range 0..N using (1) symmetry about 0 * and (2) periodicity mod 2N */ k = ABS(j); k = (k + N)%(2*N) - N; k = ABS(k); if (k < start) start = k; if (k > end) end = k; filters[i].weights[k] += filter_weight(hz_to_bark(j*df) - peak); if (debug_level >= 5) fprintf(stderr, "%s: index = %ld; weight[%ld] = %g\n", PROG, j, k, filters[i].weights[k]); } /* end for (j ... ) */ filters[i].start = start; filters[i].end = end; if (debug_level >= 3) fprintf(stderr, "%s: start index = %ld, end index = %ld\n", PROG, start, end); if (debug_level >= 4) { fprintf(stderr, "%s: channel %ld weights ...", PROG, i); for (j = start; j <= end; j++) { if ((j - start)%5 == 0) fprintf(stderr, "\n [%ld]\t", j); fprintf(stderr, "%14.6g", filters[i].weights[j]); } fprintf(stderr, "\n"); } } /* end for (i ... ) */ } /* end "COMPUTE SUMMATION LIMITS ..." */ /* * CREATE OUTPUT FILE */ /* CREATE HEADER */ if (debug_level >= 1) fprintf(stderr, "%s: creating output header\n", PROG); outhd = new_header(FT_FEA); add_source_file(outhd, inname, inhd); add_comment(outhd, get_cmd_line(argc, argv)); (void) strcpy(outhd->common.prog, PROG); (void) strcpy(outhd->common.vers, VERSION); (void) strcpy(outhd->common.progdate, DATE); outhd->variable.refer = inhd->variable.refer; init_feaspec_hd(outhd, tot_power_def, SPFMT_ARB_FIXED, out_sptyp, NO, out_nfreqs, frame_meth, freqs, sf, frmlen, FLOAT); outhd->common.tag = inhd->common.tag; if (outhd->common.tag) { double src_sf; /* value for output file header * item src_sf */ src_sf = get_genhd_val("src_sf", inhd, -1.0); if (src_sf == -1.0) src_sf = sf; *add_genhd_d("src_sf", NULL, 1, outhd) = src_sf; if (debug_level >= 1) fprintf(stderr, "%s: file is tagged; src_sf = %g\n", PROG, src_sf); } else { if (debug_level >= 1) fprintf(stderr, "%s: file is not tagged\n", PROG); } record_freq = get_genhd_val("record_freq", inhd, 0.0); if (record_freq != 0.0) { update_waves_gen(inhd, outhd, (float) startrec, 1.0f); if (debug_level >= 1) fprintf(stderr, "%s: record_freq defined; value is %g\n", PROG, record_freq); } else if (!outhd->common.tag) { fprintf(stderr, "%s: WARNING: file is not tagged " "and \"record_freq\" is undefined.\n", PROG); } *add_genhd_l("start", NULL, 1, outhd) = startrec; *add_genhd_l("nan", NULL, 1, outhd) = nan; *add_genhd_d("add_const", NULL, 1, outhd) = add_const; *add_genhd_d("mult_const", NULL, 1, outhd) = mult_const; *add_genhd_d("band_low", NULL, 1, outhd) = band_low; *add_genhd_d("band_high", NULL, 1, outhd) = band_high; *add_genhd_d("bark_low", NULL, 1, outhd) = bark_low; *add_genhd_d("bark_high", NULL, 1, outhd) = bark_high; (void) add_genhd_f("bark_freqs", bark_freqs, (int) out_nfreqs, outhd); /* OPEN FILE */ if (debug_level >= 1) fprintf(stderr, "%s: opening output file\n", PROG); outname = eopen(PROG, outname, "w", NONE, NONE, NULL, &outfile); if (debug_level >= 1) fprintf(stderr, "%s: output file = \"%s\".\n", PROG, outname); /* WRITE HEADER */ if (debug_level >= 1) fprintf(stderr, "%s: writing header\n", PROG); write_header(outhd, outfile); /* * SET UP I/O RECORD STRUCTS AND DATA BUFFERS */ if (debug_level >= 1) fprintf(stderr, "%s: allocating input and output record structures\n", PROG); inrec = allo_feaspec_rec(inhd, FLOAT); inbuf = inrec->re_spec_val; inbufim = inrec->im_spec_val; outrec = allo_feaspec_rec(outhd, FLOAT); outbuf = outrec->re_spec_val; /* * MAIN READ-WRITE LOOP */ fea_skiprec(infile, startrec - 1, inhd); if (debug_level >= 1) fprintf(stderr, "%s: reading and processing data\n", PROG); for (n = 0; (nan == 0 || n < nan) && get_feaspec_rec(inrec, inhd, infile) != EOF; n++) { if (debug_level >= 3) fprintf(stderr, "%s: processing record %ld\n", PROG, n + 1); if (debug_level >= 4) { fprintf(stderr, "%s: record %ld input data ...", PROG, n + 1); for (j = 0; j < in_nfreqs; j++) { if (j%5 == 0) fprintf(stderr, "\n [%ld]\t", j); fprintf(stderr, "%14.6g", inbuf[j]); } fprintf(stderr, "\n"); } /* CONVERT TO PWR */ switch (in_sptyp) { case SPTYP_PWR: /* nothing to do */ break; case SPTYP_DB: for (j = 0; j < in_nfreqs; j++) inbuf[j] = exp(LOG10_BY_10 * inbuf[j]); break; case SPTYP_REAL: for (j = 0; j < in_nfreqs; j++) inbuf[j] = inbuf[j] * inbuf[j]; break; case SPTYP_CPLX: for (j = 0; j < in_nfreqs; j++) inbuf[j] = inbuf[j]*inbuf[j] + inbufim[j]*inbufim[j]; break; default: ERROR("unrecognized input spec_type"); } if (debug_level >= 4) { fprintf(stderr, "%s: record %ld input data (PWR) ...", PROG, n + 1); for (j = 0; j < in_nfreqs; j++) { if (j%5 == 0) fprintf(stderr, "\n [%ld]\t", j); fprintf(stderr, "%14.6g", inbuf[j]); } fprintf(stderr, "\n"); } /* COMPUTE WEIGHTED SUMS */ for (i = 0; i < out_nfreqs; i++) { long start, end; double *weights; double sum; start = filters[i].start; end = filters[i].end; weights = filters[i].weights; sum = 0.0; for (j = start; j <= end; j++) sum += weights[j] * inbuf[j]; outbuf[i] = sum * df; /* Input "power" is assumed to represent a power spectral * density with units of (unit power)/Hz, such as fft * produces. The factor df converts the weighted sums into * integrated powers with units of (unit power). (df is * defined under "COMPUTE SUMMATION LIMITS AND WEIGHTS" * above.) */ } if (debug_level >= 4) { fprintf(stderr, "%s: record %ld output data ...", PROG, n + 1); for (i = 0; i < out_nfreqs; i++) { if (i%5 == 0) fprintf(stderr, "\n [%ld]\t", i); fprintf(stderr, "%14.6g", outbuf[i]); } fprintf(stderr, "\n"); } /* CONVERT TO OUTPUT SPEC_TYPE */ switch (out_sptyp) { case SPTYP_PWR: /* nothing to do */ break; case SPTYP_DB: for (i = 0; i < out_nfreqs; i++) outbuf[i] = 10*log10(outbuf[i]); break; case SPTYP_REAL: /* FALL THROUGH */ case SPTYP_CPLX: ERROR("unsupported output spec_type"); break; default: ERROR("unrecognized output spec_type"); } if (debug_level >= 4) { fprintf(stderr, "%s: record %ld output data (%s) ...", PROG, n + 1, sptyp_names[out_sptyp]); for (i = 0; i < out_nfreqs; i++) { if (i%5 == 0) fprintf(stderr, "\n [%ld]\t", i); fprintf(stderr, "%14.6g", outbuf[i]); } fprintf(stderr, "\n"); } /* OPIONAL LINEAR SCALING OF OUTPUT DATA */ if (mult_const != 1.0) for (i = 0; i < out_nfreqs; i++) outbuf[i] = outbuf[i] * mult_const; if (add_const != 0.0) for (i = 0; i < out_nfreqs; i++) outbuf[i] = outbuf[i] + add_const; if (debug_level >= 4) { fprintf(stderr, "%s: record %ld scaled output data ...", PROG, n + 1); for (i = 0; i < out_nfreqs; i++) { if (i%5 == 0) fprintf(stderr, "\n [%ld]\t", i); fprintf(stderr, "%14.6g", outbuf[i]); } fprintf(stderr, "\n"); } /* TOT_POWER, FRAME_LEN, AND TAG */ if (tot_power_def) { *outrec->tot_power = *inrec->tot_power; if (debug_level >= 3) fprintf(stderr, "%s: tot_power = %g\n", PROG, *inrec->tot_power); } if (frame_meth == SPFRM_VARIABLE) { *outrec->frame_len = *inrec->frame_len; if (debug_level >= 3) fprintf(stderr, "%s: frame_len = %ld\n", PROG, *inrec->frame_len); } if (outhd->common.tag) { *outrec->tag = *inrec->tag; if (debug_level >= 3) fprintf(stderr, "%s: tag = %ld\n", PROG, *inrec->tag); } /* WRITE RECORD */ if (debug_level >= 3) fprintf(stderr, "%s: writing output record %d\n", PROG, n + 1); put_feaspec_rec(outrec, outhd, outfile); } /* * WRAP UP */ if (debug_level >= 1) fprintf(stderr, "%s: wrote %ld records\n", PROG, n); if (n < nan) fprintf(stderr, "%s: WARNING: premature end of file; " "only %d records read\n", PROG, n); return 0; /* equivalent to exit(0); */}/* * Convert a Bark-scale value b to the equivalent linear-scale * frequency (in hertz). */static doublebark_to_hz(double b){ return 600.0*sinh(b/6.0);}/* * Convert a linear-scale frequency f (in hertz) to the equivalent * Bark-scale value. */static doublehz_to_bark(double f){ return 6.0*asinh(f/600.0);}/* * Compute the value of a critical-band weighting function at a point, * given the distance b of the point from the peak (in barks) */static doublefilter_weight(double b){ double w; /* return value (dB) */ b -= 0.210; /* adjust for peak at 0 bark; * not 0.215; see man page. */ /* the other magic numbers below come * come from Wang, Sekey, & Gersho [1] and * Sekey & Hanson [2]; see the man page * for full references. */ w = 7.0 - 7.5*b - 17.5*sqrt(0.196 + b*b); return exp(LOG10_BY_10 * w); /* convert from dB */}/* * Inverse sinh function, for use when not provided by the math library. */#ifndef ASINH_AVAILABLEstatic doubleasinh(double x){ if (x > 0.2) { /* precise value not critical */ /* theoretically correct, but loses precision * when x is small in magnitude or negative */ return log(sqrt(1 + x*x) + x); } else if (x < -0.2) { /* precise value not critical */ /* theoretically correct, but loses precision * when x is small in magnitude or positive */ return -log(sqrt(1 + x*x) - x); } else { double f, n, p, s, s0; /* use power-series expansion when |x| is small */ f = -x*x; n = 1.0; p = x; s = 0.0; /* will add in first term (x) at end */ do { s0 = s; p *= f*n/(n+1.0); n += 2.0; s += p/n; } while (s != s0); return s + x; }}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?