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

📄 avq_cod.c

📁 关于AMR-WB+语音压缩编码的实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------------------*
 *         SPLIT ALGEBRAIC VECTOR QUANTIZER BASED ON RE8 LATTICE             *
 *---------------------------------------------------------------------------*
 * NOTE: a mitsmatch can occurs in some subvectors between the encoder       *
 *       and decoder, because the encoder use a bit-rate estimator to set    *
 *       the TCX global gain - this estimator is many times faster than the  *
 *       call of RE8_idx() for bits calculation.                             * 
 *---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "../include/amr_plus.h"
#define NQ_MAX     36
#define FAC_LOG2   3.321928095f
#define NSV_MAX    256     /* number of sub-vector max in QVAE, 256*8=2048 */
/* local function */
static int calc_bits(int nq);
static void sort(int *ebits, int n, int *idx);
static void split_idx_noovf(int *xriq, int NB_BITS, int Nsv, int *nq, long *I, int *kv);
static void writ_all_nq(int n_pack, int *nq, int *pos_n, int NB_BITS, int Nsv, int *last, int **parm_ptr);
static void chk_ovf(int n_bits, int n, int *n1, int *n2);
static void writ_I(int n, int *pos_i, long *I, int *parm);
static void writ_k(int n, int *pos_i, int *k, int *parm, int flag);
static void init_pos_i_ovf(int n_pack, int *nq, int *pos_n, int last, int *pos_i_ovf);
static void writ_ovf(int n_pack, int *parm_ovf, int n, int *pos_i_ovf, int *pos_n, int **parm_ptr);
static void writ_all_i(int n_pack, int *nq, int *pos_n, int last, long *I, int *kv, int **parm_ptr);
float AVQ_cod(   /* output: comfort noise gain factor      */ 
  float *xri,    /* input:  vector to quantize             */
  int *xriq,     /* output: quantized normalized vector (assuming the bit budget is enough) */ 
  int NB_BITS,   /* input:  number of allocated bits          */ 
  int Nsv)       /* input:  number of subvectors (lg=Nsv*8) */  
{
  int    i, l, n, iter, c[8];
  float  gain, gain_inv, x1[8], ener, tmp, nbits, nbits_max, fac, offset;
  float  ebits[NSV_MAX];
  /* find energy of each subvector in log domain (scaled for bits estimation) */
  for (l=0; l<Nsv; l++)
  {
    for (i=0;i<8;i++) {
	x1[i] = xri[l*8+i];
    }
    ener = 2.0; /* to set ebits >= 0 */
    for (i=0;i<8;i++) {
	ener += x1[i]*x1[i];
    }
    /* estimated bit consumption when gain=1 */ 
    ebits[l] = 5.0f*FAC_LOG2*(float)log10(ener*0.5);
  }
  /*---------------------------------------------------------------------*
   * subvector energy worst case:                                        *
   * - typically, it's a tone with maximum of amplitude (RMS=23170).     *
   * - fft length max = 1024 (N/2 is 512)                                *
   * log10(energy) = log10(23710*23710*1024*(N/2)) = 14.45               *
   * ebits --> 5.0*FAC_LOG2*14.45 = 240 bits                             *
   *---------------------------------------------------------------------*/
  /* estimate gain according to number of bits allowed */
  fac = 128.0;      /* start at the middle (offset range = 0 to 255.75) */
  offset = 0.0;
  nbits_max = 0.95f * ((float)(NB_BITS - Nsv));
  /* tree search with 10 iterations : offset with step of 0.25 bits (0.3 dB) */
  for (iter=0; iter<10; iter++)
  {
    offset += fac;
    /* calculate the required number of bits */
    nbits = 0.0;
    for (l=0; l<Nsv; l++)
    {
      tmp = ebits[l] - offset;
      if (tmp < 0.0) {
	tmp = 0.0;
      }
      nbits += tmp;
    }
    /* decrease gain when no overflow occurs */
    if (nbits <= nbits_max) {
      offset -= fac;
    }
    fac *= 0.5;
  } 
  /* estimated gain (when offset=0, estimated gain=1) */
  gain = (float)pow(10.0, offset / (2.0*5.0*FAC_LOG2) );
  gain_inv = 1.0f / gain;
  /* quantize all subvector using estimated gain */
  for (l=0; l<Nsv; l++)
  {
    for (i=0;i<8;i++) {
      x1[i] = xri[l*8+i] * gain_inv;
    }
    RE8_PPV(x1, c);
    for (i=0;i<8;i++) {
      xriq[l*8+i] = c[i];
    }
  }
  /* evaluate comfort noise level at freq. over 3200Hz (Nsv/2) */
  /* SV with ebits < 5 bits may not be quantized */
  nbits = 0;
  n = 1;
#ifdef ENHANCE_TCX_NOISE_FILL
  /* reduce noise level when SNR is high over 3200Hz (on music harmonic tone) */
  tmp = 0.0f;
  for (l=Nsv/2; l<Nsv; l++) if (ebits[l] > tmp) tmp = ebits[l];
  tmp = tmp - 10.0f;
  if (offset < tmp) offset = tmp;
#endif
  for (l=Nsv/2; l<Nsv; l++)
  {
    tmp = ebits[l] - offset;
    if (tmp < 5.0)
    {
      nbits += tmp;
      n++;
    }
  }
  nbits /= (float)n;
  fac = (float)pow(10.0, (nbits-5.0) / (2.0*5.0*FAC_LOG2) );
  /* round bit allocations and save */
  for (i=0; i<Nsv; i++) {
    xriq[(Nsv*8)+i] = (int)floor(ebits[i]*128.0);
  }
  return(fac);
}
/*
  AVQ_encmux(xriq, parm, n_bits, NB_BITS, Nsv, n_pack)
  ENCODE AND MULTIPLEX SUBVECTORS INTO SEVERAL PACKETS
   -> n_pack  : number of packets
   -> xriq    : rounded subvectors [0..8*Nsv-1]
                followed by rounded bit allocations [8*Nsv..8*Nsv+Nsv-1]
  <-> param   : multiplexed parameters
   -> n_bits  : size of each packet 
   -> Nsv     : number of subvectors
  note:
  Nsv MUST be multiple of n_pack
  IMPORTANT:
  it is assumed that codebook numbers in track #p do not cause bit
  budget overflow in packet #p
  in practice this is ok if p<5 because the quantizer #n takes 5n bits
  and putting all bits in subvectors of track #p results in NB_BITS/5 bits
  for codebook numbers
*/
void AVQ_encmux(int n_pack, int *xriq, int *param, int *n_bits, int Nsv)
{
  int   last,i,p;
  int   kv[NSV_MAX*8], nq[NSV_MAX];
  long  I[NSV_MAX];
  int pos_n[N_PACK_MAX];
  /* int pos_i[N_PACK_MAX]; */
  int *parm;
  int *parm_ptr[4];
  int NB_BITS;
  NB_BITS=0;
  for (i=0; i<n_pack; i++) 
  {
    parm_ptr[i] = param;
    NB_BITS += n_bits[i];
    param += ((n_bits[i]+3)/4);
  }
  /* initialize pointers and packets */
  for (p=0; p<n_pack; p++)
    {
      /* pos_i[p] = 0; */
      pos_n[p] = n_bits[p]-1;
      /* initialize packet to zero, i.e. all subvectors are set to zero */
      parm = parm_ptr[p];
      for (i=0; i<=((n_bits[p]-1)/4); i++) {
	parm[i] = 0;
      }
    }
  /* encode subvectors and fix possible overflows in TOTAL bit budget:
     i.e. find (i,nq) for each subvector where
          i is a codevector index split in a base codebook index (I) and
                                                  a Voronoi index (kv)
          nq is a codebook index (nq=0,2,3,4,...) */
  split_idx_noovf(xriq, NB_BITS, Nsv, nq, I, kv);
  /* split multiplexing of codebook numbers (by interleaved tracks) */
  writ_all_nq(n_pack, nq, pos_n, NB_BITS, Nsv, &last, parm_ptr);
  /* write indices
     multiplexing is done track-by-track (from track #0 to track #n_pack-1) */
  writ_all_i(n_pack, nq, pos_n, last, I, kv, parm_ptr);
  return;
}
/*
  calc_bits(nq)
  COMPUTE (NUMBER OF BITS -1) TO DESCRIBE Q #nq
  -> nq: quantizer id (0,2,3,4...)
  <-   : bit allocation
*/
static int calc_bits(int nq)
{
  if (nq >= 2) {
    /* 4n bits + variable-length descriptor for allocation:
       descriptor -> nq
       0          -> 0
       10         -> 2
       110        -> 3
       => size of descriptor = 5n bits */
    return((nq*5)-1); /* [5n-1] */
  }
  else {
    return 0; /* 1-1 [1 bit to describe the allocation] */
  }
}
/*
  sort(ebits, n, idx)
  SORT SUBVECTORS BY DECREASING BIT ALLOCATIONS
  -> ebits : estimated bit allocations (table of n *positive* integers)
  -> n     : number of subvectors
  <- idx   : indices
*/
static void sort(int *ebits, int n, int *idx)
{
  int t[NSV_MAX],i,j,ebits_max,pos;
  for (i=0; i<n;i++) {
    t[i]=ebits[i];
  }
  for (i=0; i<n; i++) {
      ebits_max = t[0];
      pos = 0;
      for (j=1; j<n; j++) {
        if (t[j]>ebits_max) {
          ebits_max = t[j];
          pos = j;
        }
      }
      idx[i]=pos;
      t[pos]=-1;
  }
  return;
}
/*
  split_idx_noovf(xriq,NB_BITS, Nsv, nq, I, kv, last)
  COMPUTE MULTI-RATE INDICES FOR ALL SUBVECTORS AND FORCE NO BIT BUDGET OVERFLOW
  PRIOR TO MULTIPLEXING
  -> xriq    : rounded subvectors [0..8*Nsv-1]
               followed by rounded bit allocations [8*Nsv..8*Nsv+Nsv-1]
  -> NB_BITS : number of bits allocated for split multi-rate RE8 VQ
  -> Nsv     : number of subvectors
  <- nq      : codebook numbers
  <- I       : indices for base quantizers (Q2,Q3,Q4)
  <- kv      : Voronoi indices
*/
static void split_idx_noovf(int *xriq, int NB_BITS, int Nsv, int *nq, long *I, int *kv)
{
  int k,l,n,n_bits,pos, pos_max;
  int sort_idx[NSV_MAX];
  /* sort subvectors by estimated bit allocations in decreasing order
     (l=idx[0] is such that (rounded) ebits[l] is maximum) */
  sort(&xriq[8*Nsv],Nsv,sort_idx);
  /* compute multi-rate indices and avoid bit budget overflow  */
  pos_max = 0;
  n_bits = 0;
  for (l=0; l<Nsv; l++) {
    /* find vector to quantize (criteria: nb of estimated bits) */
    pos = sort_idx[l];
    /* compute multi-rate index of rounded subvector (nq,I,kv[]) */

⌨️ 快捷键说明

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