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#include #include #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 point[0]) { if (tmp
1&&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 & 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 & RE8_EVEN_FLAG) *header |= (1<<2); *header |= (n-6); break; case RE8_MODE_BASE: if (flag & RE8_SPEC_FLAG && n == 4){ /* special leader in base codebook: n = 111111 10*/ *header = 0xFE<<1; hd_len = 9; if (flag & 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 & RE8_EVEN_FLAG) *header = *header + 1; } } break; case RE8_MODE_EXT1: if (flag & RE8_SPEC_FLAG && 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 & RE8_EVEN_FLAG) *header = *header + 1; break; case RE8_MODE_EXT2: if (flag & RE8_SPEC_FLAG && 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 & RE8_EVEN_FLAG) *header = *header + 1; break; case RE8_MODE_EXT3: if (flag & RE8_SPEC_FLAG && 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 & 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 = 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 tmp) tmp = ebits[l]; tmp = tmp - 10.0f; if (offset < tmp) offset = tmp; #endif for (l=Nsv/2; l 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 = 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 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 = 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 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 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, &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 & 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 & RE8_SPEC_FLAG && 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 & RE8_SPEC_FLAG && 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 & RE8_SPEC_FLAG && 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 & RE8_SPEC_FLAG && 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 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(&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 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], &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(&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 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], &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 & 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] & 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 0) { ni=nq[l]; if(ni==2&&cache_hit[l]) ni=ni-1; chk_ovf(n_bits, ni, &n1, &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 = 4) && (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) && (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 0) && (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)) & 0x01; parm[pos/4] += moved_bit<<(pos%4); pos++; pos_ovf++; n_bits--; n--; } while ((n_bits > 0) && (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 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&&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(&kv[8*l], str)); if ((flag[l] & 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, &n1, &n2); writ_I(n1, &pos, &index, parm); n_bits -= 4*n1; if (n2>0) { /* write 4-bit groups in overflow packet */ pos_ovf = 0; writ_I(n2, &pos_ovf, &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 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, &n1, &n2); writ_k(n1, &pos, k, parm, 0); if (n2>0) { pos_ovf = 0; writ_k(n2, &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 0) { pos_ovf = 0; writ_k(n2, &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 = 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 tmp) tmp = ebits[l]; tmp = tmp - 10.0f; if (offset < tmp) offset = tmp; #endif for (l=Nsv/2; l 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 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 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 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 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 & 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] & 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 0) { chk_ovf(n_bits, nq[l], &n1, &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 = 4) && (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) && (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 0) && (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)) & 0x01; parm[pos/4] += moved_bit<<(pos%4); pos++; pos_ovf++; n_bits--; n--; } while ((n_bits > 0) && (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 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, &n1, &n2); writ_I(n1, &pos, &index, parm); n_bits -= 4*n1; if (n2>0) { /* write 4-bit groups in overflow packet */ pos_ovf = 0; writ_I(n2, &pos_ovf, &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 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, &n1, &n2); writ_k(n1, &pos, k, parm, 0); if (n2>0) { pos_ovf = 0; writ_k(n2, &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