bs_dist.c
来自「speech signal process tools」· C语言 代码 · 共 1,029 行 · 第 1/2 页
C
1,029 行
default: ERROR("type of symbol \"nan\" is not int"); } } if (debug_level >= 1) fprintf(stderr, "%s: start = {%ld, %ld}, nan = %ld\n", PROG, startrec1, startrec2, nan); REQUIRE(startrec1 >= 1, "range starts before beginning of first input file"); REQUIRE(startrec2 >= 1, "range starts before beginning of second input file"); /* DISTORTION TYPE */ distortion_type = BSD; if (m_arg != NULL) { distortion_type = lin_search(d_types, m_arg); } else if (symtype("distortion_type") != ST_UNDEF) { distypesym = getsym_s("distortion_type"); REQUIRE(distypesym != NULL, "type of symbol \"distortion_type\" is not STRING"); distortion_type = lin_search(d_types, distypesym); } else { distortion_type = BSD; } REQUIRE(distortion_type == BSD, "distortion_type is not BSD"); if (debug_level >= 1) fprintf(stderr, "%s: distortion_type = \"%s\"\n", PROG, d_types[distortion_type]); /* THRESHOLD */ check_thresh = NO; /* this becomes YES only if all conditions for * checking input frame powers against the * threshold are met: we are computing BSD, the * threshold is greater than 0, and the tot_power * field is defined in both input files */ if (distortion_type == BSD) { if (e_arg != NULL) { threshold = atof(e_arg); } else if (symtype("threshold") != ST_UNDEF) { REQUIRE(symtype("threshold") == ST_FLOAT, "type of symbol \"threshold\" is not FLOAT"); threshold = getsym_d("threshold"); } else { threshold = 0.0; } REQUIRE(threshold >= 0.0, "threshold is negative"); if (debug_level >= 1) fprintf(stderr, "%s: threshold = %g\n", PROG, threshold); if (threshold > 0.0) { REQUIRE(tot_power_defined1, "non-zero threshold specified, " "but no tot_power field defined in first input file"); REQUIRE(tot_power_defined2, "non-zero threshold specified, " "but no tot_power field defined in second input file"); check_thresh = YES; } if (debug_level >= 1) fprintf(stderr, "%s: total power of input frames " "will%sbe compared with threshold\n", PROG, (check_thresh ? " " : " not ")); } /* PERCEPTUAL WEIGHTING FACTORS */ if (symtype("perceptual_weights") != ST_UNDEF) { REQUIRE(symtype("perceptual_weights") == ST_FARRAY && symsize("perceptual_weights") >= num_freqs, "parameter \"perceptual_weights\" is too short " "or not a FLOAT array"); TRYALLOC(float, symsize("perceptual_weights"), p_wts, "p_wts"); TRYALLOC(float, symsize("perceptual_weights"), log_wts, "log_wts"); getsym_fa("perceptual_weights", p_wts, num_freqs); for (i = 0; i < num_freqs; i++) { REQUIRE(p_wts[i] > 0.0, "non-positive value in perceptual_weights array"); log_wts[i] = 10 * log10(p_wts[i]); } } else { TRYALLOC(float, num_freqs, p_wts, "p_wts"); TRYALLOC(float, num_freqs, log_wts, "log_wts"); for (i = 0; i < num_freqs; i++) { double a = 2.6; /* Numerator coefficient ... */ double b = 1.6; /* ... and denominator coefficient of bilinear * preemphasis filter. These magic numbers are * from section VI.B of Wang, Sekey, & Gersho, * (1992). */ double w0 = (a + 1.0)*(a + 1.0)/((b + 1.0)*(b + 1.0)); double two_x = 2.0 * cos(PI*freqs1[i]/4000.0); double num = (a + two_x) * a + 1.0; double den = (b + two_x) * b + 1.0; /* * numerator = |a+z|^2 * denominator = |b+z|^2 * where z = exp (2i pi f) and f = freqs1[i]/8000 */ p_wts[i] = (num/den)/w0; log_wts[i] = 10.0 * log10(p_wts[i]); } } if (debug_level >= 2) { fprintf(stderr, "%s: log perceptual weighting factors (dB) ...", PROG); for (i = 0; i < num_freqs; i++) { if (i%5 == 0) fprintf(stderr, "\n [%2ld]\t", i); fprintf(stderr, " %13.6g", log_wts[i]); } fprintf(stderr, "\n"); } /* * CREATE OUTPUT FILE */ if (!a_specified) { /* CREATE HEADER */ if (debug_level >= 1) fprintf(stderr, "%s: creating output header\n", PROG); outhd = new_header(FT_FEA); add_source_file(outhd, inname1, inhd1); add_source_file(outhd, inname2, inhd2); 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 = inhd1->variable.refer; if (tag_match) { outhd->common.tag = YES; *add_genhd_d("src_sf", NULL, 1, outhd) = src_sf1; if (debug_level >= 1) fprintf(stderr, "%s: output file is tagged; src_sf = %g\n", PROG, src_sf1); } else { outhd->common.tag = NO; if (debug_level >= 1) fprintf(stderr, "%s: output file is not tagged\n", PROG); } if (rec_freq_match) { update_waves_gen(inhd1, outhd, (float) startrec1, 1.0f); if (debug_level >= 1) fprintf(stderr, "%s: output record_freq defined; " "value is %g\n", PROG, record_freq1); } else { if (debug_level >= 1) fprintf(stderr, "%s: output record_freq undefined\n", PROG); } start = add_genhd_l("start", NULL, 2, outhd); start[0] = startrec1; start[1] = startrec2; *add_genhd_l("nan", NULL, 1, outhd) = nan; *add_genhd_e("distortion_type", NULL, 1, d_types, outhd) = distortion_type; if (distortion_type == BSD) { *add_genhd_d("threshold", NULL, 1, outhd) = threshold; } (void) add_genhd_f("perceptual_weights", p_wts, num_freqs, outhd); outfld = (distortion_type == BSD) ? "BSD" : "MBSD"; add_fea_fld(outfld, 1, 0, NULL, FLOAT, NULL, 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); } /* end if (!a_specified) */ /* * SET UP I/O RECORD STRUCTS AND DATA BUFFERS */ if (debug_level >= 1) fprintf(stderr, "%s: allocating input and output record structrures\n", PROG); inrec1 = allo_feaspec_rec(inhd1, FLOAT); inbuf1 = inrec1->re_spec_val; intag1 = inrec1->tag; inrec2 = allo_feaspec_rec(inhd2, FLOAT); inbuf2 = inrec2->re_spec_val; intag2 = inrec2->tag; if (!a_specified) { outrec = allo_fea_rec(outhd); outdata = (float *) get_fea_ptr(outrec, outfld, outhd); outtag = &outrec->tag; } if (check_thresh) { tot_power1 = inrec1->tot_power; tot_power2 = inrec2->tot_power; } /* * MAIN READ-WRITE LOOP */ fea_skiprec(infile1, startrec1 - 1, inhd1); fea_skiprec(infile2, startrec2 - 1, inhd2); if (a_specified || A_specified) { /* set up to compute overall average distortion */ sum_distortion = 0.0; norm = 0.0; } if (debug_level >= 1) fprintf(stderr, "%s: reading and processing data\n", PROG); /* If nan == 0, the loop terminates, via a break, when the end of * either input file is reached. * If nan != 0, the loop terminates after nan records have been * read and processed, unless the end of an input file is reached * sooner. In the latter case, a "premature end of file" warning * is issued. */ for (n = 0; nan == 0 || n < nan; n++) { /* READ INPUT FRAMES */ if (get_feaspec_rec(inrec1, inhd1, infile1) == EOF) { if (nan != 0) fprintf(stderr, "%s: WARNING: premature end of file in \"%s\"; " "only %d records read\n", PROG, inname1, n); break; } if (get_feaspec_rec(inrec2, inhd2, infile2) == EOF) { if (nan != 0) fprintf(stderr, "%s: WARNING: premature end of file in \"%s\"; " "only %d records read\n", PROG, inname2, n); break; } if (tag_match && inhd1->common.tag && *intag1 != *intag2) { fprintf(stderr, "%s: WARNING: " "tags mismatch in record %ld. (%ld != %ld)\n", PROG, n + 1, *intag1, *intag2); tag_match = NO; } if (debug_level >= 3) fprintf(stderr, "%s: processing record %ld\n", PROG, n + 1); if (debug_level >= 4) { print_farray(1, n + 1, "input data", num_freqs, inbuf1); print_farray(2, n + 1, "input data", num_freqs, inbuf2); } /* CONVERT TO DB */ switch (spec_type1) { case SPTYP_PWR: for (j = 0; j < num_freqs; j++) inbuf1[j] = 10.0 * log10(inbuf1[j]); break; case SPTYP_DB: /* nothing to do */ break; default: /* Should be impossible; we've already checked spec_type1 */ ERROR("ERROR determining spec_type of first input file"); } switch (spec_type2) { case SPTYP_PWR: for (j = 0; j < num_freqs; j++) inbuf2[j] = 10.0 * log10(inbuf2[j]); break; case SPTYP_DB: /* nothing to do */ break; default: /* Should be impossible; we've already checked spec_type2 */ ERROR("ERROR determining spec_type of first input file"); } if (debug_level >= 4) { print_farray(1, n + 1, "input data (DB)", num_freqs, inbuf1); print_farray(2, n + 1, "input data (DB)", num_freqs, inbuf2); } /* APPLY PERCEPTUAL WEIGHTS */ for (j = 0; j < num_freqs; j++) { inbuf1[j] += log_wts[j]; inbuf2[j] += log_wts[j]; } if (debug_level >= 4) { print_farray(1, n + 1, "input data (phones)", num_freqs, inbuf1); print_farray(2, n + 1, "input data (phones)", num_freqs, inbuf2); } /* PHONES TO SONES */ for (j = 0; j < num_freqs; j++) { inbuf1[j] = exp((inbuf1[j] - 40) * LOG2_OVER_10); inbuf2[j] = exp((inbuf2[j] - 40) * LOG2_OVER_10); } if (debug_level >= 4) { print_farray(1, n + 1, "input data (sones)", num_freqs, inbuf1); print_farray(2, n + 1, "input data (sones)", num_freqs, inbuf2); } /* SQUARED EUCLIDEAN DISTANCE */ frame_distortion = 0.0; for (j = 0; j < num_freqs; j++) { double diff = inbuf1[j] - inbuf2[j]; frame_distortion += diff * diff; } if (debug_level >= 3) fprintf(stderr, "%s: frame %ld distortion = %g\n", PROG, n + 1, frame_distortion); /* OVERALL AVERAGE DISTORTION */ if (a_specified || A_specified) { if (!check_thresh || (*tot_power1 >= threshold && *tot_power2 >= threshold)) { sum_distortion += frame_distortion; } else /* (check_thresh * && (*tot_power1 < thresh || *tot_power2 < thresh) */ { if (debug_level >= 3) fprintf(stderr, "%s: excluding frame %ld distortion---" "power below threshold\n", PROG, n + 1); } for (j = 0; j < num_freqs; j++) { norm += inbuf1[j] * inbuf1[j]; } if (debug_level >= 3) fprintf(stderr, "%s: frame %ld cumulative distortion = %g, " "norm factor %g\n", PROG, n + 1, sum_distortion, norm); } /* WRITE FRAME OUTPUT */ if (!a_specified) { *outdata = frame_distortion; if (outhd->common.tag) { *outtag = *intag1; } if (debug_level >= 3) fprintf(stderr, "%s: writing output record %ld\n", PROG, n + 1); put_fea_rec(outrec, outhd, outfile); } } /* end for (n = 0; ... ) */ /* * WRAP UP */ if (debug_level >= 1) fprintf(stderr, "%s: processed %ld frames\n", PROG, n); if (a_specified || A_specified) { printf("%g\n", sum_distortion/norm); } return 0; /* equivalent to exit(0); */}/* * formatted printout of float array for debugging */voidprint_farray(int filenum, long recnum, char *text, long numelem, float *data){ long j; fprintf(stderr, "%s: file %d record %ld %s ...", PROG, filenum, recnum, text); for (j = 0; j < numelem; j++) { if (j%5 == 0) fprintf(stderr, "\n [%ld]\t", j); fprintf(stderr, " %13.6g", data[j]); } fprintf(stderr, "\n");}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?