ALaw.java 2.22 KB
package com.genersoft.iot.vmp.jtt1078.util;

/**
 * G.711 A-Law 编解码工具类
 */
public class ALaw {

    private static final byte[] ALAW_TABLE = new byte[65536]; // 线性 -> ALaw 查找表
    private static final short[] LINEAR_TABLE = new short[256]; // ALaw -> 线性 查找表

    static {
        // 初始化 ALaw -> Linear 表
        for (int i = 0; i < 256; i++) {
            LINEAR_TABLE[i] = alaw2linear((byte) i);
        }

        // 初始化 Linear -> ALaw 表
        for (int i = -32768; i <= 32767; i++) {
            ALAW_TABLE[i & 0xFFFF] = linear2alaw((short) i);
        }
    }

    /**
     * 将 16bit PCM 压缩为 8bit A-Law (查表法,高性能)
     */
    public static byte encode(short pcm) {
        return ALAW_TABLE[pcm & 0xFFFF];
    }

    /**
     * 将 8bit A-Law 解压为 16bit PCM (查表法,高性能)
     */
    public static short decode(byte alaw) {
        return LINEAR_TABLE[alaw & 0xFF];
    }

    // --- 以下是基础算法实现,用于静态块初始化 ---

    private static final int MAX = 0x7FFF; // 32767

    private static byte linear2alaw(short pcm_val) {
        int mask;
        int seg;
        int aval;

        if (pcm_val >= 0) {
            mask = 0xD5;
        } else {
            mask = 0x55;
            pcm_val = (short) (-pcm_val - 1); // 负数转正数
            if (pcm_val < 0) {
                pcm_val = MAX;
            }
        }

        if (pcm_val < 256) {
            aval = pcm_val >> 4;
        } else {
            seg = 0;
            for (int i = pcm_val; i > 256; i >>= 1) {
                seg++;
            }
            aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0F);
        }
        return (byte) ((aval ^ mask) & 0xFF);
    }

    private static short alaw2linear(byte alaw_val) {
        int t;
        int seg;

        alaw_val ^= 0x55;

        t = (alaw_val & 0x0F) << 4;
        seg = ((int) (alaw_val & 0x70)) >> 4;

        switch (seg) {
            case 0:
                t += 8;
                break;
            case 1:
                t += 0x108;
                break;
            default:
                t += 0x108;
                t <<= seg - 1;
        }

        return (short) ((alaw_val & 0x80) == 0 ? t : -t);
    }
}