viterbi.cpp

来自「signal-processing.rar信号处理demo原码」· C++ 代码 · 共 562 行 · 第 1/2 页

CPP
562
字号
/*
//
//               INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright (c) 2006 Intel Corporation. All Rights Reserved.
//
*/

#include "time.h"
#include "conio.h"
#include "stdlib.h"
#include "math.h"
#include "stdio.h"

#include "viterbi.h"



static const int DX[12] = {0, 2, 2, 0, 0, 2,  2, 4, 4, -2, -2,  0};
static const int DY[12] = {0, 0, 2, 2, 4, 4, -2, 2, 0,  0,  2, -2};

static Ipp8u POINTLABEL[4][4] =
{
  0, 7, 4, 3,
  5, 2, 1, 6,
  4, 3, 0, 7,
  1, 6, 5, 2
};


Ipp8u GetEncoderPoint(int numStates, int prevState, int inBits)
{
  Ipp8u tmp;
  Ipp8u e;
  Ipp8u c;

  tmp = (Ipp8u)(prevState >> 1);

  switch(numStates)
  {
    case 16:
      tmp ^= (inBits & 3) ^ ((inBits & 2) << 1) ^ ((prevState & 1) << 2);
      tmp |= (prevState & 1) << 3;
      break;

    case 32:
      tmp ^= (((inBits & 2) >> 1) * 9) ^ ((inBits & 1) << 2) ^ ((inBits & 8) >> 2);
      tmp |= (prevState  & 1) << 4;
      break;

    case 64:
      tmp  = (Ipp8u)(( prevState & 1 ) << 1);
      tmp |= (((prevState ^ inBits) & 2) >> 1) ^ (( prevState & 8) >> 3);
      tmp |= (( prevState & 8) >> 1);
      e = (Ipp8u)(((prevState & 16 ) >> 1) ^ ((inBits & 1) << 3));
      tmp |=  e ^ (prevState & 8);
      c = (Ipp8u)((prevState & 32) ^ ((prevState & 16) << 1));
      tmp |= (c >> 1) ^ ((prevState & 4) << 2 ) ^
             (((prevState & 8) << 1) & ((inBits & 2) << 3)) ^ ((inBits & 4) << 2);
      tmp |= ((e << 2) & ((prevState & 8) << 2 )) ^ c ^ (( inBits & 8) << 2);
      break;

    default:
      break;
  }    

  return tmp;
} // GetEncoderPoint()


/****************************************************************************/
/* Function:          InitViterbiDecoder                                    */
/*                    Initialise Viterbi decoder                            */
/* Input parametrs:   ViterbiParam - pointer to structure with Viterbi      */
/*                    decoder parametrs                                     */
/* Output value:      -                                                     */
/****************************************************************************/
void InitViterbiDecoder(ViterbiInfo* ViterbiParam)
{
    Ipp16u i,j;

    ViterbiParam->m_NumInputBits = (Ipp8u)(ViterbiParam->m_State/32+2);
    ViterbiParam->m_BitInvertion = 0;
    ViterbiParam->m_TableDept = ViterbiParam->m_State;
    ViterbiParam->m_TickMask = (Ipp16u)(ViterbiParam->m_TableDept-1);
    ViterbiParam->m_NumInputCombination = (Ipp8u)(ViterbiParam->m_State/4);
    ViterbiParam->m_Tick = ViterbiParam->m_State;

    for( i = 0; i < ViterbiParam->m_State; i++ )
    {
        ViterbiParam->m_PathError[i]   = 32768;
        ViterbiParam->m_BranchError[i] = 65535;

        for( j = 0; j < ViterbiParam->m_NumInputCombination; j++)
        {
           if(ViterbiParam->m_State == 32)
           {
               ViterbiParam->m_NextState[i*ViterbiParam->m_NumInputCombination + j] =
                 GetEncoderPoint(ViterbiParam->m_State, (Ipp8u)i, (Ipp8u)(j+(j&4)*2));
           }
           else
           {
               ViterbiParam->m_NextState[i*ViterbiParam->m_NumInputCombination + j] =
                 GetEncoderPoint(ViterbiParam->m_State, (Ipp8u)i, (Ipp8u)j);
           }
        }
    }

    ViterbiParam->m_PathError[0] = 0;
    ViterbiParam->m_flRealData   = 0;

    for( i = 0; i < ViterbiParam->m_State * ViterbiParam->m_TableDept; i++)
    {
        ViterbiParam->m_PathTable[i].m_oldState = 0;
    }

    return;
} // InitViterbiDecoder()


