예제 #1
0
파일: Viterbi.cs 프로젝트: ptaa32/ARDOP
        // GenerateMetrics
        public byte[] DecodeFromSymbolBits(byte[] bytSymbolBits)
        {
            // Normally called with bytSymboBits padded with 16 0 symbols tagged on to "flush" decoder
            // Number of Output bytes = (bytSymbolsBits.length - 16)/16

            Int32 intMetric = 0;

            byte[] bytOutput = new byte[bytSymbolBits.Length / 16 - 1];
            Int32 ptrOutput = 0;
            Int32 intBitcnt = 0;
            Int32[] intMets = new Int32[4];
            Int32 intBestmetric = default(Int32);
            Int32 intBestState = default(Int32);
            Int32 i = default(Int32);
            stcState[,] stcState = new stcState[2, 64];
            Int32 ptrCurrent = 0;
            Int32 ptrNext = 1;
            int intSymbolsPtr = 0;

            //	 Initialize starting metrics to prefer 0 state
            stcState[ptrCurrent, 0].metric = 0;
            for (i = 1; i <= 63; i++) {
                stcState[ptrCurrent, i].metric = -999999;
            }
            stcState[ptrCurrent, 0].path = 0;
            for (intBitcnt = 0; intBitcnt <= 8 * bytOutput.Length - 1; intBitcnt++) {
                intMets[0] = aryMettab[0, bytSymbolBits[intSymbolsPtr]] + aryMettab[0, bytSymbolBits[intSymbolsPtr + 1]];
                //		mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]];
                intMets[1] = aryMettab[0, bytSymbolBits[intSymbolsPtr]] + aryMettab[1, bytSymbolBits[intSymbolsPtr + 1]];
                //		mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]];
                intMets[2] = aryMettab[1, bytSymbolBits[intSymbolsPtr]] + aryMettab[0, bytSymbolBits[intSymbolsPtr + 1]];
                //		mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]];
                intMets[3] = aryMettab[1, bytSymbolBits[intSymbolsPtr]] + aryMettab[1, bytSymbolBits[intSymbolsPtr + 1]];
                //		mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]];
                intSymbolsPtr += 2;

                // Do the Butterfly calcs here Implemented as a loop vs Macro
                for (i = 0; i <= 31; i++) {
                    int intM0 = 0;
                    int intM1 = 0;
                    int sym = bytBtfIndx[i];
                    //	 ACS for 0 branch
                    intM0 = stcState[ptrCurrent, i].metric + intMets[sym];
                    intM1 = stcState[ptrCurrent, i + 32].metric + intMets[3 ^ sym];
                    if (intM0 > intM1) {
                        stcState[ptrNext, 2 * i].metric = intM0;
                        stcState[ptrNext, 2 * i].path = stcState[ptrCurrent, i].path << 1;
                    } else {
                        stcState[ptrNext, 2 * i].metric = intM1;
                        stcState[ptrNext, 2 * i].path = (stcState[ptrCurrent, i + 32].path << 1) | Convert.ToUInt32(1);
                    }
                    //	ACS for 1 branch
                    intM0 = stcState[ptrCurrent, i].metric + intMets[3 ^ sym];
                    intM1 = stcState[ptrCurrent, i + 32].metric + intMets[sym];
                    if (intM0 > intM1) {
                        stcState[ptrNext, 2 * i + 1].metric = intM0;
                        stcState[ptrNext, 2 * i + 1].path = stcState[ptrCurrent, i].path << 1;
                    } else {
                        stcState[ptrNext, 2 * i + 1].metric = intM1;
                        stcState[ptrNext, 2 * i + 1].path = (stcState[ptrCurrent, i + 32].path << 1) | Convert.ToUInt32(1);
                    }
                }

                //		 Swap current and next states
                if ((intBitcnt & 1) != 0) {
                    ptrCurrent = 0;
                    ptrNext = 1;
                } else {
                    ptrCurrent = 1;
                    ptrNext = 0;
                }

                if (intBitcnt > bytSymbolBits.Length - 7) {
                    //	 In tail, poison non-zero nodes
                    for (i = 1; i <= 63; i += 2) {
                        stcState[ptrCurrent, i].metric = -9999999;
                    }
                }
                //	 Produce output every 8 bits once path memory is full
                if (((intBitcnt % 8) == 5) & intBitcnt > 32) {
                    //	Find current best path
                    intBestmetric = stcState[ptrCurrent, 0].metric;
                    intBestState = 0;
                    for (i = 1; i <= 63; i++) {
                        if (stcState[ptrCurrent, i].metric > intBestmetric) {
                            intBestmetric = stcState[ptrCurrent, i].metric;
                            intBestState = i;
                        }
                    }
                    //Debug.WriteLine("Beststate:" & intBestState.ToString & " metric=" & stcState(ptrCurrent, intBestState).metric.ToString & "  path=" & stcState(ptrCurrent, intBestState).path.ToString)
                    bytOutput[ptrOutput] = Convert.ToByte(stcState[ptrCurrent, intBestState].path >> 24);
                    ptrOutput += 1;
                }
            }
            //	Output remaining bits from 0 state
            if (intBitcnt % 8 != 6) {
                stcState[ptrCurrent, 0].path = stcState[ptrCurrent, 0].path << (6 - (intBitcnt % 8));
            }
            bytOutput[ptrOutput] = Convert.ToByte(stcState[ptrCurrent, 0].path >> 24);
            ptrOutput += 1;
            bytOutput[ptrOutput] = Convert.ToByte(0xff & stcState[ptrCurrent, 0].path >> 16);
            ptrOutput += 1;
            bytOutput[ptrOutput] = Convert.ToByte(0xff & stcState[ptrCurrent, 0].path >> 8);
            ptrOutput += 1;
            bytOutput[ptrOutput] = Convert.ToByte(0xff & stcState[ptrCurrent, 0].path);
            intMetric = stcState[ptrCurrent, 0].metric;
            return bytOutput;
        }