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