// 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; }