示例#1
0
/*
------------------------------------------------------------------------------
 FUNCTION NAME: ec_gain_pitch
------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

 Inputs:
  st = pointer to a pointer to a structure containing code
       state data of stucture type ec_gain_pitchState
  state = state of the state machine of type Word16
  pOverflow = pointer to overflow indicator of type Flag

  Outputs:
  state = pointer to a pointer to a structure containing code
          state data of stucture type ec_gain_pitchState
  gain_pitch = pointer to pitch gain (Q14) of type Word16
  pOverflow = 1 if there is an overflow else it is zero.

 Returns:
    None.

 Global Variables Used:
    None.

 Local Variables Needed:
    None.

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

 This function conceals the error using code gain implementation in this
 function.

------------------------------------------------------------------------------
 REQUIREMENTS

 None.

------------------------------------------------------------------------------
 REFERENCES

 ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001

------------------------------------------------------------------------------
 PSEUDO-CODE


    static const Word16 pdown[7] =
    {
        32767, 32112, 32112, 26214,
        9830, 6553, 6553
    };

    Word16 tmp;

    // calculate median of last five gains
    tmp = gmed_n (st->pbuf, 5);

    // new gain = minimum(median, past_gain) * pdown[state]
    if (sub (tmp, st->past_gain_pit) > 0)
    {
        tmp = st->past_gain_pit;
    }
    *gain_pitch = mult (tmp, pdown[state]);


------------------------------------------------------------------------------
 CAUTION [optional]
 [State any special notes, constraints or cautions for users of this function]

------------------------------------------------------------------------------
*/
void ec_gain_pitch(
    ec_gain_pitchState *st, /* i/o : state variables                   */
    Word16 state,           /* i   : state of the state machine        */
    Word16 *gain_pitch,     /* o   : pitch gain (Q14)                  */
    Flag   *pOverflow
)
{
    static const Word16 pdown[7] =
    {
        32767, 32112, 32112, 26214,
        9830, 6553, 6553
    };

    Word16 tmp;

    /* calculate median of last five gains */
    tmp = gmed_n(st->pbuf, 5);

    /* new gain = minimum(median, past_gain) * pdown[state] */
    if (sub(tmp, st->past_gain_pit, pOverflow) > 0)
    {
        tmp = st->past_gain_pit;
    }
    *gain_pitch = mult(tmp, pdown[state], pOverflow);
}
示例#2
0
/*
------------------------------------------------------------------------------
 FUNCTION NAME: ec_gain_code
------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

 Inputs:
  st = pointer to a pointer to a structure containing code state data of
       stucture type ec_gain_codeState
  pred_state = pointer to MA predictor state of type gc_predState
  state  = state of the state machine of type Word16
  gain_code = pointer to decoded innovation gain of type Word16
  pOverflow = pointer to overflow indicator of type Flag

 Outputs:
  st = pointer to a pointer to a structure containing code state data of
       stucture type ec_gain_codeState
  pred_state = pointer to MA predictor state of type gc_predState
  pOverflow = 1 if there is an overflow else it is zero.

 Returns:
    None.

 Global Variables Used:
    None.

 Local Variables Needed:
    None.

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

This function does error concealment using the codebook. Call this function
only in BFI (instead of normal gain decoding function).

------------------------------------------------------------------------------
 REQUIREMENTS

 None.

------------------------------------------------------------------------------
 REFERENCES

 ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001

------------------------------------------------------------------------------
 PSEUDO-CODE

    static const Word16 cdown[7] =
    {
        32767, 32112, 32112, 32112,
        32112, 32112, 22937
    };

    Word16 tmp;
    Word16 qua_ener_MR122;
    Word16 qua_ener;

    // calculate median of last five gain values
    tmp = gmed_n (st->gbuf,5);

    // new gain = minimum(median, past_gain) * cdown[state]
    if (sub (tmp, st->past_gain_code) > 0)
    {
        tmp = st->past_gain_code;
    }
    tmp = mult (tmp, cdown[state]);
    *gain_code = tmp;

    // update table of past quantized energies with average of
    // current values

    gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener);
    gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
}

------------------------------------------------------------------------------
 CAUTION [optional]
 [State any special notes, constraints or cautions for users of this function]

------------------------------------------------------------------------------
*/
void ec_gain_code(
    ec_gain_codeState *st,    /* i/o : State struct                     */
    gc_predState *pred_state, /* i/o : MA predictor state               */
    Word16 state,             /* i   : state of the state machine       */
    Word16 *gain_code,        /* o   : decoded innovation gain          */
    Flag   *pOverflow
)
{
    static const Word16 cdown[7] =
    {
        32767, 32112, 32112, 32112,
        32112, 32112, 22937
    };

    Word16 tmp;
    Word16 qua_ener_MR122;
    Word16 qua_ener;

    /* calculate median of last five gain values */
    tmp = gmed_n(st->gbuf, 5);

    /* new gain = minimum(median, past_gain) * cdown[state] */
    if (sub(tmp, st->past_gain_code, pOverflow) > 0)
    {
        tmp = st->past_gain_code;
    }
    tmp = mult(tmp, cdown[state], pOverflow);
    *gain_code = tmp;

    /* update table of past quantized energies with average of
     * current values
     */
    gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener, pOverflow);
    gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
}
示例#3
0
/*************************************************************************
 *
 *  Function:   gain_adapt()
 *  Purpose:    calculate pitch/codebook gain adaptation factor alpha
 *              (and update the adaptor state)
 *
 **************************************************************************
 */
