viterbi.cpp

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

CPP
562
字号
        viterbiInf->ceInput = *ce32Input;
        break;

    case ViterbiState64:
        viterbiInf->vState = 64;
        viterbiInf->numPossStates = 16;
        viterbiInf->ceStates = *ceStates64;
        viterbiInf->ceInput = *ce64Input;
        break;

    default:
        break;
    }

    viterbiInf->ceDlState = 0;

    return;
} // ViterbiInit()


bool TrellisEncoder( const Real4DSymbl *mapOut, ViterbiTestInfo *vInf )
{
    bool    U0;                                 /* trellis encoder output bit           */
    Ipp8u   ceInput;                            /* convolutional encoder input Y4Y3Y2Y1 */
    Ipp8u   ssLabel_0, ssLabel_1;               /* 2 subset labels s(2m), s(2m+1)       */
    Ipp8u   *ceState = &vInf->ceDlState;        /* convolutional encoder delay state    */

    U0 = *ceState & 0x1;

/* --------------------- Symbol-to-bit converter --------------------------- */
    ssLabel_0 = subsetLabel[(35 - mapOut->m_firstPoint.im)/2][(35 + mapOut->m_firstPoint.re)/2];
    ssLabel_1 = subsetLabel[(35 - mapOut->m_secondPoint.im)/2][(35 + mapOut->m_secondPoint.re)/2];

/* --------------------- Convolutional encoder ----------------------------- */
    ceInput = vInf->ceInput[8*ssLabel_0 + ssLabel_1];
    *ceState = vInf->ceStates[ *ceState*vInf->numPossStates + ceInput];
    U0 = *ceState & 0x1;

    return U0;
} // TrellisEncoder()


void GetTrellisSequence( Real4DSymbl *trSeq, int len, ViterbiTestInfo *vInf )
{
    int         i;
    Ipp8u       I1;     /* bit I1(i,j) from parser                          */
    Ipp8u       U0;     /* trellis encoder output bit                       */
    Ipp8u       Z;      /* differential encoder output integer              */
    Real4DSymbl v;      /* 2 2D points from the quarter superconstellation  */
    Real4DSymbl u;      /* 2 2D output siganal points                       */

/* ------------------ Quarter superconstellation indices ------------------- */
    const Ipp16s scIdx[18] = { -35, -31, -27, -23, -19, -15, -11, -7, -3,
                                 1,   5,   9,  13,  17,  21,  25, 29, 33 };
    U0 = 0;

    srand((unsigned int) time(NULL) );

    for( i = 0; i < len; i++ )
    {
/* --------------------- Initialize input data ----------------------------- */
        v.m_firstPoint.re = scIdx[rand()/1821];
        v.m_firstPoint.im = scIdx[rand()/1821];

        v.m_secondPoint.re = scIdx[rand()/1821];
        v.m_secondPoint.im = scIdx[rand()/1821];

        I1 = (Ipp8u)(rand()/16384);
      
        Z = (Ipp8u)(rand()/10923);
       
/* ---------------- Rotate it according to Z, I1, U0 ----------------------- */
        switch(Z)   /* rotate first point  */
        {
        case 0:      /* 0 degrees           */
            u.m_firstPoint.re = v.m_firstPoint.re;
            u.m_firstPoint.im = v.m_firstPoint.im;
            break;

        case 1:     /* 90 degrees         */
            u.m_firstPoint.re = v.m_firstPoint.im;
            u.m_firstPoint.im = (Ipp16u)(-v.m_firstPoint.re);
            break;

        case 2:     /* 180 degrees        */
            u.m_firstPoint.re = (Ipp16u)(-v.m_firstPoint.re);
            u.m_firstPoint.im = (Ipp16u)(-v.m_firstPoint.im);
            break;

        case 3:    /* 270 degrees        */
            u.m_firstPoint.re = (Ipp16u)(-v.m_firstPoint.im);
            u.m_firstPoint.im = v.m_firstPoint.re;
            break;

        default:
            u.m_firstPoint.re = 0;
            u.m_firstPoint.im = 0;
        }

        switch( (Z + 2*I1 + U0)%4 ) /* rotate second point  */
        {
        case 0:      /* 0 degrees         */
            u.m_secondPoint.re = v.m_secondPoint.re;
            u.m_secondPoint.im = v.m_secondPoint.im;
            break;

        case 1:     /* 90 degrees        */
            u.m_secondPoint.re = v.m_secondPoint.im;
            u.m_secondPoint.im = (Ipp16u)(-v.m_secondPoint.re);
            break;

        case 2:     /* 180 degrees       */
            u.m_secondPoint.re = (Ipp16u)(-v.m_secondPoint.re);
            u.m_secondPoint.im = (Ipp16u)(-v.m_secondPoint.im);
            break;

        case 3:     /* 270 degrees       */
            u.m_secondPoint.re = (Ipp16u)(-v.m_secondPoint.im);
            u.m_secondPoint.im = v.m_secondPoint.re;
            break;

        default:
            u.m_secondPoint.re = 0;
            u.m_secondPoint.im = 0;
       }

/* -------------------------------- Output --------------------------------- */
        trSeq[i].m_firstPoint.re = u.m_firstPoint.re;
        trSeq[i].m_firstPoint.im = u.m_firstPoint.im;
        trSeq[i].m_secondPoint.re = u.m_secondPoint.re;
        trSeq[i].m_secondPoint.im = u.m_secondPoint.im;

/* -------------------------------- Get U0 --------------------------------- */
        U0 = TrellisEncoder( &u, vInf );
    }

    return;
} // GetTrellisSequence()


