package sound;

abstract class Ulaw {
  private final static int uBIAS = 0x84;
  private final static int uCLIP = 32635;
  private final static int ACLIP = 31744;
  private final static int maxSample = 8031;

  // 8 elements
  private final static int
      exp2[] = {0, 132, 396, 924, 1980,
                4092, 8316, 16764};


  // 256 elements
  private final static int
      exp_lut[] = {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
                   4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
                   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
                   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
                   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};


  // make an 8 bit byte u-law encoding of
  // x. X is restricted to 0<|x|<1
  public static byte toUlaw(double x) {
    // max allowed by 8-bit ulaw encoder is uCLIP
    x = x * uCLIP;
    // cast x as an int to change the signature of
    // the invoked method
    return ((byte) toUlaw((int) x));
  }


  public static byte toUlaw(int sample) {

    int sign;
    int exponent;
    int mantissa;
    byte ulawbyte;


    if (Math.abs(sample) >= 1) {
      System.out.println("X is not well conditioned in Ulaw.java");
    }

    /* Get the sample into sign-magnitude. */
    sign = (sample >> 8) & 0x80;        /* set aside the sign */
    if (sign != 0) sample = -sample;        /* get magnitude */
    if (sample > uCLIP) sample = uCLIP;     /* clip the magnitude */

    /* Convert from 16 bit linear to ulaw. */
    sample = sample + uBIAS;
    exponent = exp_lut[(sample >> 7) & 0xFF];
    mantissa = (sample >> (exponent + 3)) & 0x0F;
    ulawbyte = (byte) ~(sign | (exponent << 4) | mantissa);
    return ulawbyte;
  }

  public static double ulawToDouble(byte ulawbyte) {
    return (double) ulawToLinear(ulawbyte) / uCLIP;
  }

  public static int ulawToLinear(byte ulawbyte) {

    int sign, exponent, mantissa, sample;
    ulawbyte = (byte) ~ulawbyte;
    sign = (ulawbyte & 0x80);
    exponent = (ulawbyte >> 4) & 0x07;
    mantissa = ulawbyte & 0x0F;
    sample = exp2[exponent] + (mantissa << (exponent + 3));
    if (sign != 0) sample = -sample;

    return sample;
  }


}