void gain_adapt(
    GainAdaptState *st,  /* i  : state struct                  */
    Word16 ltpg,         /* i  : ltp coding gain (log2()), Q13 */
    Word16 gain_cod,     /* i  : code gain,                Q1  */
    Word16 *alpha        /* o  : gain adaptation factor,   Q15 */
)
{
    Word16 adapt;      /* adaptdation status; 0, 1, or 2       */
    Word16 result;     /* alpha factor, Q13                    */
    Word16 filt;       /* median-filtered LTP coding gain, Q13 */
    Word16 tmp, i;
    
    /* basic adaptation */
    
    if (sub (ltpg, LTP_GAIN_THR1) <= 0)
    {
        adapt = 0;                            
    }
    else
    {
        
        if (sub (ltpg, LTP_GAIN_THR2) <= 0)
        {
            adapt = 1;                        
        }
        else
        {
            adapt = 2;                        
        }
    }

    /*
     * // onset indicator
     * if ((cbGain > onFact * cbGainMem[0]) && (cbGain > 100.0))
     *     onset = 8;
     * else
     *     if (onset)
     *         onset--;
     */
    /* tmp = cbGain / onFact; onFact = 2.0; 200 Q1 = 100.0 */
    tmp = shr_r (gain_cod, 1);
     
    if ((sub (tmp, st->prev_gc) > 0) && sub(gain_cod, 200) > 0)
    {
        st->onset = 8;                            
    }
    else
    {
        
        if (st->onset != 0)
        {
            st->onset = sub (st->onset, 1);       
        }
    }

    /*
     *  // if onset, increase adaptor state
     *  if (onset && (gainAdapt < 2)) gainAdapt++;
     */
     
    if ((st->onset != 0) && (sub (adapt, 2) < 0))
    {
        adapt = add (adapt, 1);
    }

    st->ltpg_mem[0] = ltpg;                       
    filt = gmed_n (st->ltpg_mem, 5);    /* function result */

    
    if (adapt == 0)
    {
        
        if (sub (filt, 5443) > 0) /* 5443 Q13 = 0.66443... */
        {
            result = 0; 
        }
        else
        {
            
            if (filt < 0)
            {
                result = 16384;   /* 16384 Q15 = 0.5 */
            }
            else
            {   /* result       =   0.5 - 0.75257499*filt     */
                /* result (Q15) = 16384 - 24660 * (filt << 2) */
                filt = shl (filt, 2); /* Q15 */
                result = sub (16384, mult (24660, filt));
            }
        }
    }
    else
    {
        result = 0; 
    }
    /*
     *  if (prevAlpha == 0.0) result = 0.5 * (result + prevAlpha);
     */
    
    if (st->prev_alpha == 0)
    {
        result = shr (result, 1);
    }

    /* store the result */
    *alpha = result;                           
    
    /* update adapter state memory */
    st->prev_alpha = result;                   
    st->prev_gc = gain_cod;                    

    for (i = LTPG_MEM_SIZE-1; i > 0; i--)
    {
        st->ltpg_mem[i] = st->ltpg_mem[i-1];   
    }
    /* mem[0] is just present for convenience in calling the gmed_n[5]
     * function above. The memory depth is really LTPG_MEM_SIZE-1.
     */
}
示例#4
0
/*
**************************************************************************
*
*  Function    : Bgn_scd
*  Purpose     : Charaterice synthesis speech and detect background noise
*  Returns     : background noise decision; 0 = no bgn, 1 = bgn
*
**************************************************************************
*/
Word16 Bgn_scd (Bgn_scdState *st,      /* i : State variables for bgn SCD */
                Word16 ltpGainHist[],  /* i : LTP gain history            */
                Word16 speech[],       /* o : synthesis speech frame      */
                Word16 *voicedHangover /* o : # of frames after last 
                                              voiced frame                */
                )
{
   Word16 i;
   Word16 prevVoiced, inbgNoise;
   Word16 temp;
   Word16 ltpLimit, frameEnergyMin;
   Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
   Word32 s;
   
   /* Update the inBackgroundNoise flag (valid for use in next frame if BFI) */
   /* it now works as a energy detector floating on top                      */ 
   /* not as good as a VAD.                                                  */

   currEnergy = 0;                                   move16 ();
   s = (Word32) 0;                                   move32 ();

   for (i = 0; i < L_FRAME; i++)
   {
       s = L_mac (s, speech[i], speech[i]);
   }

   s = L_shl(s, 2);  

   currEnergy = extract_h (s);

   frameEnergyMin = 32767;                     move16 ();

   for (i = 0; i < L_ENERGYHIST; i++)
   {
      test ();
      if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0)
         frameEnergyMin = st->frameEnergyHist[i];           move16 ();
   }

   noiseFloor = shl (frameEnergyMin, 4); /* Frame Energy Margin of 16 */

   maxEnergy = st->frameEnergyHist[0];               move16 ();
   for (i = 1; i < L_ENERGYHIST-4; i++)
   {
      test ();
      if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0)
      {
         maxEnergy = st->frameEnergyHist[i];         move16 ();
      }
   }
   
   maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3]; move16 ();
   for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++)
   {
      test ();
      if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0)
      {
         maxEnergyLastPart = st->frameEnergyHist[i]; move16 ();     
      }
   }

   inbgNoise = 0;        /* false */                 move16 (); 

   /* Do not consider silence as noise */
   /* Do not consider continuous high volume as noise */
   /* Or if the current noise level is very low */
   /* Mark as noise if under current noise limit */
   /* OR if the maximum energy is below the upper limit */

   test (); test (); test (); test (); test (); 
   if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) &&
        (sub(currEnergy, FRAMEENERGYLIMIT) < 0) &&
        (sub(currEnergy, LOWERNOISELIMIT) > 0) &&
        ( (sub(currEnergy, noiseFloor) < 0) ||
          (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0)))
   {
      test ();
      if (sub(add(st->bgHangover, 1), 30) > 0)
      {
         st->bgHangover = 30;                         move16 ();
      } else
      {
         st->bgHangover = add(st->bgHangover, 1);
      }
   }
   else
   {
      st->bgHangover = 0;                             move16 ();    
   }
   
   /* make final decision about frame state , act somewhat cautiosly */
   test ();
   if (sub(st->bgHangover,1) > 0)
      inbgNoise = 1;       /* true  */               move16 ();  

   for (i = 0; i < L_ENERGYHIST-1; i++)
   {
      st->frameEnergyHist[i] = st->frameEnergyHist[i+1]; move16 ();
   }
   st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;              move16 ();
   
   /* prepare for voicing decision; tighten the threshold after some 
      time in noise */
   ltpLimit = 13926;             /* 0.85  Q14 */     move16 (); 
   test ();
   if (sub(st->bgHangover, 8) > 0)
   {
      ltpLimit = 15565;          /* 0.95  Q14 */     move16 ();
   }
   test ();
   if (sub(st->bgHangover, 15) > 0)
   {
      ltpLimit = 16383;          /* 1.00  Q14 */     move16 ();
   }

   /* weak sort of voicing indication. */
   prevVoiced = 0;        /* false */                move16 ();
   test ();

   if (sub(gmed_n(&ltpGainHist[4], 5), ltpLimit) > 0)
   {
      prevVoiced = 1;     /* true  */                move16 ();
   }
   test ();   
   if (sub(st->bgHangover, 20) > 0) {
      if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0)
      {
         prevVoiced = 1;  /* true  */                move16 ();
      }
      else
      {
         prevVoiced = 0;  /* false  */                move16 ();
      }
   }
   
   test ();
   if (prevVoiced)
   {
      *voicedHangover = 0;                        move16 ();
   }
   else
   {
      temp = add(*voicedHangover, 1);
      test ();
      if (sub(temp, 10) > 0)
      {
         *voicedHangover = 10;                    move16 ();
      }
      else
      {
         *voicedHangover = temp;                  move16 ();
      }
   }

   return inbgNoise;
}
Word16 Pitch_ol_wgh(      /* o   : open loop pitch lag                            */
    pitchOLWghtState *st, /* i/o : State struct                                   */
    vadState *vadSt,      /* i/o : VAD state struct                               */
    Word16 signal[],      /* i   : signal used to compute the open loop pitch     */
    /*       signal[-pit_max] to signal[-1] should be known */
    Word16 pit_min,       /* i   : minimum pitch lag                              */
    Word16 pit_max,       /* i   : maximum pitch lag                              */
    Word16 L_frame,       /* i   : length of frame to compute pitch               */
    Word16 old_lags[],    /* i   : history with old stored Cl lags                */
    Word16 ol_gain_flg[], /* i   : OL gain flag                                   */
    Word16 idx,           /* i   : index                                          */
    Flag dtx,             /* i   : dtx flag; use dtx=1, do not use dtx=0          */
    Flag   *pOverflow     /* o   : overflow flag                                  */
)
{
    Word16 i;
    Word16 max1;
    Word16 p_max1;
    Word32 t0;
#ifndef VAD2
    Word16 corr_hp_max;
#endif
    Word32 corr[PIT_MAX+1], *corr_ptr;

    /* Scaled signal */
    Word16 scaled_signal[PIT_MAX + L_FRAME];
    Word16 *scal_sig;

    scal_sig = &scaled_signal[pit_max];

    t0 = 0L;
    for (i = -pit_max; i < L_frame; i++)
    {
        t0 = L_mac(t0, signal[i], signal[i], pOverflow);
    }
    /*--------------------------------------------------------*
     * Scaling of input signal.                               *
     *                                                        *
     *   if Overflow        -> scal_sig[i] = signal[i]>>2     *
     *   else if t0 < 1^22  -> scal_sig[i] = signal[i]<<2     *
     *   else               -> scal_sig[i] = signal[i]        *
     *--------------------------------------------------------*/

    /*--------------------------------------------------------*
     *  Verification for risk of overflow.                    *
     *--------------------------------------------------------*/

    /* Test for overflow */
    if (L_sub(t0, MAX_32, pOverflow) == 0L)
    {
        for (i = -pit_max; i < L_frame; i++)
        {
            scal_sig[i] = shr(signal[i], 3, pOverflow);
        }
    }
    else if (L_sub(t0, (Word32) 1048576L, pOverflow) < (Word32) 0)
    {
        for (i = -pit_max; i < L_frame; i++)
        {
            scal_sig[i] = shl(signal[i], 3, pOverflow);
        }
    }
    else
    {
        for (i = -pit_max; i < L_frame; i++)
        {
            scal_sig[i] = signal[i];
        }
    }

    /* calculate all coreelations of scal_sig, from pit_min to pit_max */
    corr_ptr = &corr[pit_max];
    comp_corr(scal_sig, L_frame, pit_max, pit_min, corr_ptr);

    p_max1 = Lag_max(vadSt, corr_ptr, scal_sig, L_frame, pit_max, pit_min,
                     st->old_T0_med, &max1, st->wght_flg, &ol_gain_flg[idx],
                     dtx, pOverflow);

    if (ol_gain_flg[idx] > 0)
    {
        /* Calculate 5-point median of previous lags */
        for (i = 4; i > 0; i--) /* Shift buffer */
        {
            old_lags[i] = old_lags[i-1];
        }
        old_lags[0] = p_max1;
        st->old_T0_med = gmed_n(old_lags, 5);
        st->ada_w = 32767; /* Q15 = 1.0 */
    }
    else
    {
        st->old_T0_med = p_max1;
        /* = ada_w = ada_w * 0.9 */
        st->ada_w = mult(st->ada_w, 29491, pOverflow);
    }

    if (sub(st->ada_w, 9830, pOverflow) < 0)  /* ada_w - 0.3 */
    {
        st->wght_flg = 0;
    }
    else
    {
        st->wght_flg = 1;
    }

#ifndef VAD2
    if (dtx)
    {   /* no test() call since this if is only in simulation env */
        if (sub(idx, 1, pOverflow) == 0)
        {
            /* calculate max high-passed filtered correlation of all lags */
            hp_max(corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max, pOverflow);

            /* update complex background detector */
            vad_complex_detection_update(vadSt, corr_hp_max);
        }
    }
#endif

    return (p_max1);
}
示例#6
0
//=============================================================================
//函数名称:Bgn_scd
//函数功能: 合成语音和检测背景噪音   
//函数返回:背景噪声的决定;"0"表示BGN,"1"表示无BGN
//============================================================================= 
Word16  Bgn_scd(Bgn_scdState *st,       /* i : State variables for bgn SCD  */
                Word16 ltpGainHist[],  /* i : LTP gain history             */
                Word16 speech[],       /* o : synthesis speech frame       */
                Word16 *voicedHangover,/* o : # of frames after last
                                               voiced frame                 */
                Flag   *pOverflow
               )
{
    Word16  i;
    Word16  prevVoiced, inbgNoise;
    Word16  temp;
    Word16  ltpLimit, frameEnergyMin;
    Word16  currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
    Word32  s, L_temp;


    /* Update the inBackgroundNoise flag (valid for use in next frame if BFI)   */
    /* it now works as a energy detector floating on top                        */
    /* not as good as a VAD.                                                    */

    s = (Word32) 0;

    for (i = L_FRAME - 1; i >= 0; i--)
    {
        L_temp = ((Word32) speech[i]) * speech[i];
        if (L_temp != (Word32) 0x40000000L)
        {
            L_temp = L_temp << 1;
        }
        else
        {
            L_temp = MAX_32;
        }
        s = L_add(s, L_temp, pOverflow);
    }

    /* s is a sum of squares, so don't need to check for neg overflow */
	//s是平方和,所以不需要检查负溢出
    if (s > (Word32)0x1fffffffL)
    {
        currEnergy = MAX_16;
    }
    else
    {
        currEnergy = (Word16)(s >> 14);
    }

    frameEnergyMin = 32767;
    for (i = L_ENERGYHIST - 1; i >= 0; i--)
    {
        if (st->frameEnergyHist[i] < frameEnergyMin)
        {
            frameEnergyMin = st->frameEnergyHist[i];
        }
    }

    /* Frame Energy Margin of 16 */
	//16帧的能量裕度
    L_temp = (Word32)frameEnergyMin << 4;
    if (L_temp != (Word32)((Word16) L_temp))
    {
        if (L_temp > 0)
        {
            noiseFloor = MAX_16;
        }
        else
        {
            noiseFloor = MIN_16;
        }
    }
    else
    {
        noiseFloor = (Word16)(L_temp);
    }

    maxEnergy = st->frameEnergyHist[0];
    for (i = L_ENERGYHIST - 5; i >= 1; i--)
    {
        if (maxEnergy < st->frameEnergyHist[i])
        {
            maxEnergy = st->frameEnergyHist[i];
        }
    }

    maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
    for (i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++)
    {
        if (maxEnergyLastPart < st->frameEnergyHist[i])
        {
            maxEnergyLastPart = st->frameEnergyHist[i];
        }
    }

    /* Do not consider silence as noise */
    /* Do not consider continuous high volume as noise */
    /* Or if the current noise level is very low */
    /* Mark as noise if under current noise limit */
    /* OR if the maximum energy is below the upper limit */

    if ((maxEnergy > LOWERNOISELIMIT) &&
            (currEnergy < FRAMEENERGYLIMIT) &&
            (currEnergy > LOWERNOISELIMIT) &&
            ((currEnergy < noiseFloor) ||
             (maxEnergyLastPart < UPPERNOISELIMIT)))
    {
        if ((st->bgHangover + 1) > 30)
        {
            st->bgHangover = 30;
        }
        else
        {
            st->bgHangover += 1;
        }
    }
    else
    {
        st->bgHangover = 0;
    }

    /* make final decision about frame state , act somewhat cautiosly */
	//作出关于帧状态最终决定,行动有些谨慎

    if (st->bgHangover > 1)
    {
        inbgNoise = TRUE;
    }
    else
    {
        inbgNoise = FALSE;
    }

    for (i = 0; i < L_ENERGYHIST - 1; i++)
    {
        st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
    }
    st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;

    /* prepare for voicing decision; tighten the threshold after some
       time in noise */
    //对于清浊决定做准备;后噪声一段时间收紧门槛

    if (st->bgHangover > 15)
    {
        ltpLimit = 16383;       /* 1.00  Q14 */
    }
    else if (st->bgHangover > 8)
    {
        ltpLimit = 15565;       /* 0.95  Q14 */
    }
    else
    {
        ltpLimit = 13926;       /* 0.85  Q14 */
    }

    /* weak sort of voicing indication. */
	//弱排序清浊指示
    prevVoiced = FALSE;

    if (gmed_n(&ltpGainHist[4], 5) > ltpLimit)
    {
        prevVoiced = TRUE;
    }

    if (st->bgHangover > 20)
    {
        if (gmed_n(ltpGainHist, 9) > ltpLimit)
        {
            prevVoiced = TRUE;
        }
        else
        {
            prevVoiced = FALSE;
        }
    }


    if (prevVoiced)
    {
        *voicedHangover = 0;
    }
    else
    {
        temp = *voicedHangover + 1;

        if (temp > 10)
        {
            *voicedHangover = 10;
        }
        else
        {
            *voicedHangover = temp;
        }
    }

    return(inbgNoise);
}