www.pudn.com > AVS_M_ver10.rar > re8_vor.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. ************************************************************************ */ #include#include #include #include #include "../include/amr_plus.h" #ifdef NEW_TVC static int re8_identify_absolute_leader(int y[], int* spec_flag); static int re8_in_base_codebook(int y[], int* n, int* ka, int* spec_flag); //static int re8_try_factor(int y[], int* adj_y, int* factor, int* n, int* ka, int* spec_flag); //static int re8_in_lattice(int y[]); //static char* re8_sprint(int y[], char* str); //static void re8_special_leader_revert(int src[], int dest[]); /* special leader revert from (3,3,3,3,3,3,1,1,1) and (3,3,3,3,3,3,3,1,1) * to (1,1,1,1,1,3,3,3) and (1,1,1,1,1,1,1,3,3) */ void re8_special_leader_revert(int src [ ], int dest [ ]) { int i; for (i = 0; i < 8; i++){ if (src[i] % 3 == 0){ dest[i] = src[i] / 3; }else{ dest[i] = src[i] * 3; } } } char* re8_sprint(int y [ ], char* str) { sprintf(str, "%3d %3d %3d %3d %3d %3d %3d %3d", y[0],y[1],y[2],y[3],y[4],y[5],y[6],y[7]); return str; } /*-------------------------------------------------------------- re8_in_base_codebook(y,n,ka,spec_flag) INQUIRY WHETHER RE8 LATTICE IN BASECODEBOOK (i) y: point in R^8 (o)n: basebook number (o)ka: index of absolute leader (o)spec_flag: flag to indicate special leader -------------------------------------------------------------- */ int re8_in_base_codebook(int y [ ], int* n , int* ka, int* spec_flag) { int ka_tmp, n_tmp; int *np, *kap; if (!n) np = &n_tmp; else np = n; if (!ka) kap = &ka_tmp; else kap = ka; *kap = re8_identify_absolute_leader(y, spec_flag); *np = Da_nq[*kap]; return ((*np <= 4)); } /*-------------------------------------------------------------- RE8_vor(y,n,k,c,ka, flag) MULTI-RATE RE8 INDEXING BY VORONOI EXTENSION (i) y : point in RE8 (8-dimensional integer vector) (o) n : codebook number n=0,2,3,4,... (scalar integer) (o) k : Voronoi index (integer vector of dimension 8) used only if n>4 (o) c : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c (o) ka: identifier of absolute leader (needed to index c) (o) flag: mode flag to decide encoding method. --------------------------------------------------------------- */ void RE8_vor(int y[], int *n, int k[], int c[], int *ka, int* flag) { int i,r,t[8]; int even_flag = 0, spec_flag = 0; //char str[35]; *flag = 0; if (re8_in_base_codebook(y, n, ka, &spec_flag)){ for (i=0;i<8;i++){ c[i] = y[i]; } *flag = RE8_MODE_BASE; goto END; } else { /* adjust even point to odd point */ if (y[0] % 2 == 0){ /* even point */ even_flag = 1; for (i=0; i < 8; i++){ t[i] = y[i] -1; } }else{ /* odd point */ even_flag = 0; for (i = 0; i < 8; i++){ t[i] = y[i]; } } if (even_flag == 1){ /* test adjusted even point in base codebook Q4 */ if (re8_in_base_codebook(t, n, ka, &spec_flag)){ if (*n == 4){ for (i=0;i<8;i++){ c[i] = t[i]; } *flag = RE8_MODE_BASE; goto END; } } } #if 0 /* decide the factor if needed */ res = re8_try_factor(t, c, factor, n, ka, &spec_flag); if (res == FACTOR_SUCCESS){ *flag = RE8_MODE_FAC; goto END; } #endif for (r = 0; r < 3; r++){ int maxi = tab_pow2[6-r]; for (i = 0; i < 8; i ++){ if (t[i] > 0){ k[i] = ((t[i]/4) 7)?7 : k[i]; } if (re8_in_base_codebook(c, n, ka, &spec_flag)){ *flag = r + RE8_MODE_EXT; goto END; } } } if (r >= 3){ *flag = RE8_MODE_SCALAR; // printf("can't find [%s] in base codebook!!\r\n", // re8_sprint(y, str)); } END: if (even_flag) *flag |= RE8_EVEN_FLAG; if (spec_flag) *flag |= RE8_SPEC_FLAG; return; } /*------------------------------------------------------------------------- re8_identify_absolute_leader(y) IDENTIFY THE ABSOLUTE LEADER RELATED TO y USING A PRE-DEFINED TABLE WHICH SPECIFIES THE CODEBOOKS Q0, Q2, Q3 and Q4 (i) y : point in RE8 (8-dimensional integer vector) (o) spec_flag: special leader flag. (o) returned value = integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) --------------------------------------------------------------- */ int re8_identify_absolute_leader(int y[], int* spec_flag) { int i,s,id,C[8],nb,pos,ka,flag=0; long tmp; *spec_flag = 0; /* compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2) */ for (i=0;i<8;i++) { C[i] = y[i]*y[i]; } s=0; for (i=0;i<8;i++) { s += C[i]; } if (s==4) flag=1; s >>= 3; /* compute the index 0<= ka <= NB_LEADER+1 which identifies an absolute leader of Q0, Q2, Q3 or Q4 */ ka = NB_LEADER+1; /* by default, ka=index of last element of the table (to indicate an outlier) */ if (s == 0) { if (flag) ka=0; /* if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0 */ else ka = NB_LEADER; } else { /* the maximal value of s for y in Q0, Q2, Q3 or Q4 is NB_SPHERE if s> NB_SPHERE, y is an outlier (the value of ka is set correctly) */ if (s <= NB_SPHERE) { /* compute the unique identifier id of the absolute leader related to y: s = (y1^4 + ... + y8^4)/8 */ tmp=0; for (i=0;i<8;i++) { tmp += C[i]*C[i]; } id = (int)(tmp >> 2); /* test if it's special leader (3,3,3,3,3,1,1,1) and (3,3,3,3,3,3,1,1) */ if (id == Da_id[NB_LEADER]){ ka = SPECIAL1_POS; re8_special_leader_revert(y, y); *spec_flag = RE8_SPEC_FLAG; return ka; }else if (id == Da_id[NB_LEADER+1]){ ka = SPECIAL2_POS; re8_special_leader_revert(y, y); *spec_flag = RE8_SPEC_FLAG; return ka; } /* search for id in table Da_id (containing all possible values of id if y is in Q2, Q3 or Q4) this search is focused based on the shell number s so that only the id's related to the shell of number s are checked */ nb = Da_nb[s-1]; /* get the number of absolute leaders used on the shell of number s */ pos = Da_pos[s-1]; /* get the position of the first absolute leader of shell s in Da_id */ for (i=0; i 4 (o) c : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c (o) ka: identifier of absolute leader (needed to index c) --------------------------------------------------------------- */ void RE8_vor(int y[], int *n, int k[], int c[], int *ka) { int i,r,m,v[8],c_tmp[8],k_mod[8],k_tmp[8],iter,ka_tmp,n_tmp,mask; float sphere; /* verify if y is in Q0, Q2, Q3 or Q4 (a fast search is used here: the codebooks Q0, Q2, Q3 or Q4 are specified in terms of RE8 absolute leaders - a unique code identifying the absolute leader related to y is computed in re8_identify_absolute_leader() this code is searched for in a pre-defined list which specifies Q0, Q2, Q3 or Q4) the absolute leader is identified by ka - a translation table maps ka to the codebook number n) */ *ka = re8_identify_absolute_leader(y); /* compute codebook number n of Qn (by table look-up) at this stage, n=0,2,3,4 or out=100 */ *n = Da_nq[*ka]; /* decompose y into : (if n<=4:) y = c where c is in Q0, Q2, Q3 or Q4 or (if n>4:) y = m c + v where c is in Q3 or Q4, v is a Voronoi codevector m=2^r (r integer >=2) in the latter case (if n>4), as a side-product, compute the (Voronoi) index k[] of v and replace n by n = n' + 2r where n' = 3 or 4 (c is in Qn') and r is defined above */ if (*n <= 4) { for (i=0;i<8;i++) { c[i] = y[i]; } } else { /* initialize r and m=2^r based on || y ||^2/8 */ sphere = 0.0; for (i=0;i<8;i++) { sphere += (float)y[i]*(float)y[i]; } sphere *= 0.125; r = 1; sphere *= 0.25; /* not counted, merge 0.125*0.25 */ while (sphere > 11.0) { r++; sphere *= 0.25; } /* compute the coordinates of y in the RE8 basis */ re8_coord(y, k_mod); /* compute m and the mask needed for modulo m (for Voronoi coding) */ m = 1< 4) { /* if c is not in Q2, Q3, or Q4 (i.e. n_tmp>4), use m = 2^(r+1) instead of 2^r */ r++; m = m<<1; mask = ((mask<<1)+1); /* mask = m-1; <- this is less complex */ } else { /* c is in Q2, Q3, or Q4 -> the decomposition of y as y = m c + v is valid since Q2 is a subset of Q3, indicate n=3 instead of n=2 (this is because for n>4, n=n'+2r with n'=3 or 4, so n'=2 is not valid) */ if (n_tmp < 3) { n_tmp = 3; } /* save current values into ka, n, k and c */ *ka = ka_tmp; *n = n_tmp + 2*r; for (i=0; i<8; i++) { k[i] = k_tmp[i]; } for (i=0; i<8; i++) { c[i] = c_tmp[i]; } /* try m = 2^(r-1) instead of 2^r to be sure that m is minimal */ r--; m = m>>1; mask = mask>>1; } } } return; } /*------------------------------------------------------------------------- re8_identify_absolute_leader(y) IDENTIFY THE ABSOLUTE LEADER RELATED TO y USING A PRE-DEFINED TABLE WHICH SPECIFIES THE CODEBOOKS Q0, Q2, Q3 and Q4 (i) y : point in RE8 (8-dimensional integer vector) (o) returned value = integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) --------------------------------------------------------------- */ int re8_identify_absolute_leader(int y[]) { int i,s,id,C[8],nb,pos,ka; long tmp; /* compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2) */ for (i=0;i<8;i++) { C[i] = y[i]*y[i]; } s=0; for (i=0;i<8;i++) { s += C[i]; } s >>= 3; /* compute the index 0<= ka <= NB_LEADER+1 which identifies an absolute leader of Q0, Q2, Q3 or Q4 */ ka = NB_LEADER+1; /* by default, ka=index of last element of the table (to indicate an outlier) */ if (s == 0) { /* if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0 */ ka = NB_LEADER; } else { /* the maximal value of s for y in Q0, Q2, Q3 or Q4 is NB_SPHERE if s> NB_SPHERE, y is an outlier (the value of ka is set correctly) */ if (s <= NB_SPHERE) { /* compute the unique identifier id of the absolute leader related to y: s = (y1^4 + ... + y8^4)/8 */ tmp=0; for (i=0;i<8;i++) { tmp += C[i]*C[i]; } id = (int)(tmp >> 3); /* search for id in table Da_id (containing all possible values of id if y is in Q2, Q3 or Q4) this search is focused based on the shell number s so that only the id's related to the shell of number s are checked */ nb = Da_nb[s-1]; /* get the number of absolute leaders used on the shell of number s */ pos = Da_pos[s-1]; /* get the position of the first absolute leader of shell s in Da_id */ for (i=0; i > 2; *ptr_k++ = s; } } /* re8_y2k(y,m,k) VORONOI INDEXING (INDEX DECODING) k -> y (i) k: Voronoi index k[0..7] (i) m: Voronoi modulo (m = 2^r = 1< =2) (o) y: 8-dimensional point y[0..7] in RE8 */ void re8_k2y(int *k, int m, int *y) { int i,j,*ptr_y, *ptr_M, *ptr_a, *ptr_k, *ptr_v, v[8], s; float z[8], *ptr_z; /* compute y = k M and z=(y-a)/m */ ptr_M = M_RE8; ptr_y = y; ptr_a = a; ptr_z = z; for (i=0; i<8; i++) { /* compute y_i = k * M(:,i)*/ ptr_k = k; s = 0; for (j=0; j<8; j++) { s+= *ptr_k++ * *ptr_M++; } *ptr_y++ = s; /* compute z_i = (y_i-a_i)/m */ s = s - *ptr_a++; *ptr_z++ = (float)s/(float)m; } /* find nearest neighbor v of z in infinite RE8 */ RE8_PPV(z,v); /* compute y -= m v */ ptr_y=y; ptr_v=v; for (i=0; i<8; i++) { *ptr_y++ -= m * *ptr_v++; } } #else /*---------- #ifdef DSP_OPTIMIZED ----------*/ /* re8_coord(y,k) COMPUTATION OF RE8 COORDINATES (i) y: 8-dimensional point y[0..7] in RE8 (o) k: coordinates k[0..7] */ void re8_coord(int *y, int *k) { int i, tmp, sum; /* compute k = y M^-1 M = 1/4 [ 1 ] [-1 2 ] [ | \ ] [-1 2 ] [ 5 -2 _ -2 4] */ k[7]=y[7]; tmp = y[7]; sum = 5*y[7]; for (i=6; i>=1; i--) { /* apply factor 2/4 from M^-1 */ k[i] = (y[i]-tmp)>>1; sum -= y[i]; } /* apply factor 1/4 from M^-1 */ k[0]=(y[0]+sum)>>2; } /* re8_y2k(y,m,k) VORONOI INDEXING (INDEX DECODING) k -> y (i) k: Voronoi index k[0..7] (i) m: Voronoi modulo (m = 2^r = 1< =2) (o) y: 8-dimensional point y[0..7] in RE8 */ void re8_k2y(int *k, int m, int *y) { int i, v[8], tmp, sum, *ptr1, *ptr2; float z[8]; /* compute y = k M and z=(y-a)/m, where M = [4 ] [2 2 ] [| \ ] [2 2 ] [1 1 _ 1 1] a=(2,0,...,0) */ for (i=0; i<8; i++) { y[i] = k[7]; } z[7] = (float)y[7]/m; sum=0; for (i=6; i>=1; i--) { tmp = 2*k[i]; sum += tmp; y[i] += tmp; z[i] = (float)y[i]/m; } y[0] += (4*k[0] + sum); z[0] = (float)(y[0]-2)/m; /* find nearest neighbor v of z in infinite RE8 */ RE8_PPV(z,v); /* compute y -= m v */ ptr1=y; ptr2=v; for (i=0; i<8; i++) { *ptr1++ -= m * *ptr2++; } } #endif #endif