void DeepTraceBack(ViterbiInfo* ViterbiParam,Ipp16sc Output[2],Ipp32s Deep)
{
    Ipp16s firstIndex;
    Ipp16s secondIndex;
    Ipp16s Index;
    Ipp16u PrevSost;
    Ipp16u i;
    
    Index = ViterbiParam->m_Tick;
    PrevSost = ViterbiParam->m_MinSost;
    
    for(i = 0; i < Deep; i++ )
    {
        PrevSost = ViterbiParam->m_PathTable[ Index * ViterbiParam->m_State + PrevSost].m_oldState;
        Index = (Ipp16s)((Index - 1) & ViterbiParam->m_TickMask);
    }
    
    firstIndex = (Ipp16s)(ViterbiParam->m_PathTable[ Index * ViterbiParam->m_State + PrevSost].re & 0xff);
    secondIndex = (Ipp16s)(( ViterbiParam->m_PathTable[ Index * ViterbiParam->m_State + PrevSost].re >> 8 ) & 0xff);
    
    Output[0].re = (Ipp16s)(ViterbiParam->m_ReferencePoint[Index].m_firstPoint.re + (Ipp16s)DX[firstIndex]*128);
    Output[0].im = (Ipp16s)(ViterbiParam->m_ReferencePoint[Index].m_firstPoint.im + (Ipp16s)DY[firstIndex]*128);
    Output[1].re = (Ipp16s)(ViterbiParam->m_ReferencePoint[Index].m_secondPoint.re + (Ipp16s)DX[secondIndex]*128);
    Output[1].im = (Ipp16s)(ViterbiParam->m_ReferencePoint[Index].m_secondPoint.im + (Ipp16s)DY[secondIndex]*128);

    return;
} // DeepTraceBack()


/****************************************************************************/
/* Function:          TraceBack                                             */
/*                    Find start point which place in start of path with    */
/*                    minimum current accumulation error metrics            */
/* Input parametrs:   ViterbiParam - pointer to structure with decoder      */ 
/*                                   parametrs.                             */
/*                    Output - pointer to array 2 2D symbls which ideal     */
/*                             will containe ideal symbls                   */                           
/* Output value:  -                                                         */
/****************************************************************************/

void TraceBack(ViterbiInfo* ViterbiParam,Ipp16sc Output[2])
{
    DeepTraceBack(ViterbiParam, Output, ViterbiParam->m_TableDept - 1);
    return;
}


