Ejemplo n.º 1
0
  /**
   * Calculate the allowed distortion for each scalefactor band, as determined by the psychoacoustic
   * model. xmin(sb) = ratio(sb) * en(sb) / bw(sb)
   *
   * <p>returns number of sfb's with energy > ATH
   */
  public final int calc_xmin(
      final LameGlobalFlags gfp,
      final III_psy_ratio ratio,
      final GrInfo cod_info,
      final float[] pxmin) {
    int pxminPos = 0;
    final LameInternalFlags gfc = gfp.internal_flags;
    int gsfb, j = 0, ath_over = 0;
    final ATH ATH = gfc.ATH;
    final float[] xr = cod_info.xr;
    final int enable_athaa_fix = (gfp.getVBR() == VbrMode.vbr_mtrh) ? 1 : 0;
    float masking_lower = gfc.masking_lower;

    if (gfp.getVBR() == VbrMode.vbr_mtrh || gfp.getVBR() == VbrMode.vbr_mt) {
      /* was already done in PSY-Model */
      masking_lower = 1.0f;
    }

    for (gsfb = 0; gsfb < cod_info.psy_lmax; gsfb++) {
      float en0, xmin;
      float rh1, rh2;
      int width, l;

      if (gfp.getVBR() == VbrMode.vbr_rh || gfp.getVBR() == VbrMode.vbr_mtrh)
        xmin = athAdjust(ATH.adjust, ATH.l[gsfb], ATH.floor);
      else xmin = ATH.adjust * ATH.l[gsfb];

      width = cod_info.width[gsfb];
      rh1 = xmin / width;
      rh2 = DBL_EPSILON;
      l = width >> 1;
      en0 = 0.0f;
      do {
        float xa, xb;
        xa = xr[j] * xr[j];
        en0 += xa;
        rh2 += (xa < rh1) ? xa : rh1;
        j++;
        xb = xr[j] * xr[j];
        en0 += xb;
        rh2 += (xb < rh1) ? xb : rh1;
        j++;
      } while (--l > 0);
      if (en0 > xmin) ath_over++;

      if (gsfb == Encoder.SBPSY_l) {
        float x = xmin * gfc.nsPsy.longfact[gsfb];
        if (rh2 < x) {
          rh2 = x;
        }
      }
      if (enable_athaa_fix != 0) {
        xmin = rh2;
      }
      if (!gfp.ATHonly) {
        final float e = ratio.en.l[gsfb];
        if (e > 0.0f) {
          float x;
          x = en0 * ratio.thm.l[gsfb] * masking_lower / e;
          if (enable_athaa_fix != 0) x *= gfc.nsPsy.longfact[gsfb];
          if (xmin < x) xmin = x;
        }
      }
      if (enable_athaa_fix != 0) pxmin[pxminPos++] = xmin;
      else pxmin[pxminPos++] = xmin * gfc.nsPsy.longfact[gsfb];
    } /* end of long block loop */

    /* use this function to determine the highest non-zero coeff */
    int max_nonzero = 575;
    if (cod_info.block_type != Encoder.SHORT_TYPE) {
      // NORM, START or STOP type, but not SHORT
      int k = 576;
      while (k-- != 0 && BitStream.EQ(xr[k], 0)) {
        max_nonzero = k;
      }
    }
    cod_info.max_nonzero_coeff = max_nonzero;

    for (int sfb = cod_info.sfb_smin; gsfb < cod_info.psymax; sfb++, gsfb += 3) {
      int width, b;
      float tmpATH;
      if (gfp.getVBR() == VbrMode.vbr_rh || gfp.getVBR() == VbrMode.vbr_mtrh)
        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.0f, xmin;
        float rh1, rh2;
        int l = width >> 1;

        rh1 = tmpATH / width;
        rh2 = DBL_EPSILON;
        do {
          float xa, xb;
          xa = xr[j] * xr[j];
          en0 += xa;
          rh2 += (xa < rh1) ? xa : rh1;
          j++;
          xb = xr[j] * xr[j];
          en0 += xb;
          rh2 += (xb < rh1) ? xb : rh1;
          j++;
        } while (--l > 0);
        if (en0 > tmpATH) ath_over++;
        if (sfb == Encoder.SBPSY_s) {
          float x = tmpATH * gfc.nsPsy.shortfact[sfb];
          if (rh2 < x) {
            rh2 = x;
          }
        }
        if (enable_athaa_fix != 0) xmin = rh2;
        else xmin = tmpATH;

        if (!gfp.ATHonly && !gfp.ATHshort) {
          final float e = ratio.en.s[sfb][b];
          if (e > 0.0f) {
            float x;
            x = en0 * ratio.thm.s[sfb][b] * masking_lower / e;
            if (enable_athaa_fix != 0) x *= gfc.nsPsy.shortfact[sfb];
            if (xmin < x) xmin = x;
          }
        }
        if (enable_athaa_fix != 0) pxmin[pxminPos++] = xmin;
        else pxmin[pxminPos++] = xmin * gfc.nsPsy.shortfact[sfb];
      } /* b */
      if (gfp.useTemporal) {
        if (pxmin[pxminPos - 3] > pxmin[pxminPos - 3 + 1])
          pxmin[pxminPos - 3 + 1] += (pxmin[pxminPos - 3] - pxmin[pxminPos - 3 + 1]) * gfc.decay;
        if (pxmin[pxminPos - 3 + 1] > pxmin[pxminPos - 3 + 2])
          pxmin[pxminPos - 3 + 2] +=
              (pxmin[pxminPos - 3 + 1] - pxmin[pxminPos - 3 + 2]) * gfc.decay;
      }
    } /* end of short block sfb loop */

    return ath_over;
  }