Пример #1
0
        /*
         * Reset decoder
         *
         * Set accumulated path metrics to zero. For termination other than
         * tail-biting, initialize the zero state as the encoder starting state.
         * Intialize with the maximum accumulated sum at length equal to the
         * constraint length.
         */
        static void reset_decoder(vdecoder dec, CONV_TERM term)
        {
            int ns = dec.trellis.num_states;

            memset(dec.trellis.sums, 0, sizeof(short) * ns);

            if (term != CONV_TERM.TAIL_BITING)
            {
                dec.trellis.sums[0] = (short)(sbyte.MaxValue * dec.n * dec.k);
            }
        }
Пример #2
0
        static void _traceback_rec(vdecoder dec,
                                   int state, sbyte *o, int len)
        {
            int i;
            int path;

            for (i = len - 1; i >= 0; i--)
            {
                path  = (int)(dec.paths[i][state] + 1);
                o[i]  = (sbyte)(path ^ dec.trellis.vals[state]);
                state = vstate_lshift(state, dec.k, (int)path);
            }
        }
Пример #3
0
        /*
         * Traceback and generate decoded output
         *
         * For tail biting, find the largest accumulated path metric at the final state
         * followed by two trace back passes. For zero flushing the final state is
         * always zero with a single traceback path.
         */
        static int traceback(vdecoder dec, sbyte *o, CONV_TERM term, int len)
        {
            int i, sum, max_p = -1, max = -1;
            int path, state = 0;

            if (term == CONV_TERM.TAIL_BITING)
            {
                for (i = 0; i < dec.trellis.num_states; i++)
                {
                    sum = dec.trellis.sums[i];
                    if (sum > max)
                    {
                        max_p = max;
                        max   = sum;
                        state = (int)i;
                    }
                }
                if (max < 0)
                {
                    throw new Exception();
                }
                for (i = dec.len - 1; i >= len + TAIL_BITING_EXTRA; i--)
                {
                    path = (int)(dec.paths[i][state] + 1);
                    int prestate = state;
                    state = vstate_lshift(state, dec.k, (int)path);
                    //Console.WriteLine($"[Q] path={path}, state={state}, prestate={state}, k={dec.k}, i={i}");
                }
            }
            else
            {
                for (i = dec.len - 1; i >= len; i--)
                {
                    path  = (int)(dec.paths[i][state] + 1);
                    state = vstate_lshift(state, dec.k, (int)path);
                }
            }

            if (dec.recursive != 0)
            {
                _traceback_rec(dec, state, o, len);
            }
            else
            {
                state = _traceback(dec, state, o, len, term == CONV_TERM.TAIL_BITING ? TAIL_BITING_EXTRA : 0);
            }

            /* Don't handle the odd case of recursize tail-biting codes */

            return(max - max_p);
        }
Пример #4
0
        static int _traceback(vdecoder dec, int state, sbyte *o, int len, int offset)
        {
            int i;
            int path;

            for (i = len - 1; i >= 0; i--)
            {
                path  = (int)(dec.paths[i + offset][state] + 1);
                o[i]  = dec.trellis.vals[state];
                state = vstate_lshift(state, dec.k, (int)path);
            }

            return(state);
        }
Пример #5
0
        static void reset_vdec(vdecoder dec, lte_conv_code code)
        {
            dec.n         = code.n;
            dec.k         = code.k;
            dec.recursive = code.rgen != 0 ? 1 : 0;
            dec.intrvl    = short.MaxValue / (dec.n * sbyte.MaxValue) - dec.k;

            if (dec.n != 3 || dec.k != 7)
            {
                throw new Exception();
            }

            if (code.term == CONV_TERM.FLUSH)
            {
                dec.len = code.len + code.k - 1;
            }
            else
            {
                dec.len = code.len + TAIL_BITING_EXTRA * 2;
            }
        }
Пример #6
0
        /*
         * Allocate decoder object
         *
         * Subtract the constraint length K on the normalization interval to
         * accommodate the initialization path metric at state zero.
         */
        static vdecoder alloc_vdec(lte_conv_code code)
        {
            int i, ns;

            ns = NUM_STATES(code.k);

            vdecoder dec = new vdecoder();

            dec.n         = code.n;
            dec.k         = code.k;
            dec.recursive = code.rgen != 0 ? 1 : 0;
            dec.intrvl    = short.MaxValue / (dec.n * sbyte.MaxValue) - dec.k;

            if (dec.n != 3 || dec.k != 7)
            {
                throw new Exception();
            }

            if (code.term == CONV_TERM.FLUSH)
            {
                dec.len = code.len + code.k - 1;
            }
            else
            {
                dec.len = code.len + TAIL_BITING_EXTRA * 2;
            }

            dec.trellis = generate_trellis(code);

            dec.pathsBuffer = UnsafeBuffer.Create(sizeof(short *) * dec.len * ns);
            dec.pathsPtr    = (short *)dec.pathsBuffer;
            dec.paths       = new short *[dec.len];
            for (i = 0; i < dec.len; i++)
            {
                dec.paths[i] = &dec.pathsPtr[i * ns];
            }

            return(dec);
        }
Пример #7
0
        /*
         * Forward trellis recursion
         *
         * Generate branch metrics and path metrics with a combined function. Only
         * accumulated path metric sums and path selections are stored. Normalize on
         * the interval specified by the decoder.
         */
        static void _conv_decode(vdecoder dec, sbyte *seq, CONV_TERM term, int len)
        {
            int      i, j = 0;
            vtrellis trellis = dec.trellis;

            if (term == CONV_TERM.TAIL_BITING)
            {
                j = len - TAIL_BITING_EXTRA;
            }

            for (i = 0; i < dec.len; i++, j++)
            {
                if (term == CONV_TERM.TAIL_BITING && j == len)
                {
                    j = 0;
                }

                gen_metrics_k7_n3(&seq[dec.n * j],
                                  trellis.outputs,
                                  trellis.sums,
                                  dec.paths[i],
                                  ((i % dec.intrvl) != 0 ? 0 : 1));                //flipped on purpose
            }
        }
Пример #8
0
 /* Release decoder object */
 static void free_vdec(vdecoder dec)
 {
     dec.pathsBuffer.Dispose();
 }