美文网首页音频
G711音频编码

G711音频编码

作者: MiHuASAMA | 来源:发表于2017-06-01 14:29 被阅读0次
    原理

    PCM是对模拟的连续信号进行抽样。
    G711则是对PCM数据进行再一次的抽样。
    G711主要是对16bit的PCM进行抽样,取到PCM的高位数据,去掉低位的数据,并且只保留8位。这样压缩的比率就达到了2:1。可知是有损压缩。

    这里主要讨论G711a.
    编码过程
    bit: 0--1--2--3--4--5--6--7--8--9--10--11--12--13--14--15
         0----符号位s
     *  Linear Input Code   Compressed Code
     *  ---------------------------------------
     *  0000000wxyza            000wxyz
     *  0000001wxyza            001wxyz
     *  000001wxyzab            010wxyz
     *  00001wxyzabc            011wxyz
     *  0001wxyzabcd            100wxyz
     *  001wxyzabcde            101wxyz
     *  01wxyzabcdef            110wxyz
     *  1wxyzabcdefg            111wxyz
    接下来的部分就是寻找声音的强度位。
    按上表,共有8个级别。
    标记为seg。
    然后取强度位之后的4位作为样本位wxyz
    最终经过编码以后
    就变成了:s(取反)+3位强度位+4位样本位总共8位数据。
    
    代码
    //强度表
    static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF};
    //寻找当前的强度位,其实就是前八位的匹配
    /*前八位可能性
    0x0000 0000
    0x0000 0001      
    0x0000 0010   
    0x0000 0100  
    0x0000 1000
    0x0001 0000
    0x0010 0000
    0x0100 0000
    */
    static int search(int val, short    *table, int size)
    {
        int i;
    
        for (i = 0; i < size; i++) {
            if (val <= *table++)
                return (i);
        }
        return (size);
    }
    
    //编码
    unsigned char pcm2g711a(int pcm_val)
    {
        int     mask;
        int     seg;
        unsigned char   aval;
    
        if (pcm_val >= 0) { //正数
            mask = 0xD5;    //0x 1101 0101
        } else {            //负数
            mask = 0x55;    //0x 0101 0101
            pcm_val = -pcm_val - 1; //取反减1 0x0000 0001
        }
        //mask作用,符号位取反,偶数位取反
    
        //找到高位对应的数值表所在位置
        seg = search(pcm_val, seg_end, 8);
    
        //组合符号位,高位,和高位样本位
        if (seg >= 8)       //寻找表里最大,直接返回最大值
            return (0x7F ^ mask);
        else {
            aval = seg << SEG_SHIFT;   //左移4位 取得高位,并且最低四位为0000
            if (seg < 2)               //原值seg为0或者1;
                aval |= (pcm_val >> 1) & QUANT_MASK; //右移四位,取样本位
            else                       //原值seg为2,3,4,5,6,7
                aval |= (pcm_val >> seg) & QUANT_MASK;//右移seg+3位取样本位
            return (aval ^ mask);      //高位组合样本为,并且符号位取反
        }
    }
    
    解码过程
    拿到8位的g711编码数据后
    与0x55亦或,还原偶数位,并取强度位。
    取得样本位.
    根据强度位+还原样本,放大还原。
    通过符号位的值取反得到pcm数据的正负。
    

    代码

    //解码
    short alaw2pcm(
                unsigned char   a_val)
    {
        short t;
        short seg;
        
        a_val ^= 0x55;
        
         //后四位a_val即强度样本位
        t = (a_val & QUANT_MASK) << 4;//左移放大,对其强度样本位
        //强度位
        seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
      
        switch (seg) {
            case 0:      //强度位为0,即0x0000 0000
                t += 8;  //即0x0000 0000 0000 1000+强度样本位
                break;
            case 1:      //强度位为1,即0x0000 0001
                t += 0x108;//即0x0000 0001 0000 1000+强度样本位
                break;
            default:     //强度位为2-7
                t += 0x108;//即0x0000 0001 0000 1000+强度样本位
                t <<= seg - 1; //左移恢复原本数量级
        }
        //符号位
        return ((a_val & SIGN_BIT) ? t : -t);
    }
    

    相关文章

      网友评论

        本文标题:G711音频编码

        本文链接:https://www.haomeiwen.com/subject/bovsfxtx.html