⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vad1.c

📁 AMR-NB 的编码实现,纯C, VC下建立工程即可用.
💻 C
📖 第 1 页 / 共 3 页
字号:
 * *     Function    : complex_estimate_adapt *     Purpose    : Update/adapt of complex signal estimate *     Inputs       :  low_power:   low signal power flag  *     Outputs    : st->corr_hp_fast:   long term complex signal estimate * ***************************************************************************/static void complex_estimate_adapt(vadState1 *st,  Word16 low_power )
{
   Word16 alpha;             /* Q15 */   Word32 L_tmp;            /* Q31 */   /* adapt speed on own state */
   if ( st->best_corr_hp < st->corr_hp_fast ) /* decrease */   {	alpha = st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_REALLY_FAST;	   }   else  /* increase */    {	alpha = st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_SLOW;   }   L_tmp = (st->corr_hp_fast  <<16 );   L_tmp = L_tmp - (alpha*st->corr_hp_fast<<1 );   L_tmp +=  alpha*st->best_corr_hp <<1;     st->corr_hp_fast = (Word16)(( L_tmp > 0 ) && (L_tmp + 0x00008000L)<0 ? 0x7ffff:  (L_tmp + 0x00008000L)>>16);       /* Q15 */       st->corr_hp_fast = st->corr_hp_fast <CVAD_MIN_CORR ? CVAD_MIN_CORR : st->corr_hp_fast ;   st->corr_hp_fast = low_power != 0 ? CVAD_MIN_CORR :st->corr_hp_fast ; 
}
/**************************************************************************** * *     Function     : vad_decision *     Purpose      : Calculates VAD_flag *     Inputs       : bckr_est:    background noise estimate *                         vadreg:      intermediate VAD flags
 *     Outputs      : noise_level: average level of the noise estimates *                           vadreg:      intermediate VAD flags
 *     Return value : VAD_flag * ***************************************************************************/static Word16 vad_decision( vadState1 *st,    Word16 level[COMPLEN], Word32 pow_sum   )
{
   Word16 i;   Word16 snr_sum, alpha;   Word32 L_temp,L_temp1;
   Word16 vad_thr, temp, noise_level;   Word16 low_power_flag;   Word16 hang_len, burst_len;

   vadState1 *pst = st;
   Word16*plevel = level;
	
   	/* 
	Calculate squared sum of the input levels (level)
	divided by the background noise components (bckr_est).
	*/
	L_temp = 0;                                 
	for (i = 0; i < COMPLEN; i++)
	{
		Word16 exp;
		exp = norm_s(pst->bckr_est[i]);
		temp =  (pst->bckr_est[i]<<exp);
		temp = div_s((plevel[i]>> 1), temp);
		temp  = exp>5? temp<<(exp-5): temp>> (5-exp);
		L_temp += temp*temp <<1;
		if(L_temp < 0)
		{
			L_temp = MAX_32;
			break;
		}
	}

	L_temp = L_temp > 0x01ffffff ? MAX_32 : L_temp << 6;  
	snr_sum = (Word16)(L_temp >> 16);
	snr_sum = (snr_sum* INV_COMPLEN)>>15;

	L_temp1 = pst->bckr_est[0] + pst->bckr_est[1] + pst->bckr_est[2] + pst->bckr_est[3]+ pst->bckr_est[4];
	L_temp = pst->bckr_est[5] + pst->bckr_est[6] + pst->bckr_est[7] + pst->bckr_est[8];
	L_temp += L_temp1;
	L_temp = L_temp > 0x0003ffff ? MAX_32 : L_temp << 13;
	noise_level =(Word16)( L_temp >> 16);

	/* Calculate VAD threshold */

	vad_thr = (VAD_SLOPE * (noise_level-VAD_P1)>>15) + VAD_THR_HIGH;
	vad_thr = (vad_thr < VAD_THR_LOW) ? VAD_THR_LOW : vad_thr;

	/* Shift VAD decision register */
	pst->vadreg >>= 1;  

	/* Make intermediate VAD decision */
	pst->vadreg =  (snr_sum > vad_thr ) ? pst->vadreg | 0x4000:  pst->vadreg ;     

	/* primary vad decsion made */
	/* check if the input power (pow_sum) is lower than a threshold" */
	low_power_flag =  (pow_sum<VAD_POW_LOW ) ? 1 : 0;        


   /* update complex signal estimate st->corr_hp_fast and hangover reset timer using */   /* low_power_flag and corr_hp_fast  and various adaptation speeds                 */   //complex_estimate_adapt(st, low_power_flag);   /* adapt speed on own state */   if ( pst->best_corr_hp < pst->corr_hp_fast ) /* decrease */
   {	alpha = pst->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_REALLY_FAST;	
   }   else  /* increase */    {	alpha = pst->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_SLOW;
   }   L_temp = (pst->corr_hp_fast  <<16 );
   L_temp = L_temp - (alpha*pst->corr_hp_fast<<1 );
   L_temp +=  alpha*pst->best_corr_hp <<1;  
   pst->corr_hp_fast = (Word16)(( L_temp > 0 ) && (L_temp + 0x00008000L)<0 ? 0x7ffff:  (L_temp + 0x00008000L)>>16);       /* Q15 */    
   pst->corr_hp_fast = pst->corr_hp_fast <CVAD_MIN_CORR ? CVAD_MIN_CORR : pst->corr_hp_fast ;
   pst->corr_hp_fast = low_power_flag != 0 ? CVAD_MIN_CORR :st->corr_hp_fast ;
      /* check multiple thresholds of the st->corr_hp_fast value */    //   st->complex_warning = complex_vad(st, low_power_flag); 	pst->complex_high >>= 1;                   
	pst->complex_low  >>= 1;                      
	pst->complex_high = (low_power_flag == 0)&&(pst->corr_hp_fast > CVAD_THRESH_ADAPT_HIGH) ? pst->complex_high | 0x4000 : pst->complex_high ;  
	pst->complex_low  = (low_power_flag == 0)&&(pst->corr_hp_fast > CVAD_THRESH_ADAPT_LOW)  ? pst->complex_low | 0x4000 : pst->complex_low ;  
	pst->complex_hang_timer = pst->corr_hp_fast > CVAD_THRESH_HANG ? pst->complex_hang_timer + 1 :0;
	pst->complex_warning = ( ((pst->complex_high & 0x7f80) ==0x7f80) ||((pst->complex_low & 0x7fff) ==0x7fff) );
     /* Update speech subband vad background noise estimates */      noise_estimate_update(pst, plevel);
        /*  Add speech and complex hangover and return speech VAD_flag */   /*  long term complex hangover may be added */  // st->speech_vad_decision = hangover_addition(st, noise_level, low_power_flag);
   pst->speech_vad_decision = 0;
      burst_len = (noise_level >  HANG_NOISE_THR) ? BURST_LEN_HIGH_NOISE :BURST_LEN_LOW_NOISE;   hang_len = (noise_level >  HANG_NOISE_THR) ? HANG_LEN_HIGH_NOISE :HANG_LEN_LOW_NOISE;     /* if the input power (pow_sum) is lower than a threshold, clear      counters and set VAD_flag to "0"  "fast exit"                 */   if (low_power_flag != 0)   {      pst->burst_count = 0;                                     
      pst->hang_count = 0;                                      
      pst->complex_hang_count = 0;                             
      pst->complex_hang_timer = 0;    
	        pst->speech_vad_decision = 0;
   }       pst->complex_hang_count = (pst->complex_hang_timer >CVAD_HANG_LIMIT) &&( pst->complex_hang_count < CVAD_HANG_LENGTH) ? CVAD_HANG_LENGTH :  st->complex_hang_count ;
    /* long time very complex signal override VAD output function */   if (pst->complex_hang_count != 0)
   {      pst->burst_count = BURST_LEN_HIGH_NOISE;                   
      pst->complex_hang_count --;   
	         pst->speech_vad_decision = 1; 
   }   else   {      /* let hp_corr work in from a noise_period indicated by the VAD */      if (((pst->vadreg & 0x3ff0) == 0) && (pst->corr_hp_fast > CVAD_THRESH_IN_NOISE) )
      {          pst->speech_vad_decision = 1;
      }     }   /* update the counters (hang_count, burst_count) */   if ((pst->vadreg & 0x4000) != 0)
   {       pst->burst_count ++;               
	pst->hang_count = pst->burst_count >=  burst_len? hang_len : pst->hang_count;
       pst->speech_vad_decision = 1;
   }   else   {       pst->burst_count = 0;    
	pst->speech_vad_decision = pst->hang_count > 0 ? 1 :st->speech_vad_decision ;
	pst->hang_count   = pst->hang_count > 0 ? pst->hang_count -1 : pst->hang_count;
   }      return (pst->speech_vad_decision);

}
int vad1_init (vadState1 **state){
	vadState1* pvadState1;

	if (state == (vadState1 **) NULL)
	{
		fprintf(stderr, "vad_init: invalid parameter\n");
		return -1;
	}
	*state = NULL;

	/* allocate memory */
	if ((pvadState1 = (vadState1 *) malloc(sizeof(vadState1))) == NULL)
	{
		fprintf(stderr, "vad_init: can not malloc state structure\n");
		return -1;
	}
    	//vad1_reset(pvadState1);
	/* Initialize pitch detection variables */
	pvadState1->oldlag_count = 0;
	pvadState1->oldlag = 0;         
	pvadState1->pitch = 0;
	pvadState1->tone = 0;            

	pvadState1->complex_high = 0;            
	pvadState1->complex_low = 0;            
	pvadState1->complex_hang_timer = 0;

	pvadState1->vadreg = 0;         

	pvadState1->stat_count = 0;    
	pvadState1->burst_count = 0;    
	pvadState1->hang_count = 0;     
	pvadState1->complex_hang_count = 0;     


   /* initialize memory used by the filter bank */	memset(&pvadState1->a_data5[0][0], 0, 6*sizeof(Word16));
	memset(&pvadState1->a_data3[0], 0, 5*sizeof(Word16));
	memset(&pvadState1->bckr_est[0], NOISE_INIT, COMPLEN*sizeof(Word16));   
	memset(&pvadState1->old_level[0], NOISE_INIT, COMPLEN*sizeof(Word16));
	memset(&pvadState1->old_level[0], NOISE_INIT, COMPLEN*sizeof(Word16));  
	memset(&pvadState1->sub_level[0], 0, COMPLEN*sizeof(Word16));          

	pvadState1->best_corr_hp = CVAD_LOWPOW_RESET; 
	pvadState1->speech_vad_decision = 0;
	pvadState1->complex_warning = 0;
	pvadState1->sp_burst_count = 0;        
	pvadState1->corr_hp_fast = CVAD_LOWPOW_RESET;
	*state = pvadState1;
    return 0;}
 
