예제 #1
0
        /// <summary>
        /// Encode quantization indices of excitation
        /// </summary>
        /// <param name="psRangeEnc">I/O  compressor data structure</param>
        /// <param name="signalType">I    Signal type</param>
        /// <param name="quantOffsetType">I    quantOffsetType</param>
        /// <param name="pulses">I    quantization indices</param>
        /// <param name="frame_length">I    Frame length</param>
        internal static void silk_encode_pulses(
            EntropyCoder psRangeEnc,
            int signalType,
            int quantOffsetType,
            sbyte[] pulses,
            int frame_length)
        {
            int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
            int abs_q, minSumBits_Q5, sumBits_Q5;

            int[] abs_pulses;
            int[] sum_pulses;
            int[] nRshifts;
            int[] pulses_comb = new int[8];
            int   abs_pulses_ptr;
            int   pulses_ptr;

            byte[] nBits_ptr;

            Arrays.MemSetInt(pulses_comb, 0, 8);

            /****************************/
            /* Prepare for shell coding */
            /****************************/
            /* Calculate number of shell blocks */
            Inlines.OpusAssert(1 << SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH == SilkConstants.SHELL_CODEC_FRAME_LENGTH);
            iter = Inlines.silk_RSHIFT(frame_length, SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH);
            if (iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH < frame_length)
            {
                Inlines.OpusAssert(frame_length == 12 * 10); /* Make sure only happens for 10 ms @ 12 kHz */
                iter++;
                Arrays.MemSetWithOffset <sbyte>(pulses, 0, frame_length, SilkConstants.SHELL_CODEC_FRAME_LENGTH);
            }

            /* Take the absolute value of the pulses */
            abs_pulses = new int[iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH];
            Inlines.OpusAssert((SilkConstants.SHELL_CODEC_FRAME_LENGTH & 3) == 0);

            // unrolled loop
            for (i = 0; i < iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH; i += 4)
            {
                abs_pulses[i + 0] = (int)Inlines.silk_abs(pulses[i + 0]);
                abs_pulses[i + 1] = (int)Inlines.silk_abs(pulses[i + 1]);
                abs_pulses[i + 2] = (int)Inlines.silk_abs(pulses[i + 2]);
                abs_pulses[i + 3] = (int)Inlines.silk_abs(pulses[i + 3]);
            }

            /* Calc sum pulses per shell code frame */
            sum_pulses     = new int[iter];
            nRshifts       = new int[iter];
            abs_pulses_ptr = 0;
            for (i = 0; i < iter; i++)
            {
                nRshifts[i] = 0;

                while (true)
                {
                    /* 1+1 . 2 */
                    scale_down = combine_and_check(pulses_comb, 0, abs_pulses, abs_pulses_ptr, Tables.silk_max_pulses_table[0], 8);
                    /* 2+2 . 4 */
                    scale_down += combine_and_check(pulses_comb, pulses_comb, Tables.silk_max_pulses_table[1], 4);
                    /* 4+4 . 8 */
                    scale_down += combine_and_check(pulses_comb, pulses_comb, Tables.silk_max_pulses_table[2], 2);
                    /* 8+8 . 16 */
                    scale_down += combine_and_check(sum_pulses, i, pulses_comb, 0, Tables.silk_max_pulses_table[3], 1);

                    if (scale_down != 0)
                    {
                        /* We need to downscale the quantization signal */
                        nRshifts[i]++;
                        for (k = abs_pulses_ptr; k < abs_pulses_ptr + SilkConstants.SHELL_CODEC_FRAME_LENGTH; k++)
                        {
                            abs_pulses[k] = Inlines.silk_RSHIFT(abs_pulses[k], 1);
                        }
                    }
                    else
                    {
                        /* Jump out of while(1) loop and go to next shell coding frame */
                        break;
                    }
                }

                abs_pulses_ptr += SilkConstants.SHELL_CODEC_FRAME_LENGTH;
            }

            /**************/
            /* Rate level */
            /**************/
            /* find rate level that leads to fewest bits for coding of pulses per block info */
            minSumBits_Q5 = int.MaxValue;
            for (k = 0; k < SilkConstants.N_RATE_LEVELS - 1; k++)
            {
                nBits_ptr  = Tables.silk_pulses_per_block_BITS_Q5[k];
                sumBits_Q5 = Tables.silk_rate_levels_BITS_Q5[signalType >> 1][k];
                for (i = 0; i < iter; i++)
                {
                    if (nRshifts[i] > 0)
                    {
                        sumBits_Q5 += nBits_ptr[SilkConstants.SILK_MAX_PULSES + 1];
                    }
                    else
                    {
                        sumBits_Q5 += nBits_ptr[sum_pulses[i]];
                    }
                }
                if (sumBits_Q5 < minSumBits_Q5)
                {
                    minSumBits_Q5  = sumBits_Q5;
                    RateLevelIndex = k;
                }
            }

            psRangeEnc.enc_icdf(RateLevelIndex, Tables.silk_rate_levels_iCDF[signalType >> 1], 8);

            /***************************************************/
            /* Sum-Weighted-Pulses Encoding                    */
            /***************************************************/
            for (i = 0; i < iter; i++)
            {
                if (nRshifts[i] == 0)
                {
                    psRangeEnc.enc_icdf(sum_pulses[i], Tables.silk_pulses_per_block_iCDF[RateLevelIndex], 8);
                }
                else
                {
                    psRangeEnc.enc_icdf(SilkConstants.SILK_MAX_PULSES + 1, Tables.silk_pulses_per_block_iCDF[RateLevelIndex], 8);
                    for (k = 0; k < nRshifts[i] - 1; k++)
                    {
                        psRangeEnc.enc_icdf(SilkConstants.SILK_MAX_PULSES + 1, Tables.silk_pulses_per_block_iCDF[SilkConstants.N_RATE_LEVELS - 1], 8);
                    }

                    psRangeEnc.enc_icdf(sum_pulses[i], Tables.silk_pulses_per_block_iCDF[SilkConstants.N_RATE_LEVELS - 1], 8);
                }
            }

            /******************/
            /* Shell Encoding */
            /******************/
            for (i = 0; i < iter; i++)
            {
                if (sum_pulses[i] > 0)
                {
                    ShellCoder.silk_shell_encoder(psRangeEnc, abs_pulses, i * SilkConstants.SHELL_CODEC_FRAME_LENGTH);
                }
            }

            /****************/
            /* LSB Encoding */
            /****************/
            for (i = 0; i < iter; i++)
            {
                if (nRshifts[i] > 0)
                {
                    pulses_ptr = i * SilkConstants.SHELL_CODEC_FRAME_LENGTH;
                    nLS        = nRshifts[i] - 1;
                    for (k = 0; k < SilkConstants.SHELL_CODEC_FRAME_LENGTH; k++)
                    {
                        abs_q = (sbyte)Inlines.silk_abs(pulses[pulses_ptr + k]);
                        for (j = nLS; j > 0; j--)
                        {
                            bit = Inlines.silk_RSHIFT(abs_q, j) & 1;
                            psRangeEnc.enc_icdf(bit, Tables.silk_lsb_iCDF, 8);
                        }
                        bit = abs_q & 1;
                        psRangeEnc.enc_icdf(bit, Tables.silk_lsb_iCDF, 8);
                    }
                }
            }

            /****************/
            /* Encode signs */
            /****************/
            CodeSigns.silk_encode_signs(psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses);
        }
