📄 viterbidecoder.cpp
字号:
/* Reset all metrics in the trellis. We initialize all states exept of
the zero state with a high metric, because we KNOW that the state "0"
is the transmitted state */
pOldTrelMetric[0] = (_VITMETRTYPE) 0;
for (i = 1; i < MC_NUM_STATES; i++)
pOldTrelMetric[i] = MC_METRIC_INIT_VALUE;
/* Backward direction */
for (i = iNumOutBitsWithMemory - 1; i >= 0; i--)
{
/* Variables storing the likelihood of 0 and 1 bit */
_VITMETRTYPE rL0 = MC_METRIC_INIT_VALUE;
_VITMETRTYPE rL1 = MC_METRIC_INIT_VALUE;
/* Update trellis --------------------------------------------------- */
#define BUTTERFLY(cur, prev0, prev1, met0, met1) \
{ \
/* Calculate metrics from the two previous states, use the old
metric from the previous states plus the "transition-metric" */ \
const _VITMETRTYPE rFiStAccMetricPrev0 = \
pOldTrelMetric[prev0] + METRICSET(i)[met0]; \
const _VITMETRTYPE rFiStAccMetricPrev1 = \
pOldTrelMetric[prev1] + METRICSET(i)[met1]; \
\
/* Take path with smallest metric */ \
if (rFiStAccMetricPrev0 < rFiStAccMetricPrev1) \
{ \
/* Save minimum metric for this state */ \
pCurTrelMetric[cur] = rFiStAccMetricPrev0; \
\
/* Likelihood for 0 bit: max(alpha + beta) */ \
const _VITMETRTYPE rL0tmp = \
rFiStAccMetricPrev0 + matrAlpha[i][cur]; \
if (rL0tmp < rL0) \
rL0 = rL0tmp; \
} \
else \
{ \
/* Save minimum metric for this state */ \
pCurTrelMetric[cur] = rFiStAccMetricPrev1; \
\
/* Likelihood for 1 bit: max(alpha + beta) */ \
const _VITMETRTYPE rL1tmp = \
rFiStAccMetricPrev1 + matrAlpha[i][cur]; \
if (rL1tmp < rL1) \
rL1 = rL1tmp; \
} \
}
/* Unroll butterflys with backwards direction parameters */
BUTTERFLY( 0, 0, 1, 0, 15)
BUTTERFLY( 1, 2, 3, 6, 9)
BUTTERFLY( 2, 4, 5, 11, 4)
BUTTERFLY( 3, 6, 7, 13, 2)
BUTTERFLY( 4, 8, 9, 11, 4)
BUTTERFLY( 5, 10, 11, 13, 2)
BUTTERFLY( 6, 12, 13, 0, 15)
BUTTERFLY( 7, 14, 15, 6, 9)
BUTTERFLY( 8, 16, 17, 4, 11)
BUTTERFLY( 9, 18, 19, 2, 13)
BUTTERFLY(10, 20, 21, 15, 0)
BUTTERFLY(11, 22, 23, 9, 6)
BUTTERFLY(12, 24, 25, 15, 0)
BUTTERFLY(13, 26, 27, 9, 6)
BUTTERFLY(14, 28, 29, 4, 11)
BUTTERFLY(15, 30, 31, 2, 13)
BUTTERFLY(16, 32, 33, 9, 6)
BUTTERFLY(17, 34, 35, 15, 0)
BUTTERFLY(18, 36, 37, 2, 13)
BUTTERFLY(19, 38, 39, 4, 11)
BUTTERFLY(20, 40, 41, 2, 13)
BUTTERFLY(21, 42, 43, 4, 11)
BUTTERFLY(22, 44, 45, 9, 6)
BUTTERFLY(23, 46, 47, 15, 0)
BUTTERFLY(24, 48, 49, 13, 2)
BUTTERFLY(25, 50, 51, 11, 4)
BUTTERFLY(26, 52, 53, 6, 9)
BUTTERFLY(27, 54, 55, 0, 15)
BUTTERFLY(28, 56, 57, 6, 9)
BUTTERFLY(29, 58, 59, 0, 15)
BUTTERFLY(30, 60, 61, 13, 2)
BUTTERFLY(31, 62, 63, 11, 4)
BUTTERFLY(32, 0, 1, 15, 0)
BUTTERFLY(33, 2, 3, 9, 6)
BUTTERFLY(34, 4, 5, 4, 11)
BUTTERFLY(35, 6, 7, 2, 13)
BUTTERFLY(36, 8, 9, 4, 11)
BUTTERFLY(37, 10, 11, 2, 13)
BUTTERFLY(38, 12, 13, 15, 0)
BUTTERFLY(39, 14, 15, 9, 6)
BUTTERFLY(40, 16, 17, 11, 4)
BUTTERFLY(41, 18, 19, 13, 2)
BUTTERFLY(42, 20, 21, 0, 15)
BUTTERFLY(43, 22, 23, 6, 9)
BUTTERFLY(44, 24, 25, 0, 15)
BUTTERFLY(45, 26, 27, 6, 9)
BUTTERFLY(46, 28, 29, 11, 4)
BUTTERFLY(47, 30, 31, 13, 2)
BUTTERFLY(48, 32, 33, 6, 9)
BUTTERFLY(49, 34, 35, 0, 15)
BUTTERFLY(50, 36, 37, 13, 2)
BUTTERFLY(51, 38, 39, 11, 4)
BUTTERFLY(52, 40, 41, 13, 2)
BUTTERFLY(53, 42, 43, 11, 4)
BUTTERFLY(54, 44, 45, 6, 9)
BUTTERFLY(55, 46, 47, 0, 15)
BUTTERFLY(56, 48, 49, 2, 13)
BUTTERFLY(57, 50, 51, 4, 11)
BUTTERFLY(58, 52, 53, 9, 6)
BUTTERFLY(59, 54, 55, 15, 0)
BUTTERFLY(60, 56, 57, 9, 6)
BUTTERFLY(61, 58, 59, 15, 0)
BUTTERFLY(62, 60, 61, 2, 13)
BUTTERFLY(63, 62, 63, 4, 11)
#undef BUTTERFLY
/* Calculate final soft out value */
if (i < iNumOutBits)
vecOutputBits[i] = rL0 - rL1;
/* Swap trellis data pointers (old -> new, new -> old) */
_VITMETRTYPE* pTMPTrelMetric = pCurTrelMetric;
pCurTrelMetric = pOldTrelMetric;
pOldTrelMetric = pTMPTrelMetric;
}
#endif
#ifndef USE_MAX_LOG_MAP
/* Chainback the decoded bits from trellis (only for MLSE) -------------- */
/* The end-state is defined by the DRM standard as all-zeros (shift register
in the encoder is padded with zeros at the end */
iCurDecState = 0;
for (i = 0; i < iNumOutBits; i++)
{
/* Read out decisions "backwards". Mask only first bit, because in MMX
implementation, all 8 bits of a "char" are set to the decision */
const _DECISIONTYPE decCurBit =
matdecDecisions[iNumOutBitsWithMemory - i - 1][iCurDecState] & 1;
/* Calculate next state from previous decoded bit -> shift old data
and add new bit */
iCurDecState = (iCurDecState >> 1) | (decCurBit << 5);
/* Set decisions "backwards" in actual result vector */
vecOutputBits[iNumOutBits - i - 1] = (_BINARY) decCurBit;
}
#endif
#ifdef USE_SIMD
/* No accumulated metric available because of normalizing the metric because
of fixed-point implementation */
return (_REAL) 1.0;
#else
/* Return normalized accumulated minimum metric */
return pOldTrelMetric[0] / iDistCnt;
#endif
}
void CViterbiDecoder::Init(CParameter::ECodScheme eNewCodingScheme,
CParameter::EChanType eNewChannelType, int iN1,
int iN2, int iNewNumOutBitsPartA,
int iNewNumOutBitsPartB, int iPunctPatPartA,
int iPunctPatPartB, int iLevel)
{
/* Number of bits out is the sum of all protection levels */
iNumOutBits = iNewNumOutBitsPartA + iNewNumOutBitsPartB;
/* Number of out bits including the state memory */
iNumOutBitsWithMemory = iNumOutBits + MC_CONSTRAINT_LENGTH - 1;
/* Init vector, storing table for puncturing pattern and generate pattern */
veciTablePuncPat.Init(iNumOutBitsWithMemory);
veciTablePuncPat = GenPuncPatTable(eNewCodingScheme, eNewChannelType, iN1,
iN2, iNewNumOutBitsPartA, iNewNumOutBitsPartB, iPunctPatPartA,
iPunctPatPartB, iLevel);
/* Init vector for storing the decided bits */
matdecDecisions.Init(iNumOutBitsWithMemory, MC_NUM_STATES);
#ifdef USE_MAX_LOG_MAP
/* Matrix is needed for storing the metrics since we use forward and
backward Viterbi algorithm */
matrMetricSet.Init(iNumOutBitsWithMemory, MC_NUM_OUTPUT_COMBINATIONS);
/* Init matrix for storing the accumulated metrics of forward Viterbi */
matrAlpha.Init(iNumOutBitsWithMemory, MC_NUM_STATES);
#endif
}
CViterbiDecoder::CViterbiDecoder()
{
#if 0
/* Create trellis *********************************************************/
/* Activate this code to generate the table needed for the butterfly calls
in the processing routine */
/* We need to analyze 2^(MC_CONSTRAINT_LENGTH - 1) states in the trellis */
int i;
int iPrev0IndexForw[MC_NUM_STATES];
int iPrev1IndexForw[MC_NUM_STATES];
int iMetricPrev0Forw[MC_NUM_STATES];
int iMetricPrev1Forw[MC_NUM_STATES];
int iPrev0IndexBackw[MC_NUM_STATES];
int iPrev1IndexBackw[MC_NUM_STATES];
int iMetricPrev0Backw[MC_NUM_STATES];
int iMetricPrev1Backw[MC_NUM_STATES];
for (i = 0; i < MC_NUM_STATES; i++)
{
/* Define previous states ------------------------------------------- */
/* We define in this trellis that we shift the bits from right to
the left. We use the transition-bits which "fall" out of the
shift-register (forward case) */
iPrev0IndexForw[i] = (i >> 1); /* Old state, Leading "0"
(automatically inserted by
shifting */
iPrev1IndexForw[i] = (i >> 1) /* Old state */
| (1 << (MC_CONSTRAINT_LENGTH - 2)); /* New "1", must be on position
MC_CONSTRAINT_LENGTH - 1 */
/* We define in this trellis that we shift the bits from left to
the right. We use the transition-bits which get in the
shift-register (backward case) */
/* Mask operator for length of state register of this code
[... 0, 0, 1, 1, 1, 1, 1, 1] */
const int iStRegMask = /* "MC_CONSTRAINT_LENGTH - 1" number of ones */
1 | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
iPrev0IndexBackw[i] = (i << 1) & iStRegMask; /* Old state, Beginning "0"
(automatically inserted
by shifting. Mask result
to have length of state
register */
iPrev1IndexBackw[i] = ((i << 1) & iStRegMask) | 1; /* New "1", must on
first position */
/* Assign metrics to the transitions from both paths ---------------- */
/* We define with the metrics the order: [b_3, b_2, b_1, b_0] */
iMetricPrev0Forw[i] = 0;
iMetricPrev1Forw[i] = 0;
iMetricPrev0Backw[i] = 0;
iMetricPrev1Backw[i] = 0;
for (int j = 0; j < MC_NUM_OUTPUT_BITS_PER_STEP; j++)
{
/* Calculate respective metrics from convolution of state and
transition bit */
/* forwards */
/* "0" */
iMetricPrev0Forw[i] |= Convolution(
/* Set all states in the shift-register for encoder. Use
current state with a leading "0" (which is automatically
there) */
i
/* Use generator-polynomial j */
, j)
/* Shift generated bit to the correct position */
<< j;
/* "1" */
iMetricPrev1Forw[i] |= Convolution(
/* Set all states in the shift-register for encoder. Use
current state with a leading "1". The position of this
bit is "MC_CONSTRAINT_LENGTH" (shifting from position 1:
"MC_CONSTRAINT_LENGTH - 1") */
i | (1 << (MC_CONSTRAINT_LENGTH - 1))
/* Use generator-polynomial j */
, j)
/* Shift generated bit to the correct position */
<< j;
/* backwards */
/* "0" */
iMetricPrev0Backw[i] |= Convolution(
/* Set all states in the shift-register for encoder. Use
current state with a "0" at beginning (which is automatically
there) */
(i << 1),
/* Use generator-polynomial j */
j)
/* Shift generated bit to the correct position */
<< j;
/* "1" */
iMetricPrev1Backw[i] |= Convolution(
/* Set all states in the shift-register for encoder. Use
current state with a "1" at beginning */
(i << 1) | 1,
/* Use generator-polynomial j */
j)
/* Shift generated bit to the correct position */
<< j;
}
}
/* Save trellis in file (for substituting in the code) */
static FILE* pFile = fopen("test/trellis.dat", "w");
/* forwards */
fprintf(pFile, "/* forwards */\n");
for (i = 0; i < MC_NUM_STATES; i += 2)
fprintf(pFile, "BUTTERFLY(%2d, %2d, %2d, %2d, %2d, %2d)\n", i, i + 1,
iPrev0IndexForw[i], iPrev1IndexForw[i],
iMetricPrev0Forw[i], iMetricPrev1Forw[i]);
/* backwards */
fprintf(pFile, "\n\n\n/* backwards */\n");
for (i = 0; i < MC_NUM_STATES; i++)
fprintf(pFile, "BUTTERFLY(%2d, %2d, %2d, %2d, %2d)\n", i,
iPrev0IndexBackw[i], iPrev1IndexBackw[i],
iMetricPrev0Backw[i], iMetricPrev1Backw[i]);
fprintf(pFile, "\n");
fflush(pFile);
exit(1);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -