int calc_xmin(lame_internal_flags const *gfc, III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * pxmin) { SessionConfig_t const *const cfg = &gfc->cfg; int sfb, gsfb, j = 0, ath_over = 0, k; ATH_t const *const ATH = gfc->ATH; const FLOAT *const xr = cod_info->xr; int max_nonzero; for (gsfb = 0; gsfb < cod_info->psy_lmax; gsfb++) { FLOAT en0, xmin; FLOAT rh1, rh2, rh3; int width, l; xmin = athAdjust(ATH->adjust_factor, ATH->l[gsfb], ATH->floor, cfg->ATHfixpoint); xmin *= gfc->sv_qnt.longfact[gsfb]; width = cod_info->width[gsfb]; rh1 = xmin / width; #ifdef DBL_EPSILON rh2 = DBL_EPSILON; #else rh2 = 2.2204460492503131e-016; #endif en0 = 0.0; for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; rh2 += (x2 < rh1) ? x2 : rh1; } if (en0 > xmin) ath_over++; if (en0 < xmin) { rh3 = en0; } else if (rh2 < xmin) { rh3 = xmin; } else { rh3 = rh2; } xmin = rh3; { FLOAT const e = ratio->en.l[gsfb]; if (e > 1e-12f) { FLOAT x; x = en0 * ratio->thm.l[gsfb] / e; x *= gfc->sv_qnt.longfact[gsfb]; if (xmin < x) xmin = x; } } xmin = Max(xmin, DBL_EPSILON); cod_info->energy_above_cutoff[gsfb] = (en0 > xmin+1e-14f) ? 1 : 0; *pxmin++ = xmin; } /* end of long block loop */ /*use this function to determine the highest non-zero coeff */ max_nonzero = 0; for (k = 575; k > 0; --k) { if (fabs(xr[k]) > 1e-12f) { max_nonzero = k; break; } } if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ max_nonzero |= 1; /* only odd numbers */ } else { max_nonzero /= 6; /* 3 short blocks */ max_nonzero *= 6; max_nonzero += 5; } if (gfc->sv_qnt.sfb21_extra == 0 && cfg->samplerate_out < 44000) { int const sfb_l = (cfg->samplerate_out <= 8000) ? 17 : 21; int const sfb_s = (cfg->samplerate_out <= 8000) ? 9 : 12; int limit = 575; if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ limit = gfc->scalefac_band.l[sfb_l]-1; } else { limit = 3*gfc->scalefac_band.s[sfb_s]-1; } if (max_nonzero > limit) { max_nonzero = limit; } } cod_info->max_nonzero_coeff = max_nonzero; for (sfb = cod_info->sfb_smin; gsfb < cod_info->psymax; sfb++, gsfb += 3) { int width, b, l; FLOAT tmpATH; tmpATH = athAdjust(ATH->adjust_factor, ATH->s[sfb], ATH->floor, cfg->ATHfixpoint); tmpATH *= gfc->sv_qnt.shortfact[sfb]; width = cod_info->width[gsfb]; for (b = 0; b < 3; b++) { FLOAT en0 = 0.0, xmin = tmpATH; FLOAT rh1, rh2, rh3; rh1 = tmpATH / width; #ifdef DBL_EPSILON rh2 = DBL_EPSILON; #else rh2 = 2.2204460492503131e-016; #endif for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; rh2 += (x2 < rh1) ? x2 : rh1; } if (en0 > tmpATH) ath_over++; if (en0 < tmpATH) { rh3 = en0; } else if (rh2 < tmpATH) { rh3 = tmpATH; } else { rh3 = rh2; } xmin = rh3; { FLOAT const e = ratio->en.s[sfb][b]; if (e > 1e-12f) { FLOAT x; x = en0 * ratio->thm.s[sfb][b] / e; x *= gfc->sv_qnt.shortfact[sfb]; if (xmin < x) xmin = x; } } xmin = Max(xmin, DBL_EPSILON); cod_info->energy_above_cutoff[gsfb+b] = (en0 > xmin+1e-14f) ? 1 : 0; *pxmin++ = xmin; } /* b */ if (cfg->use_temporal_masking_effect) { if (pxmin[-3] > pxmin[-3 + 1]) pxmin[-3 + 1] += (pxmin[-3] - pxmin[-3 + 1]) * gfc->cd_psy->decay; if (pxmin[-3 + 1] > pxmin[-3 + 2]) pxmin[-3 + 2] += (pxmin[-3 + 1] - pxmin[-3 + 2]) * gfc->cd_psy->decay; } } /* end of short block sfb loop */ return ath_over; }
/* Calculate the allowed distortion for each scalefactor band, as determined by the psychoacoustic model. xmin(sb) = ratio(sb) * en(sb) / bw(sb) returns number of sfb's with energy > ATH */ static int calc_xmin_(lame_internal_flags const *gfc, III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * pxmin) { SessionConfig_t const *const cfg = &gfc->cfg; int sfb, gsfb, j = 0, ath_over = 0, k; ATH_t const *const ATH = gfc->ATH; const FLOAT *const xr = cod_info->xr; int max_nonzero; FLOAT masking_lower = gfc->sv_qnt.masking_lower; for (gsfb = 0; gsfb < cod_info->psy_lmax; gsfb++) { FLOAT en0, xmin; int width, l; if (cfg->vbr == vbr_rh) xmin = athAdjust(ATH->adjust, ATH->l[gsfb], ATH->floor); else xmin = ATH->adjust * ATH->l[gsfb]; en0 = 0.0; width = cod_info->width[gsfb]; for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; } if (en0 > xmin) ath_over++; if (!cfg->ATHonly) { FLOAT const e = ratio->en.l[gsfb]; if (e > 0.0f) { FLOAT x; x = en0 * ratio->thm.l[gsfb] * masking_lower / e; if (xmin < x) xmin = x; } } *pxmin++ = xmin * gfc->sv_qnt.longfact[gsfb]; } /* end of long block loop */ /*use this function to determine the highest non-zero coeff */ max_nonzero = 575; if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ k = 576; while (k-- && EQ(xr[k], 0)) { max_nonzero = k; } } cod_info->max_nonzero_coeff = max_nonzero; for (sfb = cod_info->sfb_smin; gsfb < cod_info->psymax; sfb++, gsfb += 3) { int width, b, l; FLOAT tmpATH; if (cfg->vbr == vbr_rh) tmpATH = athAdjust(ATH->adjust, ATH->s[sfb], ATH->floor); else tmpATH = ATH->adjust * ATH->s[sfb]; width = cod_info->width[gsfb]; for (b = 0; b < 3; b++) { FLOAT en0 = 0.0, xmin; for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; } if (en0 > tmpATH) ath_over++; xmin = tmpATH; if (!cfg->ATHonly && !cfg->ATHshort) { FLOAT const e = ratio->en.s[sfb][b]; if (e > 0.0f) { FLOAT x; x = en0 * ratio->thm.s[sfb][b] * masking_lower / e; if (xmin < x) xmin = x; } } *pxmin++ = xmin * gfc->sv_qnt.shortfact[sfb]; } /* b */ if (cfg->use_temporal_masking_effect) { if (pxmin[-3] > pxmin[-3 + 1]) pxmin[-3 + 1] += (pxmin[-3] - pxmin[-3 + 1]) * gfc->cd_psy->decay; if (pxmin[-3 + 1] > pxmin[-3 + 2]) pxmin[-3 + 2] += (pxmin[-3 + 1] - pxmin[-3 + 2]) * gfc->cd_psy->decay; } } /* end of short block sfb loop */ return ath_over; }
static int calc_xmin_new(lame_internal_flags const *gfc, III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * pxmin) { SessionConfig_t const *const cfg = &gfc->cfg; int sfb, gsfb, j = 0, ath_over = 0, k; ATH_t const *const ATH = gfc->ATH; const FLOAT *const xr = cod_info->xr; int max_nonzero; for (gsfb = 0; gsfb < cod_info->psy_lmax; gsfb++) { FLOAT en0, xmin; FLOAT rh1, rh2; int width, l; xmin = athAdjust(ATH->adjust, ATH->l[gsfb], ATH->floor); width = cod_info->width[gsfb]; rh1 = xmin / width; #ifdef DBL_EPSILON rh2 = DBL_EPSILON; #else rh2 = 2.2204460492503131e-016; #endif en0 = 0.0; for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; rh2 += (x2 < rh1) ? x2 : rh1; } if (en0 > xmin) ath_over++; if (gsfb == SBPSY_l) { FLOAT x = xmin * gfc->sv_qnt.longfact[gsfb]; if (rh2 < x) { rh2 = x; } } xmin = rh2; if (!cfg->ATHonly) { FLOAT const e = ratio->en.l[gsfb]; if (e > 0.0f) { FLOAT x; x = en0 * ratio->thm.l[gsfb] / e; x *= gfc->sv_qnt.longfact[gsfb]; if (xmin < x) xmin = x; } } *pxmin++ = xmin; } /* end of long block loop */ /*use this function to determine the highest non-zero coeff */ max_nonzero = 575; if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ k = 576; while (k-- && EQ(xr[k], 0)) { max_nonzero = k; } } cod_info->max_nonzero_coeff = max_nonzero; for (sfb = cod_info->sfb_smin; gsfb < cod_info->psymax; sfb++, gsfb += 3) { int width, b, l; FLOAT tmpATH; tmpATH = athAdjust(ATH->adjust, ATH->s[sfb], ATH->floor); width = cod_info->width[gsfb]; for (b = 0; b < 3; b++) { FLOAT en0 = 0.0, xmin; FLOAT rh1, rh2; rh1 = tmpATH / width; #ifdef DBL_EPSILON rh2 = DBL_EPSILON; #else rh2 = 2.2204460492503131e-016; #endif for (l = 0; l < width; ++l) { FLOAT const xa = xr[j++]; FLOAT const x2 = xa * xa; en0 += x2; rh2 += (x2 < rh1) ? x2 : rh1; } if (en0 > tmpATH) ath_over++; if (sfb == SBPSY_s) { FLOAT x = tmpATH * gfc->sv_qnt.shortfact[sfb]; if (rh2 < x) { rh2 = x; } } xmin = rh2; if (!cfg->ATHonly && !cfg->ATHshort) { FLOAT const e = ratio->en.s[sfb][b]; if (e > 0.0f) { FLOAT x; x = en0 * ratio->thm.s[sfb][b] / e; x *= gfc->sv_qnt.shortfact[sfb]; if (xmin < x) xmin = x; } } *pxmin++ = xmin; } /* b */ if (cfg->use_temporal_masking_effect) { if (pxmin[-3] > pxmin[-3 + 1]) pxmin[-3 + 1] += (pxmin[-3] - pxmin[-3 + 1]) * gfc->cd_psy->decay; if (pxmin[-3 + 1] > pxmin[-3 + 2]) pxmin[-3 + 2] += (pxmin[-3 + 1] - pxmin[-3 + 2]) * gfc->cd_psy->decay; } } /* end of short block sfb loop */ return ath_over; }
/* Calculate the allowed distortion for each scalefactor band, as determined by the psychoacoustic model. xmin(sb) = ratio(sb) * en(sb) / bw(sb) returns number of sfb's with energy > ATH */ int calc_xmin( lame_global_flags *gfp, const III_psy_ratio * const ratio, const gr_info * const cod_info, III_psy_xmin * const l3_xmin ) { lame_internal_flags *gfc = gfp->internal_flags; int sfb, j=0, ath_over=0; FLOAT8 xmin, tmpATH; ATH_t * ATH = gfc->ATH; const FLOAT8 *xr = cod_info->xr; for (sfb = 0; sfb < cod_info->psy_lmax; sfb++) { FLOAT en0 = 0.0; int width, l; if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) tmpATH = athAdjust( ATH->adjust, ATH->l[sfb], ATH->floor ); else tmpATH = ATH->adjust * ATH->l[sfb]; width = gfc->scalefac_band.l[sfb+1] - gfc->scalefac_band.l[sfb]; l = width; do { en0 += xr[j] * xr[j]; j++; } while (--l > 0); /* why is it different from short blocks <?> */ if ( !gfc->nsPsy.use ) en0 /= width; xmin = tmpATH; if (!gfp->ATHonly) { xmin = ratio->en.l[sfb]; if (xmin > 0.0) xmin = en0 * ratio->thm.l[sfb] * gfc->masking_lower / xmin; if (xmin < tmpATH) xmin = tmpATH; } /* why is it different from short blocks <?> */ if ( !gfc->nsPsy.use ) { xmin *= width; } else { if (sfb <= 6) xmin *= gfc->nsPsy.bass; else if (sfb <= 13) xmin *= gfc->nsPsy.alto; else if (sfb <= 20) xmin *= gfc->nsPsy.treble; else xmin *= gfc->nsPsy.sfb21; if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) xmin *= 0.001; } l3_xmin->l[sfb] = xmin; if (en0 > tmpATH) ath_over++; } /* end of long block loop */ for (sfb = cod_info->sfb_smin; sfb < cod_info->psy_smax; sfb++) { int width, b; if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) tmpATH = athAdjust( ATH->adjust, ATH->s[sfb], ATH->floor ); else tmpATH = ATH->adjust * ATH->s[sfb]; width = gfc->scalefac_band.s[sfb+1] - gfc->scalefac_band.s[sfb]; for ( b = 0; b < 3; b++ ) { FLOAT en0 = 0.0; int l = width; do { en0 += xr[j] * xr[j]; j++; } while (--l > 0); en0 /= width; xmin = tmpATH; if (!gfp->ATHonly && !gfp->ATHshort) { xmin = ratio->en.s[sfb][b]; if (xmin > 0.0) xmin = en0 * ratio->thm.s[sfb][b] * gfc->masking_lower / xmin; if (xmin < tmpATH) xmin = tmpATH; } xmin *= width; if (gfc->nsPsy.use) { if (sfb <= 5) xmin *= gfc->nsPsy.bass; else if (sfb <= 10) xmin *= gfc->nsPsy.alto; else xmin *= gfc->nsPsy.treble; if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) xmin *= 0.001; } l3_xmin->s[sfb][b] = xmin; if (en0 > tmpATH) ath_over++; } /* b */ if (gfp->useTemporal) { for ( b = 1; b < 3; b++ ) { xmin = l3_xmin->s[sfb][b] * (1.0 - gfc->decay) + l3_xmin->s[sfb][b-1] * gfc->decay; if (l3_xmin->s[sfb][b] < xmin) l3_xmin->s[sfb][b] = xmin; } } /* sfb */ } /* end of short block loop */ return ath_over; }