新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > adpcm音頻壓縮算法源代碼

        adpcm音頻壓縮算法源代碼

        作者: 時間:2017-06-04 來源:網(wǎng)絡 收藏


        #include stdio.h>

        本文引用地址:http://www.104case.com/article/201706/348587.htm

        #ifndef __STDC__
        #define signed
        #endif

        struct adpcm_state
        {
        short valprev; /* Previous output value */
        char index; /* Index into stepsize table */
        };

        /* Intel ADPCM step variation table */
        static int indexTable[16] = {
        -1, -1, -1, -1, 2, 4, 6, 8,
        -1, -1, -1, -1, 2, 4, 6, 8,
        };

        static int stepsizeTable[89] = {
        7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
        19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
        50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
        130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
        337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
        876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
        2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
        5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
        15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
        };

        /*-------------adpcm_ecoder---------------------------------------------*/
        void
        adpcm_coder(indata, outdata, len, state)
        short indata[];
        char outdata[];
        int len;
        struct adpcm_state *state;
        {
        short *inp;/* Input buffer pointer */
        signed char *outp;/* output buffer pointer */
        int val;/* Current input sample value */
        int sign;/* Current adpcm sign bit */
        int delta;/* Current adpcm output value */
        int diff;/* Difference between val and valprev */
        int step;/* Stepsize */
        int valpred;/* Predicted output value */
        int vpdiff;/* Current change to valpred */
        int index;/* Current step change index */
        int outputbuffer;/* place to keep previous 4-bit value */
        int bufferstep;/* toggle between outputbuffer/output */

        outp = (signed char *)outdata;
        inp = indata;

        valpred = state->valprev;
        index = state->index;
        step = stepsizeTable[index];

        bufferstep = 1;

        for ( ; len > 0 ; len-- ) {
        val = *inp++;

        /* Step 1 - compute difference with previous value */
        diff = val - valpred;
        sign = (diff 0) ? 8 : 0;
        if ( sign ) diff = (-diff);

        /* Step 2 - Divide and clamp */
        /* Note:
        ** This code *approximately* computes:
        ** delta = diff*4/step;
        ** vpdiff = (delta+0.5)*step/4;
        ** but in shift step bits are dropped. The net result of this is
        ** that even if you have fast mul/div hardware you cannot put it to
        ** good use since the fixup would be too expensive.
        */
        delta = 0;
        vpdiff = (step >> 3);

        if ( diff >= step ) {
        delta = 4;
        diff -= step;
        vpdiff += step;
        }
        step >>= 1;
        if ( diff >= step ) {
        delta |= 2;
        diff -= step;
        vpdiff += step;
        }
        step >>= 1;
        if ( diff >= step ) {
        delta |= 1;
        vpdiff += step;
        }

        /* Step 3 - Update previous value */
        if ( sign )
        valpred -= vpdiff;
        else
        valpred += vpdiff;

        /* Step 4 - Clamp previous value to 16 bits */
        if ( valpred > 32767 )
        valpred = 32767;
        else if ( valpred -32768 )
        valpred = -32768;

        /* Step 5 - Assemble value, update index and step values */
        delta |= sign;

        index += indexTable[delta];
        if ( index 0 ) index = 0;
        if ( index > 88 ) index = 88;
        step = stepsizeTable[index];

        /* Step 6 - Output value */
        if ( bufferstep ) {
        outputbuffer = (delta 4) 0xf0;
        } else {
        *outp++ = (delta 0x0f) | outputbuffer;
        }
        bufferstep = !bufferstep;
        }

        /* Output last step, if needed */
        if ( !bufferstep )
        *outp++ = outputbuffer;

        state->valprev = valpred;
        state->index = index;
        }


        /*-------------adpcm_decoder---------------------------------------------*/
        void
        adpcm_decoder(indata, outdata, len, state)
        char indata[];
        short outdata[];
        int len;
        struct adpcm_state *state;
        {
        signed char *inp;/* Input buffer pointer */
        short *outp;/* output buffer pointer */
        int sign;/* Current adpcm sign bit */
        int delta;/* Current adpcm output value */
        int step;/* Stepsize */
        int valpred;/* Predicted value */
        int vpdiff;/* Current change to valpred */
        int index;/* Current step change index */
        int inputbuffer;/* place to keep next 4-bit value */
        int bufferstep;/* toggle between inputbuffer/input */

        outp = outdata;
        inp = (signed char *)indata;

        valpred = state->valprev;
        index = state->index;
        step = stepsizeTable[index];

        bufferstep = 0;

        for ( ; len > 0 ; len-- ) {

        /* Step 1 - get the delta value */
        if ( bufferstep ) {
        delta = inputbuffer 0xf;
        } else {
        inputbuffer = *inp++;
        delta = (inputbuffer >> 4) 0xf;
        }
        bufferstep = !bufferstep;

        /* Step 2 - Find new index value (for later) */
        index += indexTable[delta];
        if ( index 0 ) index = 0;
        if ( index > 88 ) index = 88;

        /* Step 3 - Separate sign and magnitude */
        sign = delta 8;
        delta = delta 7;

        /* Step 4 - Compute difference and new predicted value */
        /*
        ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
        ** in adpcm_coder.
        */
        vpdiff = step >> 3;
        if ( delta 4 ) vpdiff += step;
        if ( delta 2 ) vpdiff += step>>1;
        if ( delta 1 ) vpdiff += step>>2;

        if ( sign )
        valpred -= vpdiff;
        else
        valpred += vpdiff;

        /* Step 5 - clamp output value */
        if ( valpred > 32767 )
        valpred = 32767;
        else if ( valpred -32768 )
        valpred = -32768;

        /* Step 6 - Update step value */
        step = stepsizeTable[index];

        /* Step 7 - Output value */
        *outp++ = valpred;
        }

        state->valprev = valpred;
        state->index = index;
        }



        評論


        相關推薦

        技術專區(qū)

        關閉
        主站蜘蛛池模板: 新安县| 大邑县| 涞源县| 安远县| 信丰县| 康乐县| 阿巴嘎旗| 潼南县| 伊金霍洛旗| 柯坪县| 磴口县| 闽侯县| 吉首市| 柳州市| 老河口市| 保靖县| 嵊泗县| 武强县| 尼勒克县| 剑河县| 安阳市| 静海县| 当雄县| 广昌县| 长治市| 大方县| 合肥市| 上思县| 阳原县| 南充市| 木里| 东至县| 蕉岭县| 裕民县| 南皮县| 嵊泗县| 龙江县| 洛宁县| 汨罗市| 汉寿县| 监利县|