• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ** Copyright 2003-2010, VisualOn, Inc.
3  **
4  ** Licensed under the Apache License, Version 2.0 (the "License");
5  ** you may not use this file except in compliance with the License.
6  ** You may obtain a copy of the License at
7  **
8  **     http://www.apache.org/licenses/LICENSE-2.0
9  **
10  ** Unless required by applicable law or agreed to in writing, software
11  ** distributed under the License is distributed on an "AS IS" BASIS,
12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  ** See the License for the specific language governing permissions and
14  ** limitations under the License.
15  */
16 
17 /************************************************************************
18 *      File: c2t64fx.c                                                  *
19 *                                                                       *
20 *      Description:Performs algebraic codebook search for 6.60kbits mode*
21 *                                                                       *
22 *************************************************************************/
23 
24 #include "typedef.h"
25 #include "basic_op.h"
26 #include "math_op.h"
27 #include "acelp.h"
28 #include "cnst.h"
29 
30 #define NB_TRACK  2
31 #define STEP      2
32 #define NB_POS    32
33 #define MSIZE     1024
34 
35 /*************************************************************************
36 * Function:  ACELP_2t64_fx()                                             *
37 *                                                                        *
38 * 12 bits algebraic codebook.                                            *
39 * 2 tracks x 32 positions per track = 64 samples.                        *
40 *                                                                        *
41 * 12 bits --> 2 pulses in a frame of 64 samples.                         *
42 *                                                                        *
43 * All pulses can have two (2) possible amplitudes: +1 or -1.             *
44 * Each pulse can have 32 possible positions.                             *
45 **************************************************************************/
46 
ACELP_2t64_fx(Word16 dn[],Word16 cn[],Word16 H[],Word16 code[],Word16 y[],Word16 * index)47 void ACELP_2t64_fx(
48         Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */
49         Word16 cn[],                          /* (i) <12b : residual after long term prediction         */
50         Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */
51         Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */
52         Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */
53         Word16 * index                        /* (o) : index (12): 5+1+5+1 = 11 bits.                   */
54         )
55 {
56     Word32 i, j, k, i0, i1, ix, iy, pos, pos2;
57     Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;
58     Word16 alp, val, exp, k_cn, k_dn;
59     Word16 *p0, *p1, *p2, *psign;
60     Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;
61 
62     Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];
63     Word16 h_buf[4 * L_SUBFR] = {0};
64     Word16 rrixix[NB_TRACK][NB_POS];
65     Word16 rrixiy[MSIZE];
66     Word32 s, cor;
67 
68     /*----------------------------------------------------------------*
69      * Find sign for each pulse position.                             *
70      *----------------------------------------------------------------*/
71     alp = 8192;                              /* alp = 2.0 (Q12) */
72 
73     /* calculate energy for normalization of cn[] and dn[] */
74     /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
75 #ifdef ASM_OPT             /* asm optimization branch */
76     s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);
77 #else
78     s = Dot_product12(cn, cn, L_SUBFR, &exp);
79 #endif
80 
81     Isqrt_n(&s, &exp);
82     s = L_shl(s, add1(exp, 5));
83     if (s > INT_MAX - 0x8000) {
84         s = INT_MAX - 0x8000;
85     }
86     k_cn = vo_round(s);
87 
88     /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
89 #ifdef ASM_OPT                  /* asm optimization branch */
90     s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);
91 #else
92     s = Dot_product12(dn, dn, L_SUBFR, &exp);
93 #endif
94 
95     Isqrt_n(&s, &exp);
96     k_dn = voround(L_shl(s, (exp + 8)));    /* k_dn = 256..4096 */
97     k_dn = vo_mult_r(alp, k_dn);              /* alp in Q12 */
98 
99     /* mix normalized cn[] and dn[] */
100     p0 = cn;
101     p1 = dn;
102     p2 = dn2;
103 
104     for (i = 0; i < L_SUBFR/4; i++)
105     {
106         s = (k_cn* (*p0++))+(k_dn * (*p1++));
107         *p2++ = s >> 7;
108         s = (k_cn* (*p0++))+(k_dn * (*p1++));
109         *p2++ = s >> 7;
110         s = (k_cn* (*p0++))+(k_dn * (*p1++));
111         *p2++ = s >> 7;
112         s = (k_cn* (*p0++))+(k_dn * (*p1++));
113         *p2++ = s >> 7;
114     }
115 
116     /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[]    */
117     for (i = 0; i < L_SUBFR; i ++)
118     {
119         val = dn[i];
120         ps = dn2[i];
121         if (ps >= 0)
122         {
123             sign[i] = 32767;             /* sign = +1 (Q12) */
124             vec[i] = -32768;
125         } else
126         {
127             sign[i] = -32768;            /* sign = -1 (Q12) */
128             vec[i] = 32767;
129             dn[i] = -val;
130         }
131     }
132     /*------------------------------------------------------------*
133      * Compute h_inv[i].                                          *
134      *------------------------------------------------------------*/
135     /* impulse response buffer for fast computation */
136     h = h_buf + L_SUBFR;
137     h_inv = h + (L_SUBFR<<1);
138 
139     for (i = 0; i < L_SUBFR; i++)
140     {
141         h[i] = H[i];
142         h_inv[i] = vo_negate(h[i]);
143     }
144 
145     /*------------------------------------------------------------*
146      * Compute rrixix[][] needed for the codebook search.         *
147      * Result is multiplied by 0.5                                *
148      *------------------------------------------------------------*/
149     /* Init pointers to last position of rrixix[] */
150     p0 = &rrixix[0][NB_POS - 1];
151     p1 = &rrixix[1][NB_POS - 1];
152 
153     ptr_h1 = h;
154     cor = 0x00010000L;                          /* for rounding */
155     for (i = 0; i < NB_POS; i++)
156     {
157         cor += ((*ptr_h1) * (*ptr_h1) << 1);
158         ptr_h1++;
159         *p1-- = (extract_h(cor) >> 1);
160         cor += ((*ptr_h1) * (*ptr_h1) << 1);
161         ptr_h1++;
162         *p0-- = (extract_h(cor) >> 1);
163     }
164 
165     /*------------------------------------------------------------*
166      * Compute rrixiy[][] needed for the codebook search.         *
167      *------------------------------------------------------------*/
168     pos = MSIZE - 1;
169     pos2 = MSIZE - 2;
170     ptr_hf = h + 1;
171 
172     for (k = 0; k < NB_POS; k++)
173     {
174         p1 = &rrixiy[pos];
175         p0 = &rrixiy[pos2];
176         cor = 0x00008000L;                        /* for rounding */
177         ptr_h1 = h;
178         ptr_h2 = ptr_hf;
179 
180         for (i = (k + 1); i < NB_POS; i++)
181         {
182             cor += ((*ptr_h1) * (*ptr_h2))<<1;
183             ptr_h1++;
184             ptr_h2++;
185             *p1 = extract_h(cor);
186             cor += ((*ptr_h1) * (*ptr_h2))<<1;
187             ptr_h1++;
188             ptr_h2++;
189             *p0 = extract_h(cor);
190 
191             p1 -= (NB_POS + 1);
192             p0 -= (NB_POS + 1);
193         }
194         cor += ((*ptr_h1) * (*ptr_h2))<<1;
195         ptr_h1++;
196         ptr_h2++;
197         *p1 = extract_h(cor);
198 
199         pos -= NB_POS;
200         pos2--;
201         ptr_hf += STEP;
202     }
203 
204     /*------------------------------------------------------------*
205      * Modification of rrixiy[][] to take signs into account.     *
206      *------------------------------------------------------------*/
207     p0 = rrixiy;
208     for (i = 0; i < L_SUBFR; i += STEP)
209     {
210         psign = sign;
211         if (psign[i] < 0)
212         {
213             psign = vec;
214         }
215         for (j = 1; j < L_SUBFR; j += STEP)
216         {
217             *p0 = vo_mult(*p0, psign[j]);
218             p0++;
219         }
220     }
221     /*-------------------------------------------------------------------*
222      * search 2 pulses:                                                  *
223      * ~@~~~~~~~~~~~~~~                                                  *
224      * 32 pos x 32 pos = 1024 tests (all combinaisons is tested)         *
225      *-------------------------------------------------------------------*/
226     p0 = rrixix[0];
227     p1 = rrixix[1];
228     p2 = rrixiy;
229 
230     psk = -1;
231     alpk = 1;
232     ix = 0;
233     iy = 1;
234 
235     for (i0 = 0; i0 < L_SUBFR; i0 += STEP)
236     {
237         ps1 = dn[i0];
238         alp1 = (*p0++);
239         pos = -1;
240         for (i1 = 1; i1 < L_SUBFR; i1 += STEP)
241         {
242             ps2 = add1(ps1, dn[i1]);
243             alp2 = add1(alp1, add1(*p1++, *p2++));
244             sq = vo_mult(ps2, ps2);
245             s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1);
246             if (s > 0)
247             {
248                 psk = sq;
249                 alpk = alp2;
250                 pos = i1;
251             }
252         }
253         p1 -= NB_POS;
254         if (pos >= 0)
255         {
256             ix = i0;
257             iy = pos;
258         }
259     }
260     /*-------------------------------------------------------------------*
261      * Build the codeword, the filtered codeword and index of codevector.*
262      *-------------------------------------------------------------------*/
263 
264     for (i = 0; i < L_SUBFR; i++)
265     {
266         code[i] = 0;
267     }
268 
269     i0 = (ix >> 1);                       /* pos of pulse 1 (0..31) */
270     i1 = (iy >> 1);                       /* pos of pulse 2 (0..31) */
271     if (sign[ix] > 0)
272     {
273         code[ix] = 512;                     /* codeword in Q9 format */
274         p0 = h - ix;
275     } else
276     {
277         code[ix] = -512;
278         i0 += NB_POS;
279         p0 = h_inv - ix;
280     }
281     if (sign[iy] > 0)
282     {
283         code[iy] = 512;
284         p1 = h - iy;
285     } else
286     {
287         code[iy] = -512;
288         i1 += NB_POS;
289         p1 = h_inv - iy;
290     }
291     *index = add1((i0 << 6), i1);
292     for (i = 0; i < L_SUBFR; i++)
293     {
294         y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3);
295     }
296     return;
297 }
298 
299 
300 
301