int AddChannelNoise( Real4DSymbl *tOutput, Real4DSymbl *vInput,int len, double SNR )
{
    int             i, j;
    int             sLen;           /* signal lenght            */
    float           sMagn;          /* output signal power      */
    float           cFreq;          /* carrier frequency        */
    float           pPhase;         /* tone phase               */
    float           *samples;       /* output signal            */
    float           *Cos, *Sin;
    Ipp16s          *gns;           /* white gaussian nois      */
    Ipp16s          stDev;          /* noise standard deviation */
    unsigned int    gnsSeed;
    IppStatus       st;
    sLen = 6*len;

/* ----------------------- Generate output samples ------------------------- */
    Cos = ippsMalloc_32f( sLen );
    
    Sin = ippsMalloc_32f( sLen );
    
    cFreq = 0.1904345f;    /* maximum speed */

    pPhase = 0.0f;
    st = ippsTone_Direct_32f( Cos, sLen, 1.0f, cFreq, &pPhase, ippAlgHintAccurate );
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsToneDirect: %s\n", ippGetStatusString(st));
       return 1;
   }
    pPhase = (float)IPP_PI2;
    st = ippsTone_Direct_32f( Sin, sLen, 1.0f, cFreq, &pPhase, ippAlgHintAccurate );
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsTone_Direct_32f: %s\n", ippGetStatusString(st));
       return 1;
    }
    samples = ippsMalloc_32f( sLen );

    for( i = 0; i < len; i++ )
    {
        tOutput[i].m_firstPoint.re = (Ipp16s)(128*tOutput[i].m_firstPoint.re);
        tOutput[i].m_firstPoint.im = (Ipp16s)(128*tOutput[i].m_firstPoint.im);

        for( j = 6*i; j < 6*i+3; j++ )
        {
            samples[j] = tOutput[i].m_firstPoint.re * Cos[j] - tOutput[i].m_firstPoint.im * Sin[j];
        }

        tOutput[i].m_secondPoint.re = (Ipp16s)(128*tOutput[i].m_secondPoint.re);
        tOutput[i].m_secondPoint.im = (Ipp16s)(128*tOutput[i].m_secondPoint.im);

        for( j = 6*i+3; j < 6*i+6; j++ )
        {
            samples[j] = tOutput[i].m_secondPoint.re * Cos[j] - tOutput[i].m_secondPoint.im * Sin[j];
        }
    }

    ippsFree( Cos );
    ippsFree( Sin );

/* ---------------------- Compute output signal power ---------------------- */
    st = ippsNorm_L2_32f( samples, sLen, &sMagn );
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsNorm_L2_32f: %s\n", ippGetStatusString(st));
       return 1;
    }
    ippsFree( samples );

/* ------------------- Compute noise standard deviation -------------------- */
    stDev = (Ipp16s)( sMagn/sqrt(sLen*pow(10.0, SNR/10.0)) );

/* ------------------- Generate white gaussian noise ----------------------- */
    gns = ippsMalloc_16s( sLen );
   
    st = ippsRandGauss_Direct_16s( gns, sLen, 0, stDev, &gnsSeed );
    if(ippStsNoErr != st)
    {
       printf(" Error in ippsRandGauss_Direct_16s: %s\n", ippGetStatusString(st));
       return 1;
    }
/* ---------------- Add noise to Viterbi decoder input --------------------- */
    for( i = 0; i < len; i++ )
    {
        vInput[i].m_firstPoint.re  = (Ipp16s)(tOutput[i].m_firstPoint.re + gns[4*i]);
        vInput[i].m_firstPoint.im  = (Ipp16s)(tOutput[i].m_firstPoint.im + gns[4*i+1]);
        vInput[i].m_secondPoint.re = (Ipp16s)(tOutput[i].m_secondPoint.re + gns[4*i+2]);
        vInput[i].m_secondPoint.im = (Ipp16s)(tOutput[i].m_secondPoint.im + gns[4*i+3]);
    }

    ippsFree( gns );

    return 0;
} // AddChannelNoise()


int CheckViterbiOut( const Real4DSymbl     *tOutput,
                     const Real4DSymbl     *vInput,
                     int                   len,
                     const ViterbiTestInfo *vInf,
                     long                  *failCount)
{
    int         i;
    Ipp16sc     inputPoint[2];          /* 4D Viterbi decoder input point   */
    Ipp16sc     outputPoint[2];         /* 4D Viterbi decoder output point  */
    ViterbiInfo viterbiParam;
   
    viterbiParam.m_State = vInf->vState;

/* ------------------------ Initialise Viterbi decoder --------------------- */
    InitViterbiDecoder( &viterbiParam);

/* --------------------------- Run Viterbi decoder ------------------------- */
    for( i = 0; i < len; i++ )
    {
        inputPoint[0].re = vInput[i].m_firstPoint.re;
        inputPoint[0].im = vInput[i].m_firstPoint.im;
        inputPoint[1].re = vInput[i].m_secondPoint.re;
        inputPoint[1].im = vInput[i].m_secondPoint.im;
        
        if(GetViterbiData( inputPoint, outputPoint, &viterbiParam))
        {
            return 1;
        }

        if( i >= viterbiParam.m_State )
        {
/* -------------------------- Check Viterbi output ------------------------- */
            if( outputPoint[0].re != tOutput[i-viterbiParam.m_State].m_firstPoint.re  ||
                outputPoint[0].im != tOutput[i-viterbiParam.m_State].m_firstPoint.im  ||
                outputPoint[1].re != tOutput[i-viterbiParam.m_State].m_secondPoint.re ||
                outputPoint[1].im != tOutput[i-viterbiParam.m_State].m_secondPoint.im   )
            {   
                (*failCount)++;
            }
        }
    }

    return 0;
} // CheckViterbiOut()

⌨️ 快捷键说明

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