c2t64fx.c revision 3cdaed88daeeebfe05e7913837f41c2d92f411cc
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
47// There are many integer overflows in this function, as none of them appear to
48// lead to memory accesses, and performing the appropriate checks will lead
49// to considerably larger code, mark this as ignore.
50__attribute__((no_sanitize("integer")))
51void ACELP_2t64_fx(
52		Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */
53		Word16 cn[],                          /* (i) <12b : residual after long term prediction         */
54		Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */
55		Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */
56		Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */
57		Word16 * index                        /* (o) : index (12): 5+1+5+1 = 11 bits.                   */
58		)
59{
60	Word32 i, j, k, i0, i1, ix, iy, pos, pos2;
61	Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;
62	Word16 alp, val, exp, k_cn, k_dn;
63	Word16 *p0, *p1, *p2, *psign;
64	Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;
65
66	Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];
67	Word16 h_buf[4 * L_SUBFR] = {0};
68	Word16 rrixix[NB_TRACK][NB_POS];
69	Word16 rrixiy[MSIZE];
70	Word32 s, cor;
71
72	/*----------------------------------------------------------------*
73	 * Find sign for each pulse position.                             *
74	 *----------------------------------------------------------------*/
75	alp = 8192;                              /* alp = 2.0 (Q12) */
76
77	/* calculate energy for normalization of cn[] and dn[] */
78	/* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
79#ifdef ASM_OPT             /* asm optimization branch */
80	s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);
81#else
82	s = Dot_product12(cn, cn, L_SUBFR, &exp);
83#endif
84
85	Isqrt_n(&s, &exp);
86	s = L_shl(s, add1(exp, 5));
87	k_cn = vo_round(s);
88
89	/* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
90#ifdef ASM_OPT                  /* asm optimization branch */
91	s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);
92#else
93	s = Dot_product12(dn, dn, L_SUBFR, &exp);
94#endif
95
96	Isqrt_n(&s, &exp);
97	k_dn = vo_round(L_shl(s, (exp + 8)));    /* k_dn = 256..4096 */
98	k_dn = vo_mult_r(alp, k_dn);              /* alp in Q12 */
99
100	/* mix normalized cn[] and dn[] */
101	p0 = cn;
102	p1 = dn;
103	p2 = dn2;
104
105	for (i = 0; i < L_SUBFR/4; i++)
106	{
107		s = (k_cn* (*p0++))+(k_dn * (*p1++));
108		*p2++ = s >> 7;
109		s = (k_cn* (*p0++))+(k_dn * (*p1++));
110		*p2++ = s >> 7;
111		s = (k_cn* (*p0++))+(k_dn * (*p1++));
112		*p2++ = s >> 7;
113		s = (k_cn* (*p0++))+(k_dn * (*p1++));
114		*p2++ = s >> 7;
115	}
116
117	/* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[]    */
118	for (i = 0; i < L_SUBFR; i ++)
119	{
120		val = dn[i];
121		ps = dn2[i];
122		if (ps >= 0)
123		{
124			sign[i] = 32767;             /* sign = +1 (Q12) */
125			vec[i] = -32768;
126		} else
127		{
128			sign[i] = -32768;            /* sign = -1 (Q12) */
129			vec[i] = 32767;
130			dn[i] = -val;
131		}
132	}
133	/*------------------------------------------------------------*
134	 * Compute h_inv[i].                                          *
135	 *------------------------------------------------------------*/
136	/* impulse response buffer for fast computation */
137	h = h_buf + L_SUBFR;
138	h_inv = h + (L_SUBFR<<1);
139
140	for (i = 0; i < L_SUBFR; i++)
141	{
142		h[i] = H[i];
143		h_inv[i] = vo_negate(h[i]);
144	}
145
146	/*------------------------------------------------------------*
147	 * Compute rrixix[][] needed for the codebook search.         *
148	 * Result is multiplied by 0.5                                *
149	 *------------------------------------------------------------*/
150	/* Init pointers to last position of rrixix[] */
151	p0 = &rrixix[0][NB_POS - 1];
152	p1 = &rrixix[1][NB_POS - 1];
153
154	ptr_h1 = h;
155	cor = 0x00010000L;                          /* for rounding */
156	for (i = 0; i < NB_POS; i++)
157	{
158		cor += ((*ptr_h1) * (*ptr_h1) << 1);
159		ptr_h1++;
160		*p1-- = (extract_h(cor) >> 1);
161		cor += ((*ptr_h1) * (*ptr_h1) << 1);
162		ptr_h1++;
163		*p0-- = (extract_h(cor) >> 1);
164	}
165
166	/*------------------------------------------------------------*
167	 * Compute rrixiy[][] needed for the codebook search.         *
168	 *------------------------------------------------------------*/
169	pos = MSIZE - 1;
170	pos2 = MSIZE - 2;
171	ptr_hf = h + 1;
172
173	for (k = 0; k < NB_POS; k++)
174	{
175		p1 = &rrixiy[pos];
176		p0 = &rrixiy[pos2];
177		cor = 0x00008000L;                        /* for rounding */
178		ptr_h1 = h;
179		ptr_h2 = ptr_hf;
180
181		for (i = (k + 1); i < NB_POS; i++)
182		{
183			cor += ((*ptr_h1) * (*ptr_h2))<<1;
184			ptr_h1++;
185			ptr_h2++;
186			*p1 = extract_h(cor);
187			cor += ((*ptr_h1) * (*ptr_h2))<<1;
188			ptr_h1++;
189			ptr_h2++;
190			*p0 = extract_h(cor);
191
192			p1 -= (NB_POS + 1);
193			p0 -= (NB_POS + 1);
194		}
195		cor += ((*ptr_h1) * (*ptr_h2))<<1;
196		ptr_h1++;
197		ptr_h2++;
198		*p1 = extract_h(cor);
199
200		pos -= NB_POS;
201		pos2--;
202		ptr_hf += STEP;
203	}
204
205	/*------------------------------------------------------------*
206	 * Modification of rrixiy[][] to take signs into account.     *
207	 *------------------------------------------------------------*/
208	p0 = rrixiy;
209	for (i = 0; i < L_SUBFR; i += STEP)
210	{
211		psign = sign;
212		if (psign[i] < 0)
213		{
214			psign = vec;
215		}
216		for (j = 1; j < L_SUBFR; j += STEP)
217		{
218			*p0 = vo_mult(*p0, psign[j]);
219			p0++;
220		}
221	}
222	/*-------------------------------------------------------------------*
223	 * search 2 pulses:                                                  *
224	 * ~@~~~~~~~~~~~~~~                                                  *
225	 * 32 pos x 32 pos = 1024 tests (all combinaisons is tested)         *
226	 *-------------------------------------------------------------------*/
227	p0 = rrixix[0];
228	p1 = rrixix[1];
229	p2 = rrixiy;
230
231	psk = -1;
232	alpk = 1;
233	ix = 0;
234	iy = 1;
235
236	for (i0 = 0; i0 < L_SUBFR; i0 += STEP)
237	{
238		ps1 = dn[i0];
239		alp1 = (*p0++);
240		pos = -1;
241		for (i1 = 1; i1 < L_SUBFR; i1 += STEP)
242		{
243			ps2 = add1(ps1, dn[i1]);
244			alp2 = add1(alp1, add1(*p1++, *p2++));
245			sq = vo_mult(ps2, ps2);
246			s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1);
247			if (s > 0)
248			{
249				psk = sq;
250				alpk = alp2;
251				pos = i1;
252			}
253		}
254		p1 -= NB_POS;
255		if (pos >= 0)
256		{
257			ix = i0;
258			iy = pos;
259		}
260	}
261	/*-------------------------------------------------------------------*
262	 * Build the codeword, the filtered codeword and index of codevector.*
263	 *-------------------------------------------------------------------*/
264
265	for (i = 0; i < L_SUBFR; i++)
266	{
267		code[i] = 0;
268	}
269
270	i0 = (ix >> 1);                       /* pos of pulse 1 (0..31) */
271	i1 = (iy >> 1);                       /* pos of pulse 2 (0..31) */
272	if (sign[ix] > 0)
273	{
274		code[ix] = 512;                     /* codeword in Q9 format */
275		p0 = h - ix;
276	} else
277	{
278		code[ix] = -512;
279		i0 += NB_POS;
280		p0 = h_inv - ix;
281	}
282	if (sign[iy] > 0)
283	{
284		code[iy] = 512;
285		p1 = h - iy;
286	} else
287	{
288		code[iy] = -512;
289		i1 += NB_POS;
290		p1 = h_inv - iy;
291	}
292	*index = add1((i0 << 6), i1);
293	for (i = 0; i < L_SUBFR; i++)
294	{
295		y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3);
296	}
297	return;
298}
299
300
301
302