G711Utils.java 2.07 KB
package com.genersoft.iot.vmp.utils;

public class G711Utils {
    private final static int SIGN_BIT = 0x80;
    private final static int QUANT_MASK = 0xf;
    private final static int NSEGS = 8;
    private final static int SEG_MASK = 0x70;
    private final static int SEG_SHIFT = 4;
    private final static int[] seg_uend = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};

    public static byte[] encodeA(byte[] pcm) {
        byte[] table = new byte[pcm.length / 2];
        for (int i = 0, j = 0; i < pcm.length; i += 2, j++) {
            // [核心修复] 尝试交换高低位 (杂音修复)
            // 方案 A: 假设输入是 Little Endian (JTT1078标准) -> 这里的写法是对的
            // 方案 B: 如果还是杂音,很可能你的 PCM 是 Big Endian,需要交换 pcm[i] 和 pcm[i+1]

            // 下面这是 JTT1078 常见的 Little Endian 处理方式:
            // pcm[i] 是低位, pcm[i+1] 是高位
            short s = (short) ((pcm[i] & 0xff) | (pcm[i + 1] << 8));

            // [调试] 如果依然杂音刺耳,请注释掉上面一行,换成下面这行测试:
            // short s = (short) ((pcm[i] << 8) | (pcm[i + 1] & 0xff));

            table[j] = linear2alaw(s);
        }
        return table;
    }

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

        if (pcm_val >= 0) {
            mask = 0xD5;
        } else {
            mask = 0x55;
            pcm_val = (short) (-pcm_val - 8);
        }

        if (pcm_val < 0) {
            pcm_val = 32767;
        }

        seg = 8;
        for (int i = 0; i < NSEGS; i++) {
            if (pcm_val <= seg_uend[i]) {
                seg = i;
                break;
            }
        }

        if (seg >= 8)
            return (byte) (0x7F ^ mask);
        else {
            aval = (byte) (seg << SEG_SHIFT);
            if (seg < 2)
                aval |= (pcm_val >> 4) & QUANT_MASK;
            else
                aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
            return (byte) (aval ^ mask);
        }
    }
}