예제 #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;
  }
예제 #2
0
  private void compute_ath(final LameGlobalFlags gfp) {
    final float[] ATH_l = gfp.internal_flags.ATH.l;
    final float[] ATH_psfb21 = gfp.internal_flags.ATH.psfb21;
    final float[] ATH_s = gfp.internal_flags.ATH.s;
    final float[] ATH_psfb12 = gfp.internal_flags.ATH.psfb12;
    final LameInternalFlags gfc = gfp.internal_flags;
    final float samp_freq = gfp.getOutSampleRate();

    for (int sfb = 0; sfb < Encoder.SBMAX_l; sfb++) {
      int start = gfc.scalefac_band.l[sfb];
      int end = gfc.scalefac_band.l[sfb + 1];
      ATH_l[sfb] = Float.MAX_VALUE;
      for (int i = start; i < end; i++) {
        final float freq = i * samp_freq / (2 * 576);
        float ATH_f = ATHmdct(gfp, freq); /* freq in kHz */
        ATH_l[sfb] = Math.min(ATH_l[sfb], ATH_f);
      }
    }

    for (int sfb = 0; sfb < Encoder.PSFB21; sfb++) {
      int start = gfc.scalefac_band.psfb21[sfb];
      int end = gfc.scalefac_band.psfb21[sfb + 1];
      ATH_psfb21[sfb] = Float.MAX_VALUE;
      for (int i = start; i < end; i++) {
        final float freq = i * samp_freq / (2 * 576);
        float ATH_f = ATHmdct(gfp, freq); /* freq in kHz */
        ATH_psfb21[sfb] = Math.min(ATH_psfb21[sfb], ATH_f);
      }
    }

    for (int sfb = 0; sfb < Encoder.SBMAX_s; sfb++) {
      int start = gfc.scalefac_band.s[sfb];
      int end = gfc.scalefac_band.s[sfb + 1];
      ATH_s[sfb] = Float.MAX_VALUE;
      for (int i = start; i < end; i++) {
        final float freq = i * samp_freq / (2 * 192);
        float ATH_f = ATHmdct(gfp, freq); /* freq in kHz */
        ATH_s[sfb] = Math.min(ATH_s[sfb], ATH_f);
      }
      ATH_s[sfb] *= (gfc.scalefac_band.s[sfb + 1] - gfc.scalefac_band.s[sfb]);
    }

    for (int sfb = 0; sfb < Encoder.PSFB12; sfb++) {
      int start = gfc.scalefac_band.psfb12[sfb];
      int end = gfc.scalefac_band.psfb12[sfb + 1];
      ATH_psfb12[sfb] = Float.MAX_VALUE;
      for (int i = start; i < end; i++) {
        final float freq = i * samp_freq / (2 * 192);
        float ATH_f = ATHmdct(gfp, freq); /* freq in kHz */
        ATH_psfb12[sfb] = Math.min(ATH_psfb12[sfb], ATH_f);
      }
      /* not sure about the following */
      ATH_psfb12[sfb] *= (gfc.scalefac_band.s[13] - gfc.scalefac_band.s[12]);
    }

    /*
     * no-ATH mode: reduce ATH to -200 dB
     */
    if (gfp.noATH) {
      for (int sfb = 0; sfb < Encoder.SBMAX_l; sfb++) {
        ATH_l[sfb] = 1E-20f;
      }
      for (int sfb = 0; sfb < Encoder.PSFB21; sfb++) {
        ATH_psfb21[sfb] = 1E-20f;
      }
      for (int sfb = 0; sfb < Encoder.SBMAX_s; sfb++) {
        ATH_s[sfb] = 1E-20f;
      }
      for (int sfb = 0; sfb < Encoder.PSFB12; sfb++) {
        ATH_psfb12[sfb] = 1E-20f;
      }
    }

    /*
     * work in progress, don't rely on it too much
     */
    gfc.ATH.floor = 10.f * (float) Math.log10(ATHmdct(gfp, -1.f));
  }