void vad1_exit (vadState1 **state){    if (state == NULL || *state == NULL)        return;        /* deallocate memory */    free(*state);    *state = NULL;        return;}
/****************************************************************************
      Function     : vad1
      Purpose      : Main program for Voice Activity Detection (VAD) for AMR 
      Return value : VAD Decision, 1 = speech, 0 = noise
      Input:
                    st            : State struct   
                    in_buf[] : samples of the input frame   
                    
      Output :
                    st : State struct     
 ***************************************************************************/
Word16 vad1(vadState1 *st, Word16 in_buf[]  )
{
   Word16 level[COMPLEN];   Word32 pow_sum, sum1;   Word16 i,temp1, temp2, temp3,temp4;   Word16* pInBuf;   pInBuf = in_buf;      /* Calculate power of the input frame. */   pow_sum = 0L;                  for (i = 0; i < FRAME_LEN; i+=4 )   {  		temp1 = pInBuf[i-LOOKAHEAD];		temp2 = pInBuf[i-LOOKAHEAD+1];		temp3 = pInBuf[i-LOOKAHEAD+2];		temp4 = pInBuf[i-LOOKAHEAD+3];		sum1 = temp1*temp1 + temp2*temp2 + temp3*temp3 + temp4*temp4;				pow_sum += sum1 <<1 ; 				if (pow_sum < 0)		{			pow_sum = MAX_32;			break;		}    }        /*     If input power is very low, clear pitch flag of the current frame     */   st->pitch = pow_sum < POW_PITCH_THR ? st->pitch & 0x3fff : st->pitch ;            /*     If input power is very low, clear complex flag of the "current" frame     */   st->complex_low = pow_sum < POW_COMPLEX_THR ? st->complex_low & 0x3fff : st->complex_low ;        /*     Run the filter bank which calculates signal levels at each band     */   filter_bank(st, in_buf, level);      return (vad_decision(st, level, pow_sum));  
}


⌨️ 快捷键说明

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