All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.fmj.media.codec.audio.alaw.ALawDecoderUtil Maven / Gradle / Ivy

package net.sf.fmj.media.codec.audio.alaw;

/**
 * Turns 8-bit A-law bytes back into 16-bit PCM values.
 *
 * Adapted from code by Marc Sweetgall at
 * http://www.codeproject.com/csharp/g711audio.asp
 */
public class ALawDecoderUtil
{
    /**
     * An array where the index is the a-law input, and the value is the 16-bit
     * PCM result.
     *
     */
    private static short[] aLawToPcmMap;

    static
    {
        aLawToPcmMap = new short[256];
        for (int i = 0; i < aLawToPcmMap.length; i++)
            aLawToPcmMap[i] = decode((byte) i);
    }

    public static void aLawDecode(boolean bigEndian, byte[] data, int offset,
            int length, byte[] decoded)
    {
        if (bigEndian)
            aLawDecodeBigEndian(data, offset, length, decoded);
        else
            aLawDecodeLittleEndian(data, offset, length, decoded);
    }

    /**
     * Decode one a-law byte
     *
     * @param alaw
     *            The encoded a-law byte
     * @return A short containing the 16-bit result
     */
    public static short aLawDecode(byte alaw)
    {
        return aLawToPcmMap[alaw & 0xff];
    }

    // /**
    // * Decode an array of a-law encoded bytes
    // *
    // * @param data An array of a-law encoded bytes
    // * @return An array of shorts containing the results
    // */
    // public static short[] aLawDecode(byte[] data)
    // {
    // int size = data.length;
    // short[] decoded = new short[size];
    // for (int i = 0; i < size; i++)
    // decoded[i] = aLawToPcmMap[data[i]];
    // return decoded;
    // }
    //
    // /**
    // * Decode an array of a-law encoded bytes
    // *
    // * @param data An array of a-law encoded bytes
    // * @param decoded An array of shorts containing the results
    // * Same as the other method that returns an array of shorts
    // */
    // public static void aLawDecode(byte[] data, short[] decoded)
    // {
    // int size = data.length;
    // for (int i = 0; i < size; i++)
    // decoded[i] = aLawToPcmMap[data[i] & 0xff];
    // }

    public static void aLawDecodeBigEndian(byte[] data, int offset, int length,
            byte[] decoded)
    {
        int size = length;
        for (int i = 0; i < size; i++)
        {
            decoded[2 * i + 1] = (byte) (aLawToPcmMap[data[offset + i] & 0xff] & 0xff);
            decoded[2 * i] = (byte) (aLawToPcmMap[data[offset + i] & 0xff] >> 8);
        }
    }

    /**
     * Decode an array of a-law encoded bytes
     *
     * @param data
     *            An array of a-law encoded bytes
     * @param decoded
     *            An array of bytes in Little-Endian format containing the
     *            results. Should be twice as big as data.
     */
    public static void aLawDecodeLittleEndian(byte[] data, int offset,
            int length, byte[] decoded)
    {
        int size = length;
        for (int i = 0; i < size; i++)
        {
            // First byte is the less significant byte
            decoded[2 * i] = (byte) (aLawToPcmMap[data[offset + i] & 0xff] & 0xff);
            // Second byte is the more significant byte
            decoded[2 * i + 1] = (byte) (aLawToPcmMap[data[offset + i] & 0xff] >> 8);
        }
    }

    /**
     * Decode one a-law byte. For internal use only.
     *
     * @param alaw
     *            The encoded a-law byte
     * @return A short containing the 16-bit result
     */
    private static short decode(byte alaw)
    {
        // Invert every other bit, and the sign bit (0xD5 = 1101 0101)
        alaw ^= 0xD5;

        // Pull out the value of the sign bit
        int sign = alaw & 0x80;
        // Pull out and shift over the value of the exponent
        int exponent = (alaw & 0x70) >> 4;
        // Pull out the four bits of data
        int data = alaw & 0x0f;

        // Shift the data four bits to the left
        data <<= 4;
        // Add 8 to put the result in the middle of the range (like adding a
        // half)
        data += 8;

        // If the exponent is not 0, then we know the four bits followed a 1,
        // and can thus add this implicit 1 with 0x100.
        if (exponent != 0)
            data += 0x100;
        /*
         * Shift the bits to where they need to be: left (exponent - 1) places
         * Why (exponent - 1) ? 1 2 3 4 5 6 7 8 9 A B C D E F G . 7 6 5 4 3 2 1
         * . . . . . . . . <-- starting bit (based on exponent) . . . . . . . Z
         * x x x x 1 0 0 0 <-- our data (Z is 0 only when exponent is 0) We need
         * to move the one under the value of the exponent, which means it must
         * move (exponent - 1) times It also means shifting is unnecessary if
         * exponent is 0 or 1.
         */
        if (exponent > 1)
            data <<= (exponent - 1);

        return (short) (sign == 0 ? data : -data);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy