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

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

There is a newer version: 1.0.2-jitsi
Show newest version
package net.sf.fmj.media.codec.audio.alaw;

import com.lti.utils.*;

/**
 * Turns 16-bit linear PCM values into 8-bit A-law bytes. Adapted from code by
 * Marc Sweetgall at http://www.codeproject.com/csharp/g711audio.asp
 */
public class ALawEncoderUtil
{
    public static final int MAX = 0x7fff; // maximum that can be held in 15 bits

    /**
     * An array where the index is the 16-bit PCM input, and the value is the
     * a-law result.
     */
    private static byte[] pcmToALawMap;

    static
    {
        pcmToALawMap = new byte[65536];
        for (int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++)
            pcmToALawMap[UnsignedUtils.uShortToInt((short) i)] = encode(i);
    }

    /**
     * Encode an array of pcm values into a pre-allocated target array
     *
     * @param data
     *            An array of bytes in Little-Endian format
     * @param target
     *            A pre-allocated array to receive the A-law bytes. This array
     *            must be at least half the size of the source.
     */
    public static void aLawEncode(boolean bigEndian, byte[] data, int offset,
            int length, byte[] target)
    {
        if (bigEndian)
            aLawEncodeBigEndian(data, offset, length, target);
        else
            aLawEncodeLittleEndian(data, offset, length, target);
    }

    /**
     * Encode a pcm value into a a-law byte
     *
     * @param pcm
     *            A 16-bit pcm value
     * @return A a-law encoded byte
     */
    public static byte aLawEncode(int pcm)
    {
        return pcmToALawMap[UnsignedUtils.uShortToInt((short) (pcm & 0xffff))];
    }

    /**
     * Encode a pcm value into a a-law byte
     *
     * @param pcm
     *            A 16-bit pcm value
     * @return A a-law encoded byte
     */
    public static byte aLawEncode(short pcm)
    {
        return pcmToALawMap[UnsignedUtils.uShortToInt(pcm)];
    }

    // /**
    // * Encode an array of pcm values
    // *
    // * @param data An array of 16-bit pcm values
    // * @parem encoded An array to be filled with a-law bytes containing the
    // results. must be same size as data.
    // */
    // public static void aLawEncode(int[] data, byte[] encoded)
    // {
    // int size = data.length;
    // //byte[] encoded = new byte[size];
    // for (int i = 0; i < size; i++)
    // encoded[i] = aLawEncode(data[i]);
    // //return encoded;
    // }
    //
    // /**
    // * Encode an array of pcm values
    // *
    // * @param data An array of 16-bit pcm values
    // * @parem encoded An array to be filled with a-law bytes containing the
    // results. must be same size as data.
    // */
    // public static void aLawEncode(short[] data, byte[] encoded)
    // {
    // int size = data.length;
    // //byte[] encoded = new byte[size];
    // for (int i = 0; i < size; i++)
    // encoded[i] = aLawEncode(data[i]);
    // //return encoded;
    // }
    //
    // /**
    // * Encode an array of pcm values
    // *
    // * @param data An array of bytes in Little-Endian format
    // * @return An array of a-law bytes containing the results
    // */
    // public static byte[] aLawEncode(byte[] data)
    // {
    // int size = data.length / 2;
    // byte[] encoded = new byte[size];
    // for (int i = 0; i < size; i++)
    // encoded[i] = aLawEncode((data[2 * i + 1] << 8) | data[2 * i]);
    // return encoded;
    // }

    public static void aLawEncodeBigEndian(byte[] data, int offset, int length,
            byte[] target)
    {
        int size = length / 2;
        for (int i = 0; i < size; i++)
            target[i] = aLawEncode(((data[offset + 2 * i + 1]) & 0xff)
                    | ((data[offset + 2 * i] & 0xff) << 8));
    }

    public static void aLawEncodeLittleEndian(byte[] data, int offset,
            int length, byte[] target)
    {
        int size = length / 2;
        for (int i = 0; i < size; i++)
            target[i] = aLawEncode(((data[offset + 2 * i + 1] & 0xff) << 8)
                    | (data[offset + 2 * i]) & 0xff);
    }

    /**
     * Encode one a-law byte from a 16-bit signed integer. Internal use only.
     *
     * @param pcm
     *            A 16-bit signed pcm value
     * @return A a-law encoded byte
     */
    private static byte encode(int pcm)
    {
        // Get the sign bit. Shift it for later use without further modification
        int sign = (pcm & 0x8000) >> 8;
        // If the number is negative, make it positive (now it's a magnitude)
        if (sign != 0)
            pcm = -pcm;
        // The magnitude must fit in 15 bits to avoid overflow
        if (pcm > MAX)
            pcm = MAX;

        /*
         * Finding the "exponent" Bits: 1 2 3 4 5 6 7 8 9 A B C D E F G S 7 6 5
         * 4 3 2 1 0 0 0 0 0 0 0 0 We want to find where the first 1 after the
         * sign bit is. We take the corresponding value from the second row as
         * the exponent value. (i.e. if first 1 at position 7 -> exponent = 2)
         * The exponent is 0 if the 1 is not found in bits 2 through 8. This
         * means the exponent is 0 even if the "first 1" doesn't exist.
         */
        int exponent = 7;
        // Move to the right and decrement exponent until we hit the 1 or the
        // exponent hits 0
        for (int expMask = 0x4000; (pcm & expMask) == 0 && exponent > 0; exponent--, expMask >>= 1)
        {
        }

        /*
         * The last part - the "mantissa" We need to take the four bits after
         * the 1 we just found. To get it, we shift 0x0f : 1 2 3 4 5 6 7 8 9 A B
         * C D E F G S 0 0 0 0 0 1 . . . . . . . . . (say that exponent is 2) .
         * . . . . . . . . . . . 1 1 1 1 We shift it 5 times for an exponent of
         * two, meaning we will shift our four bits (exponent + 3) bits. For
         * convenience, we will actually just shift the number, then AND with
         * 0x0f.
         *
         * NOTE: If the exponent is 0: 1 2 3 4 5 6 7 8 9 A B C D E F G S 0 0 0 0
         * 0 0 0 Z Y X W V U T S (we know nothing about bit 9) . . . . . . . . .
         * . . . 1 1 1 1 We want to get ZYXW, which means a shift of 4 instead
         * of 3
         */
        int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f;

        // The a-law byte bit arrangement is SEEEMMMM (Sign, Exponent, and
        // Mantissa.)
        byte alaw = (byte) (sign | exponent << 4 | mantissa);

        // Last is to flip every other bit, and the sign bit (0xD5 = 1101 0101)
        return (byte) (alaw ^ 0xD5);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy