All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rubycoder.gsm.GSMEncoder Maven / Gradle / Ivy

There is a newer version: 1.0.2-jitsi
Show newest version
package org.rubycoder.gsm;

public class GSMEncoder
{
    private static final byte GSM_MAGIC = 0x0d;
    private static final int[] FAC = { 18431, 20479, 22527, 24575, 26623,
            28671, 30719, 32767 };

    private static int add(int a, int b)
    {
        int sum = a + b;
        return saturate(sum);
    }

    private static int asl(int a, int n)
    {
        if (n >= 16)
        {
            return 0;
        }
        if (n <= -16)
        {
            return (a < 0 ? -1 : 0);
        }
        if (n < 0)
        {
            return asr(a, -n);
        }
        return (a << n);
    }

    private static int asr(int a, int n)
    {
        if (n >= 16)
        {
            return (a < 0 ? -1 : 0);
        }
        if (n <= -16)
        {
            return 0;
        }
        if (n < 0)
        {
            return (a << -n);// &0xffff;
        }
        return (a >> n);
    }

    private static void Coefficients_40_159(int LARpp_j[], int LARp[])
    {
        int i;

        for (i = 0; i < 8; i++)
        {
            LARp[i] = LARpp_j[i];
        }
    }

    private static void LARp_to_rp(int LARp[])
    {
        int i;
        int temp;

        for (i = 0; i < 8; i++)
        {
            if (LARp[i] < 0)
            {
                temp = ((LARp[i] == MIN_WORD) ? MAX_WORD : -LARp[i]);
                LARp[i] = (-((temp < 11059) ? temp << 1
                        : ((temp < 20070) ? temp + 11059 : add((temp >> 2),
                                26112))));
            } else
            {
                temp = LARp[i];
                LARp[i] = ((temp < 11059) ? temp << 1
                        : ((temp < 20070) ? temp + 11059 : add((temp >> 2),
                                26112)));
            }
        }
    }

    public static void main(String args[])
    {
        GSMEncoder encoder = new GSMEncoder();
        int[] s = new int[160];
        encoder.encode(s);

    }

    private static int mult_r(int a, int b)
    {
        if (b == MIN_WORD && a == MIN_WORD)
        {
            return MAX_WORD;
        } else
        {
            int prod = a * b + 16384;
            // prod >>= 15;
            return saturate(prod >> 15);// &0xffff;
            // return (prod & 0xffff);
        }
    }

    public static void print(String name, int data[])
    {
        System.out.print("[" + name + ":");
        for (int i = 0; i < data.length; i++)
        {
            System.out.print("" + data[i]);
            if (i < data.length - 1)
            {
                System.out.print(",");
            } else
            {
                System.out.println("]");
            }
        }
    }

    public static void print(String name, int data)
    {
        System.out.println("[" + name + ":" + data + "]");
    }

    private static int saturate(int x)
    {
        return (x < MIN_WORD ? MIN_WORD : (x > MAX_WORD ? MAX_WORD : x));
    }

    private static int sub(int a, int b)
    {
        int diff = a - b;
        return saturate(diff);
    }

