www.pudn.com > AVS_M_ver10.rar > avq_cod.c
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2007 Audio Video Coding Standard, Part Ⅹ
*
* This software module was developed by AVS Audio sub-group
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the users without any
* license fee or royalty on an "as is" basis. The AVS disclaims
* any and all warranties, whether express, implied, or statutory,
* including any implied warranties of merchantability or of fitness
* for a particular purpose. In no event shall the contributors or
* the AVS be liable for any incidental, punitive, or consequential
* damages of any kind whatsoever arising from the use of this program.
*
* This disclaimer of warranty extends to the user of this program
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The AVS does not represent or warrant that the program furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy is available from the AVS Web site at
* http://www.avs.org.cn
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
************************************************************************
*/
/*---------------------------------------------------------------------------*
* 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 */
#ifdef NEW_TVC
#define VQ_FACTOR 5.285f
#define VQ_FACTOR2 1.1f
/* local function */
static int calc_bits(int nq, int flag, int* nq_change, int cache_hit);
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, int* flag, int *ka);
static void writ_all_nq(int n_pack, int *nq, int *pos_n, int NB_BITS, int Nsv, int *last, int **parm_ptr, int* flag, int *cache_hit);
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, int *cache_hit);
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, int* flag, int *cache_hit);
static int calc_header(int n, int flag, int* header,int cache_hit);
static int hit_table(int *p,long index,int base);
long cache[16*2]={0};
int hit_table(int *p,long index,int base)
{
long *point,*j;
int flag=0,tmp=base,cache_num;
for (point=p;point<p+16*2;point=point+2)
{
flag=0;
if (point[0]!=0)
{
flag=1;
if (tmp<point[0])
tmp=point[0];}
if (flag==0)
{break;}
if (point[1]==index)
{
cache_num=point[0];
for(j=p;j<p+16*2;j=j+2)
if (j[0]>point[0])
{
if (tmp<j[0])
tmp=j[0];
j[0]--;}
point[0]=tmp;
return cache_num;
}
}
if (flag==0){
point[0]=tmp+1;
}
else{
for (j=p;j<p+16*2;j=j+2)
if (j[0]>1&amt;&amt;j[0]<5) j[0]=j[0]-1;
else if (j[0]>4) ;
else {j[0]=4;point=j;}
}
point[1]=index;
return 0;
}
int calc_header(int n, int flag, int* header, int cache_hit)
{
int hd_len = 0;
if (flag > 0xfff || flag < 0)
flag = 0;
switch (flag &amt; RE8_MODE_MASK){
case RE8_MODE_SCALAR:
/* bits/digital in n, header = 111111 11 11 11 x mm
x = EVEN_FLAG
n = 6, 7, 8, 9 ==> mm = 00, 01, 10, 11 */
*header = 0xFFF << 3;
hd_len = 15;
if (flag &amt; RE8_EVEN_FLAG)
*header |= (1<<2);
*header |= (n-6);
break;
case RE8_MODE_BASE:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader in base codebook: n = 111111 10*/
*header = 0xFE<<1;
hd_len = 9;
if (flag &amt; RE8_EVEN_FLAG)
*header = *header + 1;
}else{
/* in Q0: n = 0, in Q2: n = 10, in Q3: n = 110, in Q4: n = 1110 */
if (n == 0){
*header = 0;
hd_len = 1;
}else if ( n== 2){
if (cache_hit){
*header = 0xD;
hd_len = 4;
}
else{
*header = 2;
hd_len = 2;
}
}else if (n == 3){
*header = 0xC;
hd_len = 4;
}else if (n == 4){
*header = 0xE<<1;
hd_len = 5;
if (flag &amt; RE8_EVEN_FLAG)
*header = *header + 1;
}
}
break;
case RE8_MODE_EXT1:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=1 in Q4 n = 111111 11 00*/
*header = 0x3FC;
hd_len = 11;
}else{
/* in Q3: n = 111111 00, in Q4: n = 11110 */
if (n == 3 || n == 2){
*header = 0xFC;
hd_len = 9;
}else{
*header = 0x1E;
hd_len = 6;
}
}
*header = *header << 1;
if (flag &amt; RE8_EVEN_FLAG)
*header = *header + 1;
break;
case RE8_MODE_EXT2:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=2 in Q4 n = 111111 11 11 0*/
*header = 0x7FE;
hd_len = 12;
}else{
/* in Q3: n = 111111 01, in Q4: n = 111110 */
if (n == 3 || n == 2){
*header = 0xFD;
hd_len = 9;
}else{
*header = 0x3E;
hd_len = 7;
}
}
*header = *header << 1;
if (flag &amt; RE8_EVEN_FLAG)
*header = *header + 1;
break;
case RE8_MODE_EXT3:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=3 in Q4 n = 111111 11 11 10*/
*header = 0xFFE;
hd_len = 13;
}else{
/* in Q3: n = 111111 11 01, in Q4: n = 111111 11 10 */
if (n == 3 || n == 2){
*header = 0x3FD;
hd_len = 11;
}else{
*header = 0x3FE;
hd_len = 11;
}
}
*header = *header << 1;
if (flag &amt; RE8_EVEN_FLAG)
*header = *header + 1;
break;
default:
printf(">s Internal error: unkown flag >d in RE8_cod()\r\n", "calc_header", flag);
}
return hd_len;
}
/* …… 预整形 模块 (开始) ……*/
/*-----------------------------------------------------------------*
* Funtion AVQ_gain_allocator *
* ->routine to compute two gains allocated to high band and low band
*-----------------------------------------------------------------*/
void AVQ_gain_allocator(
float *xri, /* (i) input samples in frequency band */
int len, /* (i) length of the sample array in whole band */
int bits_max, /* (i) available bits number */
float *gh, /* (o) gain for high band */
float* gg) /* (o) gain for low band */
{
float ebits[NSV_MAX];
float offset, offset1, offset2, tmp, nbits;
int Nsv = len / 8;
int rb,i;
offset = AVQ_gain_comput(xri, len, bits_max, ebits);
/* computing actual bits consumed by low band */
nbits = 0;
for (i = 0; i < Nsv/2; i++){
tmp = ebits[i] - offset;
if (tmp < 0.0){
tmp = 1.0;
}
nbits += tmp;
}
rb = bits_max - (int)ceil(VQ_FACTOR2*nbits);
/* high band gain estimation */
offset2 = AVQ_gain_comput(xri+len/2, len/2, rb, ebits);
/* computing actual bits consumed by high band */
nbits = 0;
for (i = 0; i < Nsv/2; i++){
tmp = ebits[i] - offset2;
if (tmp < 0.0){
tmp = 1.0;
}
nbits += tmp;
}
rb = bits_max - (int)ceil(VQ_FACTOR2*nbits);
/* further low band gain estimation */
offset1 = AVQ_gain_comput(xri, len/2, rb, ebits);
offset1 = (offset1 < offset)?offset:offset1;
offset2 = (offset2 > offset)?offset:offset2;
/* estimated gain (when offset=0, estimated gain=1) */
*gg = (float)pow(10.0, offset1 / (2.0*VQ_FACTOR*FAC_LOG2));
*gh = (float)pow(10.0, (offset1-offset2)/(2.0*VQ_FACTOR*FAC_LOG2));
//printf("gg = >f; gh = >f\r\n", *gg, *gh);
return;
}
/*-----------------------------------------------------------------*
* Funtion AVQ_get_nf *
* ->routine to get noise factor of a frame
* Return: noise factor
*-----------------------------------------------------------------*/
float AVQ_get_nf( /* output noise factor */
float *xri, /* (i) input samples in freqency band */
int NB_BITS, /* (i) available bits number */
int Nsv) /* (i) number of 8-bits subvectors */
{
int i, l, n, iter;
float 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] = VQ_FACTOR*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;
}
/* 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*VQ_FACTOR*FAC_LOG2) );
return(fac);
}
/*-----------------------------------------------------------------*
* Funtion AVQ_gband *
* ->routine to quantize the gain
* Return: quantized index of the gain
*-----------------------------------------------------------------*/
int AVQ_gband( /* output quantized index of the gain */
float gain, /* (i) gain to be quantized */
float *qgain) /* (o) gain after quantize/dequantize */
{
int tmp;
tmp = (int)floor(64 * gain + 0.5);
if (tmp > 127)
tmp = 127;
else if (tmp < 3)
tmp = 2;
*qgain = (float)tmp/(float)64.0;
return(tmp);
}
/*-----------------------------------------------------------------*
* Funtion AVQ_gain_comput *
* ->routine to estimate proper gain when bits_max bits are available
* Return: estimated gain
*-----------------------------------------------------------------*/
float AVQ_gain_comput( /* output estimated gain */
float *xri, /* (i) input samples in freqency band */
int len, /* (i) length of input samples */
int bits_max, /* (i) available bits number */
float *ebits) /* (o) estimated consumed bits for every 8-bit subvector */
{
int i, l, iter;
float x1[8], ener, tmp, nbits, nbits_max, fac, offset;
int Nsv = len / 8;
/* 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] = VQ_FACTOR*FAC_LOG2*(float)log10(ener*0.5);
}
fac = 128.0; /* start at the middle (offset range = 0 to 255.75) */
offset = 0.0;
nbits_max = 0.95f * ((float)(bits_max-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)); */
return(offset);
}
/*-----------------------------------------------------------------*
* Funtion AVQ_cod *
* ->routine to quantize input samples in a frame in freqency band
*-----------------------------------------------------------------*/
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) */
float *gh, /* input: ratio between high band and low band scale factor */
float *gg) /* input: whole band scale factor */
{
int i, l, c[8];
float gain_inv, x1[8], ener;
float ebits[NSV_MAX];
/* amplify high band */
for (l = 0; l < Nsv*8/2; l++){
xri[l+Nsv*8/2] *= (*gh);
}
/* 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] = VQ_FACTOR*FAC_LOG2*(float)log10(ener*0.5);
}
/* quantize all subvector using estimated gain */
gain_inv = 1.0f / (*gg);
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];
}
}
/* round bit allocations and save */
for (i=0; i<Nsv; i++) {
xriq[(Nsv*8)+i] = (int)floor(ebits[i]*128.0);
}
return 0;
}
/* …… 预整形 模块 (结束) ……*/
/*
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,flag[NSV_MAX];
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;
//new
int ka[NSV_MAX],l,hit_num=0,cache_hit[NSV_MAX]={0};
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, flag,ka);
//new
for (l=0; l<Nsv; l++){
if(nq[l]>0){
switch(ka[l]){
case 0:
case 1:
case 2:
hit_num=hit_table(cache,I[l],0);
break;
default: {hit_num=0;break;}
}
if(hit_num){
cache_hit[l]=1;
I[l]=hit_num;
}
}
}
//end
/* split multiplexing of codebook numbers (by interleaved tracks) */
writ_all_nq(n_pack, nq, pos_n, NB_BITS, Nsv, &amt;last, parm_ptr, flag, cache_hit);
/* 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, flag, cache_hit);
}
/*
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 n, int flag, int* nq_change, int cache_hit)
{
int len = 0;
if (flag > 0xfff || flag < 0)
flag = 0;
switch (flag &amt; RE8_MODE_MASK){
case RE8_MODE_SCALAR:
/* bits/digital in n, header = 111111 11 11 11 x mm */
len = 15 + n * 8;
*nq_change = n;
break;
case RE8_MODE_BASE:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader in base codebook: n = 111111 10*/
len = 9+4*4;
}else{
/* in Q0: n = 0, in Q2: n = 10, in Q3: n = 110, in Q4: n = 1110 */
if (n == 0){
len = 1;
}else if ( n== 2){
// len = 2+2*4;
if (cache_hit)
len= 8;
else
len = 2+2*4;
}else if (n == 3){
len = 3+3*4+1;
}else if (n == 4){
len = 5+4*4;
}
}
*nq_change = n;
break;
case RE8_MODE_EXT1:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=1 in Q4 n = 111111 11 00*/
len = 11+4*4+8;
}else{
/* in Q3: n = 111111 00, in Q4: n = 11110 */
if (n == 3 || n == 2){
len = 9+3*4+8;
}else{
len = 6+4*4+8;
}
}
if (n == 2)n = 3; /* consider Q2 as Q3 when using division table */
*nq_change = n+2;
break;
case RE8_MODE_EXT2:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=2 in Q4 n = 111111 11 11 0*/
len = 12+4*4+8*2;
}else{
/* in Q3: n = 111111 01, in Q4: n = 111110 */
if (n == 3 || n == 2){
len = 9+3*4+2*8;
}else{
len = 7+4*4+2*8;
}
}
if (n == 2)n = 3; /* consider Q2 as Q3 when using division table */
*nq_change = n+4;
break;
case RE8_MODE_EXT3:
if (flag &amt; RE8_SPEC_FLAG &amt;&amt; n == 4){
/* special leader with r=3 in Q4 n = 111111 11 11 10*/
len = 13+4*4+8*3;
}else{
/* in Q3: n = 111111 11 01, in Q4: n = 111111 11 10 */
if (n == 3 || n == 2){
len = 11+3*4+3*8;
}else{
len = 11+4*4+3*8;
}
}
if (n == 2)n = 3; /* consider Q2 as Q3 when using division table */
*nq_change = n + 6;
break;
default:
printf(">s Internal error: unkown flag >d in RE8_cod()\r\n", "calc_bits", flag);
}
return len;
}
/*
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* flag, int *ka)
{
int k,l,n,n_bits,pos, pos_max, n_ch;
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(&amt;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[]) */
RE8_cod(&amt;xriq[pos*8], &amt;nq[pos], &amt;I[pos], &amt;kv[8*pos], &amt;flag[pos], &amt;ka[pos]);
if (nq[pos]>0) {
k = pos_max;
if (pos > k) {
k = pos;
}
/* check for overflow and compute number of bits-1 (n) */
n = calc_bits(nq[pos], flag[pos], &amt;n_ch,0);
if ((n_bits+n+k) > NB_BITS) { /* if budget overflow */
// char str[35];
//printf("Truancate [>s] to Q0\r\n", re8_sprint(&amt;xriq[pos*8], str));
nq[pos] = 0; /* force Q0 */
} else {
n_bits += n;
pos_max = k; /* update index of last described subvector (last) */
}
}
}
// printf("here\r\n");
}
/*
writ_all_nq(n_pack, nq, pos_n, NB_BITS, last, parm_ptr)
ENCODE AND MULTIPLEX ALL CODEBOOKS NUMBERS IN nq[] TRACK-BY-TRACK
-> n_pack : number of packets
-> nq : table of codebook numbers [0..Nsv-1]
-> pos_n : table of pointers to write nq in packets [0..n_pack-1]
-> NB_BITS : total bit allocation
<- last : index of last subvector for which an index is written
<-> parm : bistream
*/
static void writ_all_nq(int n_pack, int *nq, int *pos_n, int NB_BITS, int Nsv, int *last, int **parm_ptr, int* flag, int *cache_hit)
{
int p, pos, l, i, n_bits, *parm, hd, hd_len,room,nq_change;
n_bits = NB_BITS;
*last = -1;
/* write nq[l] for l=0...Nsv-1 in packet #p= mod(l,number_of_packets)*/
for (l=0;l<Nsv;l++) {
p = l>n_pack; /* alternative : apply mask 0x01 / 0x03 */
parm = parm_ptr[p];
pos = pos_n[p];
/* compute the minimal bit budget to write nq[l] and the related index */
i = calc_bits(nq[l], flag[l], &amt;nq_change, cache_hit[l]);
/* if the budget is exceeded, force nq[l] to 0
else decrement the number of left bits */
if (i > n_bits) {
nq[l] = 0;
} else {
n_bits -= i;
}
/* update "last" */
if (nq[l] >= 2) {
*last=l;
}
/* write the header for nq[l] in packet #p */
hd_len = calc_header(nq[l], flag[l], &amt;hd, cache_hit[l]);
// printf("header = >x\r\n", hd);
/* fill the first 4 bits room and then fill remains*/
room = (pos>4)+1;
while (hd_len > room){
hd_len -= room;
parm[pos/4] += hd >> hd_len;
hd -= (hd >> hd_len) << hd_len;
pos -= room;
room = 4;
}
parm[pos/4] += hd << (room - hd_len);
pos -= hd_len;
pos_n[p] = pos;
if (nq_change > 4)
nq[l] = nq_change;
}
return;
}
/* check if n groups of 4 bits fit in n_bits bits */
static void chk_ovf(int n_bits, int n, int *n1, int *n2)
{
if (4*n<=n_bits) {
*n1=n;
*n2=0;
} else {
*n1=n_bits/4; /* >> 2*/
*n2=n-*n1;
}
}
/* write n groups of 4-bit for base codebook index (I) */
static void writ_I(int n, int *pos_i, long *I, int *parm)
{
int pos;
/* base codebook index */
pos = *pos_i/4;
while (n-- > 0) {
parm[pos++] = (*I &amt; 0x0F);
*I = *I>>4;
}
*pos_i=pos*4;
}
/* write n groups of 4-bit for Voronoi index (k[]) */
static void writ_k(int n, int *pos_i, int *k, int *parm, int flag)
{
int i, ival, delta, *kv, pos;
delta = 4*flag;
pos = *pos_i/4;
while (n-- > 0) {
kv=k+delta;
ival = 0;
for (i=0; i<4; i++) {
ival <<= 1;
ival += (kv[i] &amt; 0x01);
kv[i] >>= 1;
}
parm[pos++] = ival;
delta = (delta+4)>8; /* circular shift */
}
*pos_i=pos*4;
}
/* find in each packet the positions where overflow occurs */
static void init_pos_i_ovf(int n_pack, int *nq, int *pos_n, int last, int *pos_i_ovf, int *cache_hit)
{
int p, pos, n_bits, l, n1, n2, ni=0;
for (p=0; p<n_pack; p++) {
pos = 0;
n_bits = pos_n[p]+1; /* pos_n[p] - 0 +1 */
for (l=p; l<=last; l+=n_pack) {
if (nq[l] > 0) {
ni=nq[l];
if(ni==2&amt;&amt;cache_hit[l])
ni=ni-1;
chk_ovf(n_bits, ni, &amt;n1, &amt;n2);
n_bits -= 4*n1;
pos += n1;
}
}
pos_i_ovf[p] = pos*4;
}
}
/* write bits in overflow */
static void writ_ovf(int n_pack, int *parm_ovf, int n, int *pos_i_ovf, int *pos_n, int **parm_ptr)
{
int pos_ovf, p, n_bits, pos, *parm, moved_bit;
/* initialize position in overflow packet (parm_ovf[]) */
pos_ovf=0;
/* move bits from overflow packet (parm_ovf[]) to packets (parm_ptr[][])
[write 4-bit by 4-bit] */
for (p=0; p<n_pack; p++) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos_i_ovf[p]+1;
if ((n_bits >= 4) &amt;&amt; (n>0)) {
pos=pos_i_ovf[p]/4;
parm = parm_ptr[p];
do {
parm[pos++]=parm_ovf[pos_ovf++]; /* move 4 bits */
n_bits -= 4;
n -= 4;
} while ((n_bits>=4) &amt;&amt; (n>0));
pos_i_ovf[p]=pos*4;
}
}
pos_ovf *=4;
/* move bits remaining in overflow packet
[write bit-by-bit (3 bits at maximum per packet)] */
for (p=0; p<n_pack; p++) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos_i_ovf[p]+1;
if ((n_bits > 0) &amt;&amt; (n>0)) {
pos = pos_i_ovf[p];
parm = parm_ptr[p];
do {
/* write a single bit */
moved_bit = (parm_ovf[pos_ovf/4] >> (pos_ovf>4)) &amt; 0x01;
parm[pos/4] += moved_bit<<(pos>4);
pos++;
pos_ovf++;
n_bits--;
n--;
} while ((n_bits > 0) &amt;&amt; (n > 0));
pos_i_ovf[p] = pos;
}
}
}
/*
writ_all_i(nq, p, pos_n, n_pack, last, pos_ovf, n_bits_left, parm_ptr)
MULTIPLEX AN INDEX (I,kv) OF 4*nq BITS INTO BITSTREAM
(THE INDEX CORRESPONDS TO A SUBVECTOR IN TRACK #p)
-> nq : codebook number (scalar)
-> p : index of track
-> pos_i : pointer to write i in packet [0..n_pack-1]
-> n_pack : number of packets
<-> pos_ovf : pointers for overflow [0..n_pack-1]
<-> n_bits_left : number of unused bits in packets [0..n_pack-1]
-> I : base codebook index
-> kv : Voronoi index
<-> parm : bistream [initialized to zero when writ_all_i is called]
->flag : mode flag to decide encoding mode.
->cache_hit : whether Q2 index is cache index or basebook index
important note:
- if the index fits completely in packet #p, multiplexing is done as
in writ_parm from top to bottom:
the 1st bit of I is written at the top
the last bit of kv at the bottom
*/
static void writ_all_i(int n_pack, int *nq, int *pos_n, int last, long *I, int *kv, int **parm_ptr, int* flag, int *cache_hit)
{
int pos_ovf, p, l, n_bits, ni, nk, n1, i, n2, pos, k[8], *parm;
long index;
// char str[35];
int parm_ovf[NQ_MAX];
int pos_i_ovf[N_PACK_MAX];
/* initialize overflow packet */
for (i=0; i<NQ_MAX; i++) {
parm_ovf[i]=0;
}
/* find positions in each packet from which the bits in overflow can be
written */
init_pos_i_ovf(n_pack, nq, pos_n, last, pos_i_ovf,cache_hit);
/* write indices */
for (p=0; p<n_pack; p++) {
pos = 0;
parm = parm_ptr[p];
for (l=p; l<=last; l+=n_pack) {
if (nq[l] > 0) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos+1;
/* compute number of 4-bit groups for base codebook index (ni)
and Voronoi index (nk) */
ni=nq[l];
nk = 0;
if(ni==2&amt;&amt;cache_hit[l]==1)
ni=ni-1;
if (ni <= 4){
for (i = 0; i < 8; i++)
kv[8*l+i] = 0;
}
// printf("I = >d k = [>s]\r\n", I[l], re8_sprint(&amt;kv[8*l], str));
if ((flag[l] &amt; RE8_MODE_MASK) != RE8_MODE_SCALAR){
/* LVQ mode */
if (ni > 4) {
nk = (ni-4+1)/2; /* nkv*2 = number of 4-bit groups */
nk *= 2;
ni -= nk;
}
/* write base codebook index (in packet #p / overflow packet) */
index = I[l];
chk_ovf(n_bits, ni, &amt;n1, &amt;n2);
writ_I(n1, &amt;pos, &amt;index, parm);
n_bits -= 4*n1;
if (n2>0) {
/* write 4-bit groups in overflow packet */
pos_ovf = 0;
writ_I(n2, &amt;pos_ovf, &amt;index, parm_ovf);
/* distribute bits from overflow packet to packets
#0 to n_pack-1 */
writ_ovf(n_pack, parm_ovf, 4*n2, pos_i_ovf, pos_n, parm_ptr);
for (i=0; i<n2; i++) {
parm_ovf[i]=0;
}
}
if (nk>0) {
/* write table index (in packet #p / overflow packet) */
for (i=0; i<8; i++) {
k[i] = kv[8*l+i];
}
chk_ovf(n_bits, nk, &amt;n1, &amt;n2);
writ_k(n1, &amt;pos, k, parm, 0);
if (n2>0) {
pos_ovf = 0;
writ_k(n2, &amt;pos_ovf, k, parm_ovf,n1>2);
writ_ovf(n_pack, parm_ovf, 4*n2, pos_i_ovf, pos_n, parm_ptr);
for (i=0; i<n2; i++) {
parm_ovf[i]=0;
}
}
}
}else{
/* scalar quatizer, bits/digital in n, index in k[]*/
for (i=0; i<8; i++) {
k[i] = kv[8*l+i];
}
chk_ovf(n_bits, 2*nq[l], &amt;n1, &amt;n2);
writ_k(n1, &amt;pos, k, parm, 0);
if (n2>0) {
pos_ovf = 0;
writ_k(n2, &amt;pos_ovf, k, parm_ovf,n1>2);
writ_ovf(n_pack, parm_ovf, 4*n2, pos_i_ovf, pos_n, parm_ptr);
for (i=0; i<n2; i++) {
parm_ovf[i]=0;
}
}
}
}
}
}
}
#else
/* 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, &amt;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(&amt;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[]) */
RE8_cod(&amt;xriq[pos*8], &amt;nq[pos], &amt;I[pos], &amt;kv[8*pos]);
if (nq[pos]>0) {
k = pos_max;
if (pos > k) {
k = pos;
}
/* check for overflow and compute number of bits-1 (n) */
n = calc_bits(nq[pos]);
if ((n_bits+n+k) > NB_BITS) { /* if budget overflow */
nq[pos] = 0; /* force Q0 */
} else {
n_bits += n;
pos_max = k; /* update index of last described subvector (last) */
}
}
}
}
/*
writ_all_nq(n_pack, nq, pos_n, NB_BITS, last, parm_ptr)
ENCODE AND MULTIPLEX ALL CODEBOOKS NUMBERS IN nq[] TRACK-BY-TRACK
-> n_pack : number of packets
-> nq : table of codebook numbers [0..Nsv-1]
-> pos_n : table of pointers to write nq in packets [0..n_pack-1]
-> NB_BITS : total bit allocation
<- last : index of last subvector for which an index is written
<-> parm : bistream
*/
static void writ_all_nq(int n_pack, int *nq, int *pos_n, int NB_BITS, int Nsv, int *last, int **parm_ptr)
{
int p, pos, l, i, n_bits, *parm;
n_bits = NB_BITS;
*last = -1;
/* write nq[l] for l=0...Nsv-1 in packet #p= mod(l,number_of_packets)*/
for (l=0;l<Nsv;l++) {
p = l>n_pack; /* alternative : apply mask 0x01 / 0x03 */
parm = parm_ptr[p];
pos = pos_n[p];
/* compute the minimal bit budget to write nq[l] and the related index */
i = calc_bits(nq[l]);
/* if the budget is exceeded, force nq[l] to 0
else decrement the number of left bits */
if (i > n_bits) {
nq[l] = 0;
} else {
n_bits -= i;
}
/* update "last" */
if (nq[l] >= 2) {
*last=l;
}
/* write the unary code (except stop bit) for nq[l] in packet #p */
i = nq[l] - 1;
while (i-- > 0) {
parm[pos/4] += 1<<(pos>4);
pos--;
}
/* if bit budget is not empty, write stop bit of unary code */
if (n_bits > 0) {
pos--;
n_bits--;
}
pos_n[p] = pos;
}
return;
}
/* check if n groups of 4 bits fit in n_bits bits */
static void chk_ovf(int n_bits, int n, int *n1, int *n2)
{
if (4*n<=n_bits) {
*n1=n;
*n2=0;
} else {
*n1=n_bits/4; /* >> 2*/
*n2=n-*n1;
}
}
/* write n groups of 4-bit for base codebook index (I) */
static void writ_I(int n, int *pos_i, long *I, int *parm)
{
int pos;
/* base codebook index */
pos = *pos_i/4;
while (n-- > 0) {
parm[pos++] = (*I &amt; 0x0F);
*I = *I>>4;
}
*pos_i=pos*4;
}
/* write n groups of 4-bit for Voronoi index (k[]) */
static void writ_k(int n, int *pos_i, int *k, int *parm, int flag)
{
int i, ival, delta, *kv, pos;
delta = 4*flag;
pos = *pos_i/4;
while (n-- > 0) {
kv=k+delta;
ival = 0;
for (i=0; i<4; i++) {
ival <<= 1;
ival += (kv[i] &amt; 0x01);
kv[i] >>= 1;
}
parm[pos++] = ival;
delta = (delta+4)>8; /* circular shift */
}
*pos_i=pos*4;
}
/* find in each packet the positions where overflow occurs */
static void init_pos_i_ovf(int n_pack, int *nq, int *pos_n, int last, int *pos_i_ovf)
{
int p, pos, n_bits, l, n1, n2;
for (p=0; p<n_pack; p++) {
pos = 0;
n_bits = pos_n[p]+1; /* pos_n[p] - 0 +1 */
for (l=p; l<=last; l+=n_pack) {
if (nq[l] > 0) {
chk_ovf(n_bits, nq[l], &amt;n1, &amt;n2);
n_bits -= 4*n1;
pos += n1;
}
}
pos_i_ovf[p] = pos*4;
}
}
/* write bits in overflow */
static void writ_ovf(int n_pack, int *parm_ovf, int n, int *pos_i_ovf, int *pos_n, int **parm_ptr)
{
int pos_ovf, p, n_bits, pos, *parm, moved_bit;
/* initialize position in overflow packet (parm_ovf[]) */
pos_ovf=0;
/* move bits from overflow packet (parm_ovf[]) to packets (parm_ptr[][])
[write 4-bit by 4-bit] */
for (p=0; p<n_pack; p++) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos_i_ovf[p]+1;
if ((n_bits >= 4) &amt;&amt; (n>0)) {
pos=pos_i_ovf[p]/4;
parm = parm_ptr[p];
do {
parm[pos++]=parm_ovf[pos_ovf++]; /* move 4 bits */
n_bits -= 4;
n -= 4;
} while ((n_bits>=4) &amt;&amt; (n>0));
pos_i_ovf[p]=pos*4;
}
}
pos_ovf *=4;
/* move bits remaining in overflow packet
[write bit-by-bit (3 bits at maximum per packet)] */
for (p=0; p<n_pack; p++) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos_i_ovf[p]+1;
if ((n_bits > 0) &amt;&amt; (n>0)) {
pos = pos_i_ovf[p];
parm = parm_ptr[p];
do {
/* write a single bit */
moved_bit = (parm_ovf[pos_ovf/4] >> (pos_ovf>4)) &amt; 0x01;
parm[pos/4] += moved_bit<<(pos>4);
pos++;
pos_ovf++;
n_bits--;
n--;
} while ((n_bits > 0) &amt;&amt; (n > 0));
pos_i_ovf[p] = pos;
}
}
}
/*
writ_all_i(nq, p, pos_n, n_pack, last, pos_ovf, n_bits_left, parm_ptr)
MULTIPLEX AN INDEX (I,kv) OF 4*nq BITS INTO BITSTREAM
(THE INDEX CORRESPONDS TO A SUBVECTOR IN TRACK #p)
-> nq : codebook number (scalar)
-> p : index of track
-> pos_i : pointer to write i in packet [0..n_pack-1]
-> n_pack : number of packets
<-> pos_ovf : pointers for overflow [0..n_pack-1]
<-> n_bits_left : number of unused bits in packets [0..n_pack-1]
-> I : base codebook index
-> kv : Voronoi index
<-> parm : bistream [initialized to zero when writ_all_i is called]
important note:
- if the index fits completely in packet #p, multiplexing is done as
in writ_parm from top to bottom:
the 1st bit of I is written at the top
the last bit of kv at the bottom
*/
static void writ_all_i(int n_pack, int *nq, int *pos_n, int last, long *I, int *kv, int **parm_ptr)
{
int pos_ovf, p, l, n_bits, ni, nk, n1, i, n2, pos, k[8], *parm;
long index;
int parm_ovf[NQ_MAX];
int pos_i_ovf[N_PACK_MAX];
/* initialize overflow packet */
for (i=0; i<NQ_MAX; i++) {
parm_ovf[i]=0;
}
/* find positions in each packet from which the bits in overflow can be
written */
init_pos_i_ovf(n_pack, nq, pos_n, last, pos_i_ovf);
/* write indices */
for (p=0; p<n_pack; p++) {
pos = 0;
parm = parm_ptr[p];
for (l=p; l<=last; l+=n_pack) {
if (nq[l] > 0) {
/* compute number of bits left in packet #p */
n_bits = pos_n[p]-pos+1;
/* compute number of 4-bit groups for base codebook index (ni)
and Voronoi index (nk) */
ni=nq[l];
nk = 0;
if (ni > 4) {
nk = (ni-4+1)/2; /* nkv*2 = number of 4-bit groups */
nk *= 2;
ni -= nk;
}
/* write base codebook index (in packet #p / overflow packet) */
index = I[l];
chk_ovf(n_bits, ni, &amt;n1, &amt;n2);
writ_I(n1, &amt;pos, &amt;index, parm);
n_bits -= 4*n1;
if (n2>0) {
/* write 4-bit groups in overflow packet */
pos_ovf = 0;
writ_I(n2, &amt;pos_ovf, &amt;index, parm_ovf);
/* distribute bits from overflow packet to packets
#0 to n_pack-1 */
writ_ovf(n_pack, parm_ovf, 4*n2, pos_i_ovf, pos_n, parm_ptr);
for (i=0; i<n2; i++) {
parm_ovf[i]=0;
}
}
if (nk>0) {
/* write Voronoi index (in packet #p / overflow packet) */
for (i=0; i<8; i++) {
k[i] = kv[8*l+i];
}
chk_ovf(n_bits, nk, &amt;n1, &amt;n2);
writ_k(n1, &amt;pos, k, parm, 0);
if (n2>0) {
pos_ovf = 0;
writ_k(n2, &amt;pos_ovf, k, parm_ovf,n1>2);
writ_ovf(n_pack, parm_ovf, 4*n2, pos_i_ovf, pos_n, parm_ptr);
for (i=0; i<n2; i++) {
parm_ovf[i]=0;
}
}
}
}
}
}
}
#endif