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

📄 dec_dtx.c

📁 关于AMR-WB+语音压缩编码的实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
      temp1 = temp - isf[i - 1];
      /* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */
      if(temp1 < ISF_DITH_GAP)
      {
         isf[i] = (Word16)(isf[i - 1] + ISF_DITH_GAP);
      }
      else
      {
         isf[i] = (Word16)temp;
      }
   }
   /* Make sure that isf[M-2] will not get values above 16384 */
   if(isf[M - 2] > 16384)
   {
      isf[M - 2] = 16384;
   }
   return;
}
/*
 * D_DTX_exe
 *
 * Parameters:
 *    st           I/O: state struct
 *    exc2           O: CN excitation
 *    new_state      I: New DTX state
 *    prms           I: Vector of synthesis parameters
 *    isf            O: CN ISF vector
 *
 * Function:
 *    Confort noise generation
 *
 * Returns:
 *    void
 */
void D_DTX_exe(D_DTX_State *st, Word16 *exc2, Word16 new_state, Word16 isf[],
               Word16 **prms)
{
   Word32 i, j, L_tmp, ptr;
   Word32 exp0, int_fac;
   Word32 gain;
   Word32 L_isf[M], L_log_en_int, level32, ener32;
   Word16 log_en_index;
   Word16 tmp_int_length;
   Word16 exp, log_en_int_e, log_en_int_m, level;
   /*
    * This function is called if synthesis state is not SPEECH.
    * The globally passed inputs to this function are
    *    st->sid_frame
    *    st->valid_data
    *    st->dtxHangoverAdded
    *    new_state (SPEECH, DTX, D_DTX_MUTE)                               
    */      
   if((st->mem_dtx_hangover_added != 0) & (st->mem_sid_frame != 0))
   {
      /* sid_first after dtx hangover period
       * or sid_upd after dtxhangover
       * consider twice the last frame
       */
      ptr = st->mem_hist_ptr + 1;
      if(ptr == D_DTX_HIST_SIZE)
      {
         ptr = 0;
      }
      memcpy(&st->mem_isf_buf[ptr * M], &st->mem_isf_buf[st->mem_hist_ptr * M], 
         M * sizeof(Word16));                                                   
      st->mem_log_en_buf[ptr] = st->mem_log_en_buf[st->mem_hist_ptr];
      /* compute mean log energy and isf from decoded signal (SID_FIRST) */
      st->mem_log_en = 0;
      memset(L_isf, 0, M * sizeof(Word32));
      /* average energy and isf */
      for(i = 0; i < D_DTX_HIST_SIZE; i++)
      {
         /*
          * Division by D_DTX_HIST_SIZE = 8 has been done in dtx_buffer log_en
          * is in Q10
          */
         st->mem_log_en = (Word16)(st->mem_log_en + st->mem_log_en_buf[i]);
         for(j = 0; j < M; j++)
         {
            L_isf[j] = L_isf[j] + st->mem_isf_buf[i * M + j];
         }
      }
      /* st->log_en in Q9 */
      st->mem_log_en = (Word16)(st->mem_log_en >> 1);
      /*
       * Add 2 in Q9, in order to have only positive values for Pow2
       * this value is subtracted back after Pow2 function
       */
      st->mem_log_en = (Word16)(st->mem_log_en + 1024);
      if(st->mem_log_en < 0)    
      {
         st->mem_log_en = 0;
      }     
      for(j = 0; j < M; j++)
      {
         st->mem_isf[j] = (Word16)(L_isf[j]>>3);   /* divide by 8 */
      }
   }
   if(st->mem_sid_frame != 0)
   {
      /*
       * Set old SID parameters, always shift
       * even if there is no new valid_data
       */
      memcpy(st->mem_isf_prev, st->mem_isf, M * sizeof(Word16));
      st->mem_log_en_prev = st->mem_log_en;
      if(st->mem_valid_data != 0) /* new data available (no CRC) */             
      {
         /* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
         /*
          * Compute interpolation factor, since the division only works
          * for values of since_last_sid < 32 we have to limit
          * the interpolation to 32 frames
          */
         tmp_int_length = st->mem_since_last_sid;
         if(tmp_int_length > 32)
         {
            tmp_int_length = 32;
         }
         if(tmp_int_length >= 2)
         {
            st->mem_true_sid_period_inv =
               (Word16)(0x2000000 / (tmp_int_length << 10));
         }
         else
         {
            st->mem_true_sid_period_inv = 1 << 14;   /* 0.5 it Q15 */
         }
         D_LPC_isf_noise_d(*prms, st->mem_isf);
         (*prms) += 5;
         log_en_index = *(*prms)++;
         /* read background noise stationarity information */
         st->mem_cn_dith = *(*prms)++;
         /*
          * st->log_en = (Float32)log_en_index / 2.625 - 2.0;
          * log2(E) in Q9 (log2(E) lies in between -2:22)
          */
         st->mem_log_en = (Word16)(log_en_index << (15 - 6));
         /* Divide by 2.625  */
         st->mem_log_en = (Word16)((st->mem_log_en * 12483) >> 15);
         /*
          * Subtract 2 in Q9 is done later, after Pow2 function
          * no interpolation at startup after coder reset
          * or when SID_UPD has been received right after SPEECH
          */                            
         if((st->mem_data_updated == 0) ||
            (st->mem_dtx_global_state == SPEECH))
         {
            memcpy(st->mem_isf_prev, st->mem_isf, M * sizeof(Word16));
            st->mem_log_en_prev = st->mem_log_en;
         }
      }   /* endif valid_data */
   }   /* endif sid_frame */
   if((st->mem_sid_frame != 0) && (st->mem_valid_data != 0))
   {
      st->mem_since_last_sid = 0;
   }
   /* Interpolate SID info */                               
   if(st->mem_since_last_sid < 32)
   {
      int_fac = st->mem_since_last_sid << 10;   /* Q10 */
   }
   else
   {
      int_fac = 32767;
   }
   /* Q10 * Q15 -> Q10 */
   int_fac = (int_fac * st->mem_true_sid_period_inv) >> 15;
   /* Maximize to 1.0 in Q10 */
   if(int_fac > 1024)
   {
      int_fac = 1024;
   }
   int_fac = int_fac << 4;   /* Q10 -> Q14 */
   L_log_en_int = (int_fac * st->mem_log_en) << 1;   /* Q14 * Q9 -> Q24 */
   for(i = 0; i < M; i++)
   {
      /* Q14 * Q15 -> Q14 */
      isf[i] = (Word16)((int_fac * st->mem_isf[i]) >> 15);
   }
   int_fac = 16384 - int_fac;   /* 1-k in Q14 */
   /* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */                                   
   L_log_en_int = L_log_en_int + ((int_fac * st->mem_log_en_prev) << 1);
   for(i = 0; i < M; i++)
   {
      /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
      L_tmp = isf[i] + ((int_fac * st->mem_isf_prev[i]) >> 15);
      isf[i] = (Word16)(L_tmp << 1);   /* Q14 -> Q15 */
   }
   /* If background noise is non-stationary, insert comfort noise dithering */
   if(st->mem_cn_dith != 0)
   {
      D_DTX_cn_dithering(isf, &L_log_en_int, &st->mem_dither_seed);
   }
   /* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
   L_log_en_int = (L_log_en_int >> 9); /* Q25 -> Q16 */
   /* Find integer part  */
   log_en_int_e = (Word16)((L_log_en_int)>>16);
   /* Find fractional part */
   log_en_int_m = (Word16)((L_log_en_int - (log_en_int_e << 16)) >> 1);
   /*
    * Subtract 2 from L_log_en_int in Q9,
    * i.e divide the gain by 2 (energy by 4)
    * Add 16 in order to have the result of pow2 in Q16
    */
   log_en_int_e = (Word16)(log_en_int_e + (16 - 1));
   /* level = (Float32)( pow( 2.0f, log_en ) );  */
   level32 = D_UTIL_pow2(log_en_int_e, log_en_int_m);   /* Q16 */
   exp0 = D_UTIL_norm_l(level32);
   level32 = (level32 << exp0);   /* level in Q31 */
   exp0 = (15 - exp0);
   level = (Word16)(level32 >> 16);   /* level in Q15 */
   /* generate white noise vector */
   for(i = 0; i < L_FRAME; i++)
   {
      exc2[i] = (Word16)((D_UTIL_random(&(st->mem_cng_seed)) >> 4));
   }
   /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
   /* energy of generated excitation */
   ener32 = D_UTIL_dot_product12(exc2, exc2, L_FRAME, &exp);
   D_UTIL_normalised_inverse_sqrt(&ener32, &exp);
   gain = ener32 >>16;
   gain = (level * gain) >> 15;   /* gain in Q15 */
   /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
   exp = (Word16)(exp0 + exp  + 4);
   if(exp >= 0)
   {
      for(i = 0; i < L_FRAME; i++)
      {
         L_tmp = (exc2[i] * gain) >> 15;   /* Q0 * Q15 */
         exc2[i] = (Word16)(L_tmp << exp);
      }
   }
   else
   {                                                                            
      exp = (Word16)-exp;
      for(i = 0; i < L_FRAME; i++)
      {
         L_tmp = (exc2[i] * gain) >> 15;   /* Q0 * Q15 */
         exc2[i] = (Word16)(L_tmp >> exp);
      }
   }
   if(new_state == D_DTX_MUTE)
   {
      /*
       * mute comfort noise as it has been quite a long time since
       * last SID update was performed
       */
      tmp_int_length = st->mem_since_last_sid;
      if(tmp_int_length > 32)
      {
         tmp_int_length = 32;
      }
      st->mem_true_sid_period_inv = D_UTIL_saturate((0x02000000 / (tmp_int_length << 10)));
      st->mem_since_last_sid = 0;
      st->mem_log_en_prev = st->mem_log_en;
      /* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
      st->mem_log_en = D_UTIL_saturate(st->mem_log_en - 64);
   }
   /* reset interpolation length timer if data has been updated.        */
   if((st->mem_sid_frame != 0) && ((st->mem_valid_data != 0) ||
      ((st->mem_valid_data == 0) && (st->mem_dtx_hangover_added) != 0)))
   {
      st->mem_since_last_sid = 0;
      st->mem_data_updated = 1;
   }
   return;
}
/*
 * D_DTX_activity_update
 *
 * Parameters:
 *    st           I/O: state struct
 *    isf            O: ISF vector
 *    exc            O: excitation
 *
 * Function:
 *    Confort noise generation
 *
 * Returns:
 *    void
 */
void D_DTX_activity_update(D_DTX_State *st, Word16 isf[], Word16 exc[])
{
   Word32 L_frame_en, log_en;
   Word32 i;
   Word16 log_en_e, log_en_m;
   st->mem_hist_ptr = (Word16)(st->mem_hist_ptr + 1);
   if(st->mem_hist_ptr == D_DTX_HIST_SIZE)
   {
      st->mem_hist_ptr = 0;
   }
   memcpy(&st->mem_isf_buf[st->mem_hist_ptr * M], isf, M * sizeof(Word16));
   /* compute log energy based on excitation frame energy in Q0 */
   L_frame_en = 0;
   for(i = 0; i < L_FRAME; i++)
   {
      L_frame_en = L_frame_en + (exc[i] * exc[i]);
      if (L_frame_en > MAX_31)
      {
         L_frame_en = MAX_31;
         break;
      }
   }
   /*
    * log_en =
    * (Float32)log10(L_frame_en/(Float32)L_FRAME)/(Float32)log10(2.0f);
    */
   D_UTIL_log2(L_frame_en, &log_en_e, &log_en_m);
   /*
    * convert exponent and mantissa to Word16 Q7.
    * Q7 is used to simplify averaging in dtx_enc
    */
   log_en = log_en_e << 7;   /* Q7 */
   log_en = log_en + (log_en_m >> (15 - 7));
   /* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
   log_en = log_en - 1024;
   /* insert into log energy buffer */
   st->mem_log_en_buf[st->mem_hist_ptr] = (Word16)log_en;
   return;
}

⌨️ 快捷键说明

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