    private final int[] gsm_DLB = { 6554, 16384, 26214, 32767 };
    private static final byte[] bitoff = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4,
            4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
            2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0 };
    private final int[] gsm_NRFAC = { 29128, 26215, 23832, 21846, 20165, 18725,
            17476, 16384 };
    private static final int MIN_WORD = -32767 - 1;
    private static final int MAX_WORD = 32767;
    private static final int MIN_LONGWORD = (-2147483647 - 1);
    private static final int MAX_LONGWORD = 2147483647;
    private final int[] dp0 = new int[280];
    private final int[] u = new int[8];
    private final int[][] LARpp = new int[2][8];
    private int j;
    private final int[] e = new int[50];
    private int z1;
    private int L_z2;
    private int mp;

    private int dpOffset;

    private int dppOffset;

    private int bcOffset;

    private int ncOffset;

    private int xmaxcOffset;

    private int eOffset;

    private int xmcOffset;

    private int dOffset;

    private int mcoffset = 0;

    private int abs(int a)
    {
        return ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a));
    }

    private void APCM_quantization(int[] xM, int[] xMc, int[] mant_out,
            int[] exp_out, int[] xmaxc_out)
    {
        int i;
        boolean itest;

        int xmax, xmaxc, temp, temp1, temp2;
        int[] exp = new int[1];
        int[] mant = new int[1];

        /*
         * Find the maximum absolute value xmax of xM[0..12].
         */

        xmax = 0;
        for (i = 0; i <= 12; i++)
        {
            temp = xM[i];
            temp = abs(temp);
            if (temp > xmax)
                xmax = temp;
        }

        /*
         * Qantizing and coding of xmax to get xmaxc.
         */

        exp[0] = 0;
        temp = sasr(xmax, 9);
        itest = false;

        for (i = 0; i <= 5; i++)
        {
            itest |= (temp <= 0);
            temp = sasr(temp, 1);

            assert (exp[0] <= 5);
            if (!itest)
            {
                exp[0]++; /* exp = add (exp, 1) */

            }
        }

        assert (exp[0] <= 6 && exp[0] >= 0);
        temp = exp[0] + 5;

        assert (temp <= 11 && temp >= 0);

        xmaxc = add(sasr(xmax, temp), exp[0] << 3);
        /*
         * Quantizing and coding of the xM[0..12] RPE sequence to get the
         * xMc[0..12]
         */

        APCM_quantization_xmaxc_to_exp_mant(xmaxc, exp, mant);

        /*
         * This computation uses the fact that the decoded version of xmaxc can
         * be calculated by using the exponent and the mantissa part of xmaxc
         * (logarithmic table). So, this method avoids any division and uses
         * only a scaling of the RPE samples by a function of the exponent. A
         * direct multiplication by the inverse of the mantissa (NRFAC[0..7]
         * found in table 4.5) gives the 3 bit coded version xMc[0..12] of the
         * RPE samples.
         */

        /*
         * Direct computation of xMc[0..12] using table 4.5
         */

        assert (exp[0] <= 4096 && exp[0] >= -4096);
        assert (mant[0] >= 0 && mant[0] <= 7);

        temp1 = 6 - exp[0]; /* normalization by the exponent */
        temp2 = gsm_NRFAC[mant[0]]; /* inverse mantissa */

        for (i = 0; i <= 12; i++)
        {
            assert (temp1 >= 0 && temp1 < 16);

            temp = xM[i] << temp1;
            temp = gsm_mult(temp, temp2);
            temp = sasr(temp, 12);
            xMc[xmcOffset + i] = temp + 4;

        }

        /*
         * NOTE: This equation is used to make all the xMc[i] positive.
         */

        mant_out[0] = mant[0];
        exp_out[0] = exp[0];
        xmaxc_out[xmaxcOffset] = xmaxc;

    }

    private void APCM_quantization_xmaxc_to_exp_mant(int xmaxc, int[] exp_out,
            int[] mant_out)
    {
        int exp, mant;

        /*
         * Compute exponent and mantissa of the decoded version of xmaxc
         */

        exp = 0;
        if (xmaxc > 15)
            exp = sasr(xmaxc, 3) - 1;
        mant = xmaxc - (exp << 3);

        if (mant == 0)
        {
            exp = -4;
            mant = 7;
        } else
        {
            while (mant <= 7)
            {
                mant = mant << 1 | 1;
                exp--;
            }
            mant -= 8;
        }

        assert (exp >= -4 && exp <= 6);
        assert (mant >= 0 && mant <= 7);

        exp_out[0] = exp;
        mant_out[0] = mant;
    }

    private void APCMInverseQuantization(int xMc[], int exp, int mant,
            int xMp[])
    {
        int i;
        int temp, temp1, temp2, temp3;
        int xmpi = 0;

        assert (mant >= 0 && mant <= 7);
        int xmci = xmcOffset;
        temp1 = FAC[mant]; /* see 4.2-15 for mant */
        temp2 = sub(6, exp); /* see 4.2-15 for exp */
        temp3 = asl(1, sub(temp2, 1));

        for (i = 13; i-- > 0;)
        {
            assert (xMc[xmci] <= 7 && xMc[xmci] >= 0); /* 3 bit unsigned */

            /* temp = gsm_sub( *xMc++ << 1, 7 ); */
            temp = (xMc[xmci++] << 1) - 7; /* restore sign */
            assert (temp <= 7 && temp >= -7); /* 4 bit signed */

            temp <<= 12; /* 16 bit signed */
            temp = mult_r(temp1, temp);
            temp = add(temp, temp3);
            xMp[xmpi++] = asr(temp, temp2);
        }
    }

    private void Autocorrelation(int[] s, int[] l_acf)
    {
        int k, i;
        int si = dOffset;
        assert (dOffset == 0);
        int temp, smax, scalauto;

        smax = 0;
        for (k = 0; k <= 159; k++)
        {
            temp = abs(s[si + k]);
            if (temp > smax)
                smax = temp;
        }

        /*
         * Computation of the scaling factor.
         */
        if (smax == 0)
            scalauto = 0;
        else
        {
            assert (smax > 0);
            scalauto = 4 - gsm_norm(smax << 16);/* sub(4,..) */
        }

        /*
         * Scaling of the array s[0...159]
         */

        if (scalauto > 0)
        {
            switch (scalauto)
            {
            case 1:
                for (k = 0; k <= 159; k++)
                    s[k] = mult_r(s[k], 16384);
                break;
            case 2:
                for (k = 0; k <= 159; k++)
                    s[k] = mult_r(s[k], 16384 >> (2 - 1));
                break;
            case 3:
                for (k = 0; k <= 159; k++)
                    s[k] = mult_r(s[k], 16384 >> (3 - 1));
                break;
            case 4:
                for (k = 0; k <= 159; k++)
                    s[k] = mult_r(s[k], 16384 >> (4 - 1));
                break;

            }
        }
        int spi = 0;
        int sl = s[spi];
        for (k = 9; k > 0; k--)
            l_acf[k - 1] = 0;

        for (int j = 0; j < 8; j++)
        {
            for (int x = 0; x <= j; x++)
            {
                l_acf[x] += (sl * s[spi - x]);
            }
            if (j < 7)
                sl = s[++spi];
        }

        for (i = 8; i <= 159; i++)
        {
            sl = s[++spi];
            for (int j = 0; j <= 8; j++)
            {
                l_acf[j] += (sl * s[spi - j]);
            }
        }
        for (k = 9; k > 0; k--)
            l_acf[k - 1] <<= 1;

        /*
         * Rescaling of the array s[0..159]
         */
        if (scalauto > 0)
        {
            assert (scalauto <= 4);
            for (k = 160; k > 0; k--)
                s[si++] <<= scalauto;
        }
    }

    private void Calculation_of_the_LTP_parameters(int[] d, int[] dp,
            int[] bc_out, int[] nc_out)
    {
        int k, lambda;
        int Nc, bc;
        int[] wt = new int[40];

        int L_max, L_power;
        int R, S, dmax, scal;
        int temp;

        /*
         * Search of the optimum scaling of d[0..39].
         */
        dmax = 0;
        for (k = 0; k < 40; k++)
        {
            temp = d[dOffset + k];
            temp = abs(temp);
            if (temp > dmax)
                dmax = temp;
        }

        temp = 0;
        if (dmax == 0)
            scal = 0;
        else
        {
            assert (dmax > 0);
            temp = gsm_norm(dmax << 16);
        }

        if (temp > 6)
            scal = 0;
        else
            scal = 6 - temp;

        assert (scal >= 0);

        /*
         * Initialization of a working array wt
         */

        for (k = 0; k < 40; k++)
            wt[k] = sasr(d[dOffset + k], scal);

        /*
         * Search for the maximum cross-correlation and coding of the LTP lag
         */
        L_max = 0;
        Nc = 40; /* index for the maximum cross-correlation */

        for (lambda = 40; lambda <= 120; lambda++)
        {
            int L_result;
            L_result = wt[0] * dp[dpOffset - lambda];

            for (int i = 1; i < 40; i++)
            {
                L_result += wt[i] * dp[dpOffset + i - lambda];
            }

            if (L_result > L_max)
            {
                Nc = lambda;
                L_max = L_result;
            }
        }

        nc_out[ncOffset] = Nc;

        L_max <<= 1;

        /*
         * Rescaling of L_max
         */
        assert (scal <= 100 && scal >= -100);
        L_max >>= (6 - scal); /* sub(6, scal) */

        assert (Nc <= 120 && Nc >= 40);

        /*
         * Compute the power of the reconstructed short term residual signal
         * dp[..]
         */
        L_power = 0;
        for (k = 0; k <= 39; k++)
        {
            int L_temp;

            L_temp = sasr(dp[dpOffset + k - Nc], 3);
            L_power += L_temp * L_temp;
        }
        L_power <<= 1; /* from L_MULT */
        // System.out.println("L_max: "+L_max);

        /*
         * Normalization of L_max and L_power
         */
        if (L_max <= 0)
        {
            bc_out[bcOffset] = 0;
            return;
        }
        if (L_max >= L_power)
        {
            bc_out[bcOffset] = 3;
            return;
        }

        temp = gsm_norm(L_power);

        R = sasr(L_max << temp, 16);
        S = sasr(L_power << temp, 16);

        /*
         * Coding of the LTP gain
         */

        /*
         * Table 4.3a must be used to obtain the level DLB[i] for the
         * quantization of the LTP gain b to get the coded version bc.
         */
        for (bc = 0; bc <= 2; bc++)
            if (R <= gsm_mult(S, gsm_DLB[bc]))
                break;
        bc_out[bcOffset] = bc;

    }

    private void Coefficients_0_12(int LARpp_j_1[], int LARpp_j[], int LARp[])
    {
        int i;

        for (i = 0; i < 8; i++)
        {
            LARp[i] = add(sasr(LARpp_j_1[i], 2), sasr(LARpp_j[i], 2));
            LARp[i] = add(LARp[i], sasr(LARpp_j_1[i], 1));
        }
    }

    private void Coefficients_13_26(int LARpp_j_1[], int LARpp_j[], int LARp[])
    {
        int i;

        for (i = 0; i < 8; i++)
        {
            LARp[i] = add(sasr(LARpp_j_1[i], 1), sasr(LARpp_j[i], 1));
        }
    }

    private void Coefficients_27_39(int LARpp_j_1[], int LARpp_j[], int LARp[])
    {
        int i;

        for (i = 0; i < 8; i++)
        {
            LARp[i] = add(sasr(LARpp_j_1[i], 2), sasr(LARpp_j[i], 2));
            LARp[i] = add(LARp[i], sasr(LARpp_j[i], 1));
        }
    }

    private void DecodingOfTheCodedLogAreaRatios(int[] larc, int[] larpp)
    {
        int temp1;
        int larci = 0;
        int larppi = 0;

        // STEP(0, -32, 13107);
        temp1 = add(larc[larci++], -32) << 10;
        temp1 = sub(temp1, 0 << 1);
        temp1 = mult_r(13107, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(0, -32, 13107);
        temp1 = add(larc[larci++], -32) << 10;
        temp1 = sub(temp1, 0 << 1);
        temp1 = mult_r(13107, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(2048, -16, 13107);
        temp1 = add(larc[larci++], -16) << 10;
        temp1 = sub(temp1, 2048 << 1);
        temp1 = mult_r(13107, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(-2560, -16, 13107);
        temp1 = add(larc[larci++], -16) << 10;
        temp1 = sub(temp1, -2560 << 1);
        temp1 = mult_r(13107, temp1);
        larpp[larppi++] = add(temp1, temp1);

        // STEP(94, -8, 19223);
        temp1 = add(larc[larci++], -8) << 10;
        temp1 = sub(temp1, 94 << 1);
        temp1 = mult_r(19223, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(-1792, -8, 17476);
        temp1 = add(larc[larci++], -8) << 10;
        temp1 = sub(temp1, -1792 << 1);
        temp1 = mult_r(17476, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(-341, -4, 31454);
        temp1 = add(larc[larci++], -4) << 10;
        temp1 = sub(temp1, -341 << 1);
        temp1 = mult_r(31454, temp1);
        larpp[larppi++] = add(temp1, temp1);
        // STEP(-1144, -4, 29708);
        temp1 = add(larc[larci++], -4) << 10;
        temp1 = sub(temp1, -1144 << 1);
        temp1 = mult_r(29708, temp1);
        larpp[larppi++] = add(temp1, temp1);
    }

    public final void encode(byte c[], int s[])
    {
        int i = 0;

        int LARc[] = new int[8];
        int Nc[] = new int[4];
        int Mc[] = new int[4];
        int bc[] = new int[4];
        int xmaxc[] = new int[4];
        int xmc[] = new int[13 * 4];

        encoder(s, LARc, Nc, bc, Mc, xmaxc, xmc);

        c[i++] = (byte) ((GSM_MAGIC & 0xF) << 4 | LARc[0] >> 2 & 0xF);

        c[i++] = (byte) (((LARc[0] & 0x3) << 6) | (LARc[1] & 0x3F));
        c[i++] = (byte) (((LARc[2] & 0x1F) << 3) | ((LARc[3] >> 2) & 0x7));
        c[i++] = (byte) (((LARc[3] & 0x3) << 6) | ((LARc[4] & 0xF) << 2) | ((LARc[5] >> 2) & 0x3));
        c[i++] = (byte) (((LARc[5] & 0x3) << 6) | ((LARc[6] & 0x7) << 3) | (LARc[7] & 0x7));
        c[i++] = (byte) (((Nc[0] & 0x7F) << 1) | ((bc[0] >>> 1) & 0x1));
        c[i++] = (byte) (((bc[0] & 0x1) << 7) | ((Mc[0] & 0x3) << 5) | ((xmaxc[0] >> 1) & 0x1F));
        // System.out.println(bc[0]+" | "+Mc[0]+" | "+xmaxc[0]);
        c[i++] = (byte) (((xmaxc[0] & 0x1) << 7) | ((xmc[0] & 0x7) << 4)
                | ((xmc[1] & 0x7) << 1) | ((xmc[2] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[2] & 0x3) << 6) | ((xmc[3] & 0x7) << 3) | (xmc[4] & 0x7));
        c[i++] = (byte) (((xmc[5] & 0x7) << 5) /* 10 */
                | ((xmc[6] & 0x7) << 2) | ((xmc[7] >> 1) & 0x3));
        c[i++] = (byte) (((xmc[7] & 0x1) << 7) | ((xmc[8] & 0x7) << 4)
                | ((xmc[9] & 0x7) << 1) | ((xmc[10] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[10] & 0x3) << 6) | ((xmc[11] & 0x7) << 3) | (xmc[12] & 0x7));
        c[i++] = (byte) (((Nc[1] & 0x7F) << 1) | ((bc[1] >> 1) & 0x1));
        c[i++] = (byte) (((bc[1] & 0x1) << 7) | ((Mc[1] & 0x3) << 5) | ((xmaxc[1] >> 1) & 0x1F));
        c[i++] = (byte) (((xmaxc[1] & 0x1) << 7) | ((xmc[13] & 0x7) << 4)
                | ((xmc[14] & 0x7) << 1) | ((xmc[15] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[15] & 0x3) << 6) | ((xmc[16] & 0x7) << 3) | (xmc[17] & 0x7));
        c[i++] = (byte) (((xmc[18] & 0x7) << 5) | ((xmc[19] & 0x7) << 2) | ((xmc[20] >> 1) & 0x3));
        c[i++] = (byte) (((xmc[20] & 0x1) << 7) | ((xmc[21] & 0x7) << 4)
                | ((xmc[22] & 0x7) << 1) | ((xmc[23] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[23] & 0x3) << 6) | ((xmc[24] & 0x7) << 3) | (xmc[25] & 0x7));
        c[i++] = (byte) (((Nc[2] & 0x7F) << 1) /* 20 */
        | ((bc[2] >> 1) & 0x1));
        c[i++] = (byte) (((bc[2] & 0x1) << 7) | ((Mc[2] & 0x3) << 5) | ((xmaxc[2] >> 1) & 0x1F));
        c[i++] = (byte) (((xmaxc[2] & 0x1) << 7) | ((xmc[26] & 0x7) << 4)
                | ((xmc[27] & 0x7) << 1) | ((xmc[28] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[28] & 0x3) << 6) | ((xmc[29] & 0x7) << 3) | (xmc[30] & 0x7));
        c[i++] = (byte) (((xmc[31] & 0x7) << 5) | ((xmc[32] & 0x7) << 2) | ((xmc[33] >> 1) & 0x3));
        c[i++] = (byte) (((xmc[33] & 0x1) << 7) | ((xmc[34] & 0x7) << 4)
                | ((xmc[35] & 0x7) << 1) | ((xmc[36] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[36] & 0x3) << 6) | ((xmc[37] & 0x7) << 3) | (xmc[38] & 0x7));
        c[i++] = (byte) (((Nc[3] & 0x7F) << 1) | ((bc[3] >> 1) & 0x1));
        c[i++] = (byte) (((bc[3] & 0x1) << 7) | ((Mc[3] & 0x3) << 5) | ((xmaxc[3] >> 1) & 0x1F));
        c[i++] = (byte) (((xmaxc[3] & 0x1) << 7) | ((xmc[39] & 0x7) << 4)
                | ((xmc[40] & 0x7) << 1) | ((xmc[41] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[41] & 0x3) << 6) /* 30 */
                | ((xmc[42] & 0x7) << 3) | (xmc[43] & 0x7));
        c[i++] = (byte) (((xmc[44] & 0x7) << 5) | ((xmc[45] & 0x7) << 2) | ((xmc[46] >> 1) & 0x3));
        c[i++] = (byte) (((xmc[46] & 0x1) << 7) | ((xmc[47] & 0x7) << 4)
                | ((xmc[48] & 0x7) << 1) | ((xmc[49] >> 2) & 0x1));
        c[i++] = (byte) (((xmc[49] & 0x3) << 6) | ((xmc[50] & 0x7) << 3) | (xmc[51] & 0x7));
        // for (byte b : c) {
        // System.out.print(b + " ");
        // }
        // System.out.println("");
    }

    final int[] encode(int s[])
    {
        byte c[] = new byte[33];
        encode(c, s);
        return s;
    }

    private void encoder(int[] s, int[] LARc, int[] nc, int[] bc, int[] mc,
            int[] xmaxc, int[] xmc)
    {
        int k;
        int[] dp = dp0;
        int[] dpp = dp0;
        int so[] = new int[160];

        dpOffset = 120;
        dppOffset = 120;
        dOffset = 0;
        ncOffset = 0;
        bcOffset = 0;
        eOffset = 0;
        xmaxcOffset = 0;
        xmcOffset = 0;
        mcoffset = 0;
        GsmPreprocess(s, so);

        GsmLPCAnalysis(so, LARc);

        Gsm_Short_Term_Analysis_Filter(LARc, so);

        for (k = 0; k <= 3; k++, xmcOffset += 13)
        { // TODO START HERE!
            dOffset = k * 40;
            eOffset = 5;
            Gsm_Long_Term_Predictor(so, dp, e, dpp, nc, bc);
            Gsm_RPE_Encoding(e, xmaxc, mc, xmc);
            {
                int i;

                for (i = 0; i <= 39; i++)
                    dp[dpOffset + i] = add(e[5 + i], dpp[dppOffset + i]);
            }
            dpOffset += 40;
            dppOffset += 40;
            ncOffset++;
            bcOffset++;
            xmaxcOffset++;
            mcoffset++;
        }
        System.arraycopy(dp0, 0, dp0, 160, 120);
    }

    public void GSM()
    {
    }

    private int gsm_div(int num, int denum)
    {
        int L_num = num;
        int div = 0;
        int k = 15;
        // 220 "src/add.c"
        assert (num >= 0 && denum >= num);
        if (num == 0)
            return 0;

        while (k-- > 0)
        {
            div <<= 1;
            L_num <<= 1;

            if (L_num >= denum)
            {
                L_num -= denum;
                div++;
            }
        }

        return div;
    }

    private void Gsm_Long_Term_Predictor(int[] d, int[] dp, int[] e, int[] dpp,
            int[] nc, int[] bc)
    {
        // assert (dOffset != 0);
        // assert (dpOffset != 0);
        // assert (eOffset != 0);
        // assert (dppOffset != 0);
        // assert (ncOffset != 0);
        // assert (bcOffset != 0);

        Calculation_of_the_LTP_parameters(d, dp, bc, nc);

        Long_term_analysis_filtering(bc[bcOffset], nc[ncOffset], dp, d, dpp, e);
    }

    int gsm_mult(int a, int b)
    {
        if (a == (MIN_WORD) && b == (MIN_WORD))
            return MAX_WORD;
        else
            return ((a * b) >> (15));
    }

    private int gsm_norm(int a)
    {
        assert (a != 0);

        if (a < 0)
        {
            if (a <= -1073741824)
                return 0;
            a = ~a;
        }

        return (a & 0xffff0000) != 0 ? ((a & 0xff000000) != 0 ? -1
                + bitoff[0xFF & (a >> 24)] : 7 + bitoff[0xFF & (a >> 16)])
                : ((a & 0xff00) != 0 ? 15 + bitoff[0xFF & (a >> 8)]
                        : 23 + bitoff[0xFF & a]);
    }

    private void Gsm_RPE_Encoding(int[] e, int[] xmaxc, int[] mc, int[] xmc)
    {
        int[] x = new int[40];
        int[] xM = new int[13];
        int[] xMp = new int[13];
        int[] mant = new int[1];
        int[] exp = new int[1];

        Weighting_filter(e, x);
        RPE_grid_selection(x, xM, mc);
        APCM_quantization(xM, xmc, mant, exp, xmaxc);
        APCMInverseQuantization(xmc, exp[0], mant[0], xMp);
        RPE_grid_positioning(mc[mcoffset], xMp, e);
    }

    private void Gsm_Short_Term_Analysis_Filter(int[] larc, int[] s)
    {
        int[] LARpp_j = LARpp[j];
        int[] LARpp_j_1 = LARpp[j ^= 1];

        int[] larp = new int[8];

        DecodingOfTheCodedLogAreaRatios(larc, LARpp_j);

        Coefficients_0_12(LARpp_j_1, LARpp_j, larp);
        LARp_to_rp(larp);
        Short_term_analysis_filtering(larp, 13, s, 0);

        Coefficients_13_26(LARpp_j_1, LARpp_j, larp);
        LARp_to_rp(larp);
        Short_term_analysis_filtering(larp, 14, s, 13);

        Coefficients_27_39(LARpp_j_1, LARpp_j, larp);
        LARp_to_rp(larp);
        Short_term_analysis_filtering(larp, 13, s, 27);

        Coefficients_40_159(LARpp_j, larp);
        LARp_to_rp(larp);
        Short_term_analysis_filtering(larp, 120, s, 40);
    }

    private void GsmLPCAnalysis(int[] s, int[] LARc)
    {
        int L_ACF[] = new int[9];
        Autocorrelation(s, L_ACF);
        Reflection_coefficients(L_ACF, LARc);
        Transformation_to_Log_Area_Ratios(LARc);
        Quantization_and_coding(LARc);
    }

    final void GsmPreprocess(int[] s, int[] so)
    {
        int s1;
        int L_s2;

        int L_temp;

        int msp, lsp;
        int SO;

        int k = 160;
        int si = 0;
        int soi = 0;
        while (k-- > 0)
        {
            /*
             * 4.2.1 Downscaling of the input signal
             */
            SO = sasr(s[si], 3) << 2;
            si++;

            assert (SO >= -0x4000); /* downscaled by */
            assert (SO <= 0x3FFC); /* previous routine. */

            /*
             * 4.2.2 Offset compensation
             *
             * This part implements a high-pass filter and requires extended
             * arithmetic precision for the recursive part of this filter. The
             * input of this procedure is the array so[0...159] and the output
             * the array sof[ 0...159 ].
             */
            /*
             * Compute the non-recursive part
             */

            s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */
            z1 = SO;

            assert (s1 != MIN_WORD);

            /*
             * Compute the recursive part
             */
            L_s2 = s1;
            L_s2 <<= 15;

            /*
             * Execution of a 31 bv 16 bits multiplication
             */

            msp = sasr(L_z2, 15);
            lsp = L_z2 - (msp << 15); /* gsm_L_sub(L_z2,(msp<<15)); */

            L_s2 += mult_r(lsp, 32735);
            L_temp = msp * 32735; /* GSM_L_MULT(msp,32735) >> 1; */
            L_z2 = (int) l_add(L_temp, L_s2); // TODO not sure about the cast..

            /*
             * Compute sof[k] with rounding
             */
            L_temp = (int) l_add(L_z2, 16384);

            /*
             * 4.2.3 Preemphasis
             */

            msp = mult_r(mp, -28180);
            mp = sasr(L_temp, 15);
            so[soi++] = add(mp, msp);

        }

    }

    private long l_add(int a, int b)
    {
        long utmp;
        return ((a) < 0 ? ((b) >= 0 ? (a) + (b) : (utmp = (long) -((a) + 1)
                + (long) -((b) + 1)) >= MAX_LONGWORD ? MIN_LONGWORD : -utmp - 2)
                : ((b) <= 0 ? (a) + (b)
                        : (utmp = (long) (a) + (long) (b)) >= MAX_LONGWORD ? MAX_LONGWORD
                                : utmp));
    }

    void Long_term_analysis_filtering(int bc, int nc, int[] dp, int[] d,
            int[] dpp, int[] e)
    {
        int k;

        switch (bc)
        {
        case 0:
            // STEP(3277);
            for (k = 0; k <= 39; k++)
            {
                dpp[dppOffset + k] = mult_r(3277, dp[dpOffset + k - nc]);
                e[eOffset + k] = sub(d[dOffset + k], dpp[dppOffset + k]);
            }
            break;
        case 1:
            // STEP(11469);
            for (k = 0; k <= 39; k++)
            {
                dpp[dppOffset + k] = mult_r(11469, dp[dpOffset + k - nc]);
                e[eOffset + k] = sub(d[dOffset + k], dpp[dppOffset + k]);
            }
            break;
        case 2:
            // STEP(21299);
            for (k = 0; k <= 39; k++)
            {
                dpp[dppOffset + k] = mult_r(21299, dp[dpOffset + k - nc]);
                e[eOffset + k] = sub(d[dOffset + k], dpp[dppOffset + k]);
            }
            break;
        case 3:
            // STEP(32767);
            for (k = 0; k <= 39; k++)
            {
                dpp[dppOffset + k] = mult_r(32767, dp[dpOffset + k - nc]);
                e[eOffset + k] = sub(d[dOffset + k], dpp[dppOffset + k]);
            }
            break;
        }

    }

    private void Quantization_and_coding(int[] lar)
    {
        int temp;

        int lari = 0;
        temp = gsm_mult(20480, lar[lari]);
        temp = add(temp, 0);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 31 ? 31 - -32 : (temp < -32 ? 0 : temp - -32);
        lari++;

        temp = gsm_mult(20480, lar[lari]);
        temp = add(temp, 0);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 31 ? 31 - -32 : (temp < -32 ? 0 : temp - -32);
        lari++;

        temp = gsm_mult(20480, lar[lari]);
        temp = add(temp, 2048);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 15 ? 15 - -16 : (temp < -16 ? 0 : temp - -16);
        lari++;

        temp = gsm_mult(20480, lar[lari]);
        temp = add(temp, -2560);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 15 ? 15 - -16 : (temp < -16 ? 0 : temp - -16);
        lari++;

        temp = gsm_mult(13964, lar[lari]);
        temp = add(temp, 94);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 7 ? 7 - -8 : (temp < -8 ? 0 : temp - -8);
        lari++;

        temp = gsm_mult(15360, lar[lari]);
        temp = add(temp, -1792);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 7 ? 7 - -8 : (temp < -8 ? 0 : temp - -8);
        lari++;

        temp = gsm_mult(8534, lar[lari]);
        temp = add(temp, -341);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 3 ? 3 - -4 : (temp < -4 ? 0 : temp - -4);
        lari++;

        temp = gsm_mult(9036, lar[lari]);
        temp = add(temp, -1144);
        temp = add(temp, 256);
        temp = sasr(temp, 9);
        lar[lari] = temp > 3 ? 3 - -4 : (temp < -4 ? 0 : temp - -4);
        lari++;

    }

    private void Reflection_coefficients(int[] l_acf, int[] r)
    {
        int i, m, n;
        int temp;
        int ri = 0;
        int[] ACF = new int[9]; /* 0..8 */
        int[] P = new int[9]; /* 0..8 */
        int[] K = new int[9]; /* 2..8 */

        /*
         * Schur recursion with 16 bits arithmetic.
         */

        if (l_acf[0] == 0)
        {
            for (i = 8; i > 0; i--)
                r[ri++] = 0;
            return;
        }

        assert (l_acf[0] != 0);
        temp = gsm_norm(l_acf[0]);

        assert (temp >= 0 && temp < 32);

        /* ? overflow ? */
        for (i = 0; i <= 8; i++)
            ACF[i] = sasr(l_acf[i] << temp, 16);

        /*
         * Initialize array P[..] and K[..] for the recursion.
         */

        for (i = 1; i <= 7; i++)
            K[i] = ACF[i];
        for (i = 0; i <= 8; i++)
            P[i] = ACF[i];

        /*
         * Compute reflection coefficients
         */
        for (n = 1; n <= 8; n++, ri++)
        {
            temp = P[1];
            temp = abs(temp);
            if (P[0] < temp)
            {
                for (i = n; i <= 8; i++)
                    r[ri++] = 0;
                return;
            }

            r[ri] = gsm_div(temp, P[0]);

            assert (r[ri] >= 0);
            if (P[1] > 0)
                r[ri] = -r[ri]; /* r[n] = sub(0, r[n]) */
            assert (r[ri] != MIN_WORD);
            if (n == 8)
                return;

            /*
             * Schur recursion
             */
            temp = mult_r(P[1], r[ri]);
            P[0] = add(P[0], temp);

            for (m = 1; m <= 8 - n; m++)
            {
                temp = mult_r(K[m], r[ri]);
                P[m] = add(P[m + 1], temp);

                temp = mult_r(P[m + 1], r[ri]);
                K[m] = add(K[m], temp);
            }
        }
    }

    private void RPE_grid_positioning(int Mc, int xMp[], int ep[])
    {
        int i = 13;

        int epo = eOffset;
        int po = 0;
        // in original sources there is weird
        switch (Mc)
        {
        case 3:
            ep[epo++] = 0;
        case 2:
            ep[epo++] = 0;
        case 1:
            ep[epo++] = 0;
        case 0:
            ep[epo++] = xMp[po++];
            i--;
        }

        do
        {
            ep[epo++] = 0;
            ep[epo++] = 0;
            ep[epo++] = xMp[po++];
        } while (--i > 0);

        while (++Mc < 4)
        {
            ep[epo++] = 0;
        }
    }

    private void RPE_grid_selection(int[] x, int[] xM, int[] Mc_out)
    {
        int i;
        int L_result, L_temp;
        int EM;
        int Mc;

        int L_common_0_3;

        EM = 0;
        Mc = 0;
        // 164 "src/rpe.c"
        L_result = 0;
        for (int j = 1; j <= 12; j++)
        {
            L_temp = sasr(x[(3 * j)], 2);
            L_result += L_temp * L_temp;
        }

        L_common_0_3 = L_result;

        L_temp = sasr(x[(0)], 2);
        L_result += L_temp * L_temp;
        L_result <<= 1;
        EM = L_result;

        L_result = 0;
        for (int j = 0; j <= 12; j++)
        {
            L_temp = sasr((x[1 + 3 * j]), (2));
            L_result += L_temp * L_temp;
        }

        L_result <<= 1;
        if (L_result > EM)
        {
            Mc = 1;
            EM = L_result;
        }

        L_result = 0;
        for (int j = 0; j <= 12; j++)
        {
            L_temp = sasr((x[2 + 3 * j]), (2));
            L_result += L_temp * L_temp;
        }

        L_result <<= 1;
        if (L_result > EM)
        {
            Mc = 2;
            EM = L_result;
        }

        L_result = L_common_0_3;
        L_temp = sasr(x[3 + 3 * 12], 2);
        L_result += L_temp * L_temp;

        L_result <<= 1;
        if (L_result > EM)
        {
            Mc = 3;
            EM = L_result;
        }

        for (i = 0; i <= 12; i++)
            xM[i] = x[Mc + 3 * i];
        Mc_out[mcoffset] = Mc;

    }

    private int sasr(int x, int by)
    {
        return ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by))));
    }

    private void Short_term_analysis_filtering(int[] rp, int k_n, int[] s,
            int offset)
    {
        int i;
        int di, zzz, ui, sav, rpi;
        int si = offset;

        for (; k_n-- > 0; si++)
        {
            sav = s[si];
            di = sav;

            for (i = 0; i < 8; i++)
            { /* YYY */

                ui = u[i];
                rpi = rp[i];

                u[i] = sav;

                zzz = mult_r(rpi, di);
                sav = add(ui, zzz);

                zzz = mult_r(rpi, ui);
                di = add(di, zzz);
            }
            s[si] = di;
        }

    }

    private void Transformation_to_Log_Area_Ratios(int[] r)
    {
        int temp;
        int i;
        int ri = 0;

        /*
         * Computation of the LAR[0..7] from the r[0..7]
         */
        for (i = 1; i <= 8; i++, ri++)
        {
            temp = r[ri];
            temp = abs(temp);
            assert (temp >= 0);

            if (temp < 22118)
            {
                temp >>= 1;
            } else if (temp < 31130)
            {
                assert (temp >= 11059);
                temp -= 11059;
            } else
            {
                assert (temp >= 26112);
                temp -= 26112;
                temp <<= 2;
            }

            r[ri] = r[ri] < 0 ? -temp : temp;
            assert (r[ri] != MIN_WORD);
        }
    }

    private void Weighting_filter(int[] e, int[] x)
    {
        int L_result;
        int k;
        int ei = eOffset - 5;

        for (k = 0; k <= 39; k++)
        {
            L_result = 8192 >> 1;
            L_result += (e[(ei + k)] * -134) + (e[ei + k + 1] * -374)
                    + (e[ei + k + 3] * 2054) + (e[ei + k + 4] * 5741)
                    + (e[ei + k + 5] * 8192) + (e[ei + k + 6] * 5741)
                    + (e[ei + k + 7] * 2054) + (e[ei + k + 9] * -374)
                    + (e[ei + k + 10] * -134);

            L_result = sasr(L_result, 13);
            x[k] = (L_result < MIN_WORD ? MIN_WORD
                    : (L_result > MAX_WORD ? MAX_WORD : L_result));
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy