PCM、PCMA和PCMU之间区别与转换

一、三者优缺点

1. PCM

优点:压缩比小(CD音质>400kbps),编解码延时短
缺点:声音质量一般

2. PCMA

优点:语音质量优
缺点:占用的带宽较高

3. PCMU

优点:语音质量优(PCMU>PCMA)
缺点:占用的带宽较高

二、相互转换

获取原始录音字节流数据并转换成相应音频格式编码的字节数据

PCM转PCMA

static byte linear2alaw(short pcm_val){
        short mask;
        short seg;
        char aval;
        if(pcm_val >= 0){
            mask = 0xD5;
        }else{
            mask = 0x55;
            pcm_val = (short) (-pcm_val - 1);
            if(pcm_val < 0){
                pcm_val = 32767;
            }
        }

        /* Convert the scaled magnitude to segment number. */
        seg = search(pcm_val, seg_end, (short) 8);

        /* Combine the sign, segment, and quantization bits. */

        if (seg >= 8)       /* out of range, return maximum value. */
            return (byte) (0x7F ^ mask);
        else {
            aval = (char) (seg << SEG_SHIFT);
            if (seg < 2)
                aval |= (pcm_val >> 4) & QUANT_MASK;
            else
                aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
            return (byte) (aval ^ mask);
        }
    }

PCM转PCMU

 static byte linear2ulaw(short pcm_val)    /* 2's complement (16-bit range) */
    {
        int	        mask;
        int	        seg;
        char       uval;

        /* Get the sign and the magnitude of the value. */
       // pcm_val = (short) (pcm_val >> 2);
        if (pcm_val < 0) {
            pcm_val = (short) -pcm_val;
            mask = 0x7F;
        } else {
            mask = 0xFF;
        }
        if (pcm_val > CLIP ) pcm_val = CLIP;        /* clip the magnitude 削波*/
        pcm_val += (BIAS >> 2);

        /* Convert the scaled magnitude to segment number. */
        seg = search(pcm_val, seg_end, (short) 8);

        /*
         * Combine the sign, segment, quantization bits;
         * and complement the code word.
         */
        if (seg >= 8)        /* out of range, return maximum value. */
            return (byte) (0x7F ^ mask);
        else {
            uval =  (char) ((seg << 4) | ((pcm_val >> (seg + 3)) & 0xF));
            return (byte) (uval ^ mask);
        }
    }

工具类如下:

public class G711Code {
    private final static int SIGN_BIT = 0x80;
    private final static int QUANT_MASK = 0xf;
    private final static int SEG_SHIFT = 4;
    private final static int SEG_MASK = 0x70;
    private final static int BIAS = 0x84;
    private final static int CLIP = 8159;

    static short[] seg_end = {0xFF, 0x1FF, 0x3FF, 0x7FF,0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};

    static short search(short val,short[] table,short size){

        for (short i = 0 ; i < size; i++) {
            if(val <= table[i]){
                return i;
            }
        }
        return size;
    }

    static byte linear2alaw(short pcm_val){
        short mask;
        short seg;
        char aval;
        if(pcm_val >= 0){
            mask = 0xD5;
        }else{
            mask = 0x55;
            pcm_val = (short) (-pcm_val - 1);
            if(pcm_val < 0){
                pcm_val = 32767;
            }
        }

        /* Convert the scaled magnitude to segment number. */
        seg = search(pcm_val, seg_end, (short) 8);

        /* Combine the sign, segment, and quantization bits. */

        if (seg >= 8)       /* out of range, return maximum value. */
            return (byte) (0x7F ^ mask);
        else {
            aval = (char) (seg << SEG_SHIFT);
            if (seg < 2)
                aval |= (pcm_val >> 4) & QUANT_MASK;
            else
                aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
            return (byte) (aval ^ mask);
        }
    }


    static byte linear2ulaw(short pcm_val)    /* 2's complement (16-bit range) */
    {
        int	        mask;
        int	        seg;
        char       uval;

        /* Get the sign and the magnitude of the value. */
       // pcm_val = (short) (pcm_val >> 2);
        if (pcm_val < 0) {
            pcm_val = (short) -pcm_val;
            mask = 0x7F;
        } else {
            mask = 0xFF;
        }
        if (pcm_val > CLIP ) pcm_val = CLIP;        /* clip the magnitude 削波*/
        pcm_val += (BIAS >> 2);

        /* Convert the scaled magnitude to segment number. */
        seg = search(pcm_val, seg_end, (short) 8);

        /*
         * Combine the sign, segment, quantization bits;
         * and complement the code word.
         */
        if (seg >= 8)        /* out of range, return maximum value. */
            return (byte) (0x7F ^ mask);
        else {
            uval =  (char) ((seg << 4) | ((pcm_val >> (seg + 3)) & 0xF));
            return (byte) (uval ^ mask);
        }
    }


    static short alaw2linear(byte a_val){
        short       t;
        short       seg;

        a_val ^= 0x55;

        t = (short) ((a_val & QUANT_MASK) << 4);
        seg = (short) ((a_val & SEG_MASK) >> SEG_SHIFT);
        switch (seg) {
            case 0:
                t += 8;
                break;
            case 1:
                t += 0x108;
                break;
            default:
                t += 0x108;
                t <<= seg - 1;
        }
        return (a_val & SIGN_BIT) != 0 ? t : (short) -t;
    }

    /**
     * pcm 转 G711 a率
     * @param pcm
     * @param code
     * @param size
     */
    public static void G711aEncoder(short[] pcm,byte[] code,int size){
        for(int i=0;i<size;i++){
            code[i]=linear2alaw(pcm[i]);
            //Log.e("-------------","数据编码");
        }
    }

    /**
     * G.711 转 PCM
     * @param pcm
     * @param code
     * @param size
     */
    public static void G711aDecoder(short[] pcm,byte[] code,int size)
    {
        for(int i=0;i<size;i++){
            pcm[i]=alaw2linear(code[i]);
        }
    }
    /**
     * pcm 转 G711 u率
     * @param pcm
     * @param code
     * @param size
     */
    public static void G711uEncoder(short[] pcm,byte[] code,int size){
        for(int i=0;i<size;i++){
            code[i]=linear2ulaw(pcm[i]);
            //Log.e("-------------","数据编码");
        }
    }
}
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值