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

📄 wb_vad.c

📁 关于AMR-WB+语音压缩编码的实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
*                         INCLUDE FILES
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include "../include/amr_plus.h"
/******************************************************************************
*                         PRIVATE PROGRAM CODE
******************************************************************************/
/******************************************************************************
*
*     Function     : filter5
*     Purpose      : Fifth-order half-band lowpass/highpass filter pair with
*                    decimation.
*
*******************************************************************************
*/
static void filter5(
  float *in0,    /* i/o : input values; output low-pass part  */
  float *in1,    /* i/o : input values; output high-pass part */
  float data[]   /* i/o : updated filter memory               */
)
{
  float temp0, temp1, temp2;
  temp0 = *in0 - COEFF5_1 * data[0];
  temp1 = data[0] + COEFF5_1 * temp0;
  data[0] = temp0;
  temp0 = *in1 - COEFF5_2 * data[1];
  temp2 = data[1] + COEFF5_2 * temp0;
  data[1] = temp0;
  *in0 = (temp1 + temp2)/2.0f;
  *in1 = (temp1 - temp2)/2.0f;
}
/******************************************************************************
*
*     Function     : filter3
*     Purpose      : Third-order half-band lowpass/highpass filter pair with
*                    decimation.
*
*******************************************************************************
*/
static void filter3(
  float *in0,   /* i/o : input values; output low-pass part  */
  float *in1,   /* i/o : input values; output high-pass part */
  float *data   /* i/o : updated filter memory               */
)
{
  float temp1, temp2;
  temp1 = *in1 - COEFF3 * *data;
  temp2 = *data + COEFF3 * temp1;
  *data = temp1;
  *in1 = (*in0 - temp2)/2.0f;
  *in0 = (*in0 + temp2)/2.0f;
}
/******************************************************************************
*
*     Function   : level_calculation
*     Purpose    : Calculate signal level in a sub-band. Level is calculated
*                  by summing absolute values of the input data.
*
*                  Because speech coder has a lookahead, signal level calculated
*                  over the lookahead (data[count1 - count2]) is stored (*sub_level)
*                  and added to the level of the next frame. Additionally, group
*                  delay and decimation of the filter bank is taken into the count
*                  for the values of the counters (count1, count2).
*
*******************************************************************************
*/
static float level_calculation( /* return: signal level */
  float data[],     /* i   : signal buffer                                    */
  float *sub_level, /* i   : level calculated at the end of the previous frame*/
                     /* o   : level of signal calculated from the last         */
                     /*       (count2 - count1) samples                        */
  Word16 count1,     /* i   : number of samples to be counted                  */
  Word16 count2,     /* i   : number of samples to be counted                  */
  Word16 ind_m,      /* i   : step size for the index of the data buffer       */
  Word16 ind_a,      /* i   : starting index of the data buffer                */
  float scale       /* i   : scaling for the level calculation                */
)
{
  double l_temp1, l_temp2;
  float level;
  Word16 i;
  l_temp1 = 0.0;
  for (i = count1; i < count2; i++)
  {
     l_temp1 += fabs(data[ind_m*i+ind_a]);
  }
  l_temp1 *= 2.0f;
  l_temp2 = l_temp1 + *sub_level/scale;
  *sub_level = (float)(l_temp1*scale);
  for (i = 0; i < count1; i++)
  {
     l_temp2 += 2.0f*fabs(data[ind_m*i+ind_a]);
  }
  level = (float)(l_temp2*scale);
  return level;
}
/******************************************************************************
*
*     Function     : filter_bank
*     Purpose      : Divide input signal into bands and calculate level of
*                    the signal in each band
*
*******************************************************************************
*/
static void filter_bank(
  VadVars *st,   /* i/o : State struct               */
  float in[],   /* i   : input frame                */
  float level[] /* 0   : signal levels at each band */
)
{
  Word16 i;
  float tmp_buf[FRAME_LEN];
  /* shift input 1 bit down for safe scaling */
  for (i = 0; i < FRAME_LEN; i++) {
    tmp_buf[i] = in[i]/2.0f;
  }
  /* run the filter bank */
  for (i = 0;i < FRAME_LEN/2; i++) {
    filter5(&tmp_buf[2*i],&tmp_buf[2*i+1],st->a_data5[0]);
  }
  for (i = 0;i < FRAME_LEN/4; i++) {
    filter5(&tmp_buf[4*i],&tmp_buf[4*i+2],st->a_data5[1]);
    filter5(&tmp_buf[4*i+1],&tmp_buf[4*i+3],st->a_data5[2]);
  }
  for (i = 0; i < FRAME_LEN/8; i++)
  {
     filter5(&tmp_buf[8*i], &tmp_buf[8*i+4], st->a_data5[3]);
     filter5(&tmp_buf[8*i+2], &tmp_buf[8*i+6], st->a_data5[4]);
     filter3(&tmp_buf[8*i+3],&tmp_buf[8*i+7],&st->a_data3[0]);
  }
  for (i = 0; i < FRAME_LEN/16; i++)
  {
     filter3(&tmp_buf[16*i+0], &tmp_buf[16*i+8], &st->a_data3[1]);
     filter3(&tmp_buf[16*i+4], &tmp_buf[16*i+12], &st->a_data3[2]);
     filter3(&tmp_buf[16*i+6], &tmp_buf[16*i+14], &st->a_data3[3]);
  }
  for (i = 0; i < FRAME_LEN/32; i++)
  {
     filter3(&tmp_buf[32*i+0], &tmp_buf[32*i+16], &st->a_data3[4]);
     filter3(&tmp_buf[32*i+8], &tmp_buf[32*i+24], &st->a_data3[5]);
  }
  /* calculate levels in each frequency band */
  /* 4800 - 6400 Hz*/
  level[11] = level_calculation(tmp_buf, &st->sub_level[11],
                FRAME_LEN/4-48, FRAME_LEN/4, 4, 1, 0.25);
  /* 4000 - 4800 Hz*/
  level[10] = level_calculation(tmp_buf, &st->sub_level[10],
                FRAME_LEN/8-24, FRAME_LEN/8, 8, 7, 0.5);
  /* 3200 - 4000 Hz*/
  level[9] = level_calculation(tmp_buf, &st->sub_level[9],
               FRAME_LEN/8-24, FRAME_LEN/8, 8, 3, 0.5);
  /* 2400 - 3200 Hz*/
  level[8] = level_calculation(tmp_buf, &st->sub_level[8],
               FRAME_LEN/8-24, FRAME_LEN/8, 8, 2, 0.5);
  /* 2000 - 2400 Hz*/
  level[7] = level_calculation(tmp_buf, &st->sub_level[7],
               FRAME_LEN/16-12, FRAME_LEN/16, 16, 14, 1.0);
  /* 1600 - 2000 Hz*/
  level[6] = level_calculation(tmp_buf, &st->sub_level[6],
               FRAME_LEN/16-12, FRAME_LEN/16, 16, 6, 1.0);
  /* 1200 - 1600 Hz*/
  level[5] = level_calculation(tmp_buf, &st->sub_level[5],
               FRAME_LEN/16-12, FRAME_LEN/16, 16, 4, 1.0);
  /* 800 - 1200 Hz*/
  level[4] = level_calculation(tmp_buf, &st->sub_level[4],
               FRAME_LEN/16-12, FRAME_LEN/16, 16, 12, 1.0);
  /* 600 - 800 Hz*/
  level[3] = level_calculation(tmp_buf, &st->sub_level[3],
               FRAME_LEN/32-6, FRAME_LEN/32, 32, 8, 2.0);
  /* 400 - 600 Hz*/
  level[2] = level_calculation(tmp_buf, &st->sub_level[2],
               FRAME_LEN/32-6, FRAME_LEN/32, 32, 24, 2.0);
  /* 200 - 400 Hz*/
  level[1] = level_calculation(tmp_buf, &st->sub_level[1],
               FRAME_LEN/32-6, FRAME_LEN/32, 32, 16, 2.0);
  /* 0 - 200 Hz*/
  level[0] = level_calculation(tmp_buf, &st->sub_level[0],
               FRAME_LEN/32-6, FRAME_LEN/32, 32, 0, 2.0);
}
/******************************************************************************
*
*     Function   : update_cntrl
*     Purpose    : Control update of the background noise estimate.
*
*******************************************************************************
*/
static void update_cntrl(
  VadVars *st,   /* i/o : State structure                    */
  float level[] /* i   : sub-band levels of the input frame */
)
{
  Word16 i;
  float stat_rat;
  float num, denom;
  float alpha;
  /* if fullband pitch or tone have been detected for a while, initialize stat_count */
  if ((st->pitch_tone & 0x7c00) == 0x7c00)
  {
     st->stat_count = STAT_COUNT;
  }
  else
  {
     /* if 8 last vad-decisions have been "0", reinitialize stat_count */
     if ((st->vadreg & 0x7f80) == 0)
     {
        st->stat_count = STAT_COUNT;
     }
     else
     {
        stat_rat = 0;
        for (i = 0; i < COMPLEN; i++)
        {
           if (level[i] > st->ave_level[i])
           {
              num = level[i];
              denom = st->ave_level[i];
           }
           else
           {
              num = st->ave_level[i];
              denom = level[i];
           }
           /* Limit nimimum value of num and denom to STAT_THR_LEVEL */
           if (num  < STAT_THR_LEVEL)
           {
              num = STAT_THR_LEVEL;
           }
           if (denom < STAT_THR_LEVEL)
           {
              denom = STAT_THR_LEVEL;
           }
           stat_rat += num/denom * 64;
        }
        /* compare stat_rat with a threshold and update stat_count */
        if (stat_rat  > STAT_THR)
        {
           st->stat_count = STAT_COUNT;
        }
        else
        {
           if ((st->vadreg & 0x4000) != 0)
           {
              if (st->stat_count != 0)
              {
                 st->stat_count--;
              }
           }
        }
     }
  }
  /* Update average amplitude estimate for stationarity estimation */
  alpha = ALPHA4;
  if (st->stat_count == STAT_COUNT)
  {
     alpha = 1.0;
  }
  else if ((st->vadreg & 0x4000) == 0)
  {
     alpha = ALPHA5;
  }
  for (i = 0; i < COMPLEN; i++)
  {
     st->ave_level[i] += alpha *(level[i]- st->ave_level[i]);
  }
}
/******************************************************************************
*
*     Function     : hangover_addition
*     Purpose      : Add hangover after speech bursts
*
*******************************************************************************
*/
static Word16 hangover_addition( /* return: VAD_flag indicating final VAD decision */
  VadVars *st,       /* i/o : State structure                     */
  Word16 low_power,  /* i   : flag power of the input frame    */
  Word16 hang_len,   /* i   : hangover length */
  Word16 burst_len   /* i   : minimum burst length for hangover addition */
)
{
   /* if the input power (pow_sum) is lower than a threshold, clear
      counters and set VAD_flag to "0"  "fast exit"                 */
   if (low_power != 0)
   {
      st->burst_count = 0;
      st->hang_count = 0;
      return 0;
   }
   /* update the counters (hang_count, burst_count) */
   if ((st->vadreg & 0x4000) != 0)
   {
      st->burst_count++;
      if (st->burst_count >= burst_len)
      {
         st->hang_count = hang_len;
      }
      return 1;
   }
   else
   {
      st->burst_count = 0;
      if (st->hang_count > 0)
      {
         st->hang_count--;
         return 1;
      }
   }
   return 0;
}
/******************************************************************************
*
*     Function   : noise_estimate_update
*     Purpose    : Update of background noise estimate
*
*******************************************************************************
*/
static void noise_estimate_update(
  VadVars *st,    /* i/o : State structure                       */
  float level[]   /* i   : sub-band levels of the input frame */
)
{
   Word16 i;
   float alpha_up, alpha_down, bckr_add, temp;
   /* Control update of bckr_est[] */
   update_cntrl(st, level);
   /* Choose update speed */
   bckr_add = 2.0;
   if ((0x7800 & st->vadreg) == 0)
   {
      alpha_up = ALPHA_UP1;
      alpha_down = ALPHA_DOWN1;
   }
   else
   {
      if (st->stat_count == 0)
      {
         alpha_up = ALPHA_UP2;
         alpha_down = ALPHA_DOWN2;
      }
      else
      {
         alpha_up = 0.0;
         alpha_down = ALPHA3;
         bckr_add = 0.0;

⌨️ 快捷键说明

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