예제 #2
0
        /*********************************************/
        /* Decode quantization indices of excitation */
        /*********************************************/
        internal static void silk_decode_pulses(
            EntropyCoder psRangeDec,            /* I/O  Compressor data structure                   */
            short[] pulses,                     /* O    Excitation signal                           */
            int signalType,                     /* I    Sigtype                                     */
            int quantOffsetType,                /* I    quantOffsetType                             */
            int frame_length                    /* I    Frame length                                */
            )
        {
            int i, j, k, iter, abs_q, nLS, RateLevelIndex;

            int[] sum_pulses = new int[SilkConstants.MAX_NB_SHELL_BLOCKS];
            int[] nLshifts   = new int[SilkConstants.MAX_NB_SHELL_BLOCKS];
            int   pulses_ptr;

            /*********************/
            /* Decode rate level */
            /*********************/
            RateLevelIndex = psRangeDec.dec_icdf(Tables.silk_rate_levels_iCDF[signalType >> 1], 8);

            /* Calculate number of shell blocks */
            Inlines.OpusAssert(1 << SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH == SilkConstants.SHELL_CODEC_FRAME_LENGTH);
            iter = Inlines.silk_RSHIFT(frame_length, SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH);
            if (iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH < frame_length)
            {
                Inlines.OpusAssert(frame_length == 12 * 10); /* Make sure only happens for 10 ms @ 12 kHz */
                iter++;
            }

            /***************************************************/
            /* Sum-Weighted-Pulses Decoding                    */
            /***************************************************/
            for (i = 0; i < iter; i++)
            {
                nLshifts[i]   = 0;
                sum_pulses[i] = psRangeDec.dec_icdf(Tables.silk_pulses_per_block_iCDF[RateLevelIndex], 8);

                /* LSB indication */
                while (sum_pulses[i] == SilkConstants.SILK_MAX_PULSES + 1)
                {
                    nLshifts[i]++;
                    /* When we've already got 10 LSBs, we shift the table to not allow (SILK_MAX_PULSES + 1) */
                    sum_pulses[i] = psRangeDec.dec_icdf(
                        Tables.silk_pulses_per_block_iCDF[SilkConstants.N_RATE_LEVELS - 1], (nLshifts[i] == 10 ? 1 : 0), 8);
                }
            }

            /***************************************************/
            /* Shell decoding                                  */
            /***************************************************/
            for (i = 0; i < iter; i++)
            {
                if (sum_pulses[i] > 0)
                {
                    ShellCoder.silk_shell_decoder(pulses, Inlines.silk_SMULBB(i, SilkConstants.SHELL_CODEC_FRAME_LENGTH), psRangeDec, sum_pulses[i]);
                }
                else
                {
                    Arrays.MemSetWithOffset <short>(pulses, 0, Inlines.silk_SMULBB(i, SilkConstants.SHELL_CODEC_FRAME_LENGTH), SilkConstants.SHELL_CODEC_FRAME_LENGTH);
                }
            }

            /***************************************************/
            /* LSB Decoding                                    */
            /***************************************************/
            for (i = 0; i < iter; i++)
            {
                if (nLshifts[i] > 0)
                {
                    nLS        = nLshifts[i];
                    pulses_ptr = Inlines.silk_SMULBB(i, SilkConstants.SHELL_CODEC_FRAME_LENGTH);
                    for (k = 0; k < SilkConstants.SHELL_CODEC_FRAME_LENGTH; k++)
                    {
                        abs_q = pulses[pulses_ptr + k];
                        for (j = 0; j < nLS; j++)
                        {
                            abs_q  = Inlines.silk_LSHIFT(abs_q, 1);
                            abs_q += psRangeDec.dec_icdf(Tables.silk_lsb_iCDF, 8);
                        }
                        pulses[pulses_ptr + k] = (short)(abs_q);
                    }
                    /* Mark the number of pulses non-zero for sign decoding. */
                    sum_pulses[i] |= nLS << 5;
                }
            }

            /****************************************/
            /* Decode and add signs to pulse signal */
            /****************************************/
            CodeSigns.silk_decode_signs(psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses);
        }