/***************************************************************************/
/* Function:          GetViterbiData                                       */
/*                    This is Viterbi algoritm                             */
/* Input  parametrs:  InputPoint  - pointer to 2 2D received symbls (which */
/*                    consist 4D symbl) in format 9:7                      */             
/*                    OutputPoint - pointer to array where ideal 2 2D sym- */
/*                    bols will be written                                 */
/*                    ViterbiParam - pointer to structure with decoder pa- */
/*                    rametrs                                              */
/* Output value:      If > 0, then data in OutputPoint is true, else dont  */
/*                    never used this date                                 */
/***************************************************************************/
Ipp8u GetViterbiData(Ipp16sc InputPoint[2], Ipp16sc OutputPoint[2], ViterbiInfo* ViterbiParam)
{
    Ipp16sc     refPointNearest;
    Ipp32s      PrevIndex;
    Ipp32s      PresentIndex;
    IppStatus    st;

    if(ViterbiParam->m_Tick == 0)
      ViterbiParam->m_flRealData = 100;

    if(ViterbiParam->m_flRealData != 0)
    {
        TraceBack(ViterbiParam, OutputPoint);
    }

    PrevIndex = (ViterbiParam->m_Tick) * ViterbiParam->m_State;
    ViterbiParam->m_Tick = (Ipp16u)( (ViterbiParam->m_Tick + 1) & ViterbiParam->m_TickMask );

    PresentIndex = ViterbiParam->m_State*ViterbiParam->m_Tick; 

/* Get variant point for first 2D symbol in 4D */
   st = ippsGetVarPointDV_16sc(&InputPoint[0],
                               &refPointNearest,
                               ViterbiParam->m_VariantPoint,
                               (Ipp8u*)POINTLABEL,
                               (Ipp32s)ViterbiParam->m_State);
   if(ippStsNoErr != st)
   {
       printf(" Error in ippiGetVarPointDV: %s\n", ippGetStatusString(st));
       return 1;
   }
    ViterbiParam->m_ReferencePoint[ViterbiParam->m_Tick].m_firstPoint = refPointNearest;

    /* Get variant point for second 2D symbol */
    st = ippsGetVarPointDV_16sc(&InputPoint[1],
                                &refPointNearest,
                                ViterbiParam->m_VariantPoint+8,
                                (Ipp8u*)POINTLABEL,
                                (Ipp32s)ViterbiParam->m_State);
    if(ippStsNoErr != st)
   {
       printf(" Error in ippiGetVarPointDV: %s\n", ippGetStatusString(st));
       return 1;
   } 
    ViterbiParam->m_ReferencePoint[ViterbiParam->m_Tick].m_secondPoint = refPointNearest;

/* compute current 4D subset */
    st = ippsBuildSymblTableDV4D_16sc(ViterbiParam->m_VariantPoint,
                                     (Ipp16sc*)ViterbiParam->m_CurrentSubsetPoint,
                                     (Ipp32s)ViterbiParam->m_State,
                                     (Ipp32s)ViterbiParam->m_BitInvertion);
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsBuildSymblTableDV4D: %s\n", ippGetStatusString(st));
       return 1;
    }
    /* Work with all old state */
    st = ippsCalcStatesDV_16sc( ViterbiParam->m_PathError,
                                ViterbiParam->m_NextState,
                                ViterbiParam->m_BranchError,
                                (Ipp16s*)ViterbiParam->m_CurrentSubsetPoint,
                                (Ipp16s*)ViterbiParam->m_PathTable,
                                (Ipp32s)ViterbiParam->m_State,
                                (Ipp32s)PresentIndex );
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsCalcStatesDV: %s\n", ippGetStatusString(st));
       return 1;
    }
    st = ippsUpdatePathMetricsDV_16u(ViterbiParam->m_BranchError,
                                     &ViterbiParam->m_MinPathError,
                                     &ViterbiParam->m_MinSost,
                                     ViterbiParam->m_PathError,
                                     ViterbiParam->m_State);
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsUpdatePathMetricsDV: %s\n", ippGetStatusString(st));
       return 1;
    }
    PresentIndex += ViterbiParam->m_MinSost;

    return 0;
} // GetViterbiData()


void ViterbiInit( ViterbiTestInfo *viterbiInf, Ipp8u viterbiState)
{
    switch( viterbiState )
    {
    case ViterbiState16:
        viterbiInf->vState = 16;
        viterbiInf->numPossStates = 4;
        viterbiInf->ceStates = *ceStates16;
        viterbiInf->ceInput = *ce16Input;
        break;

    case ViterbiState32:
        viterbiInf->vState = 32;
        viterbiInf->numPossStates = 8;
        viterbiInf->ceStates = *ceStates32;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?