c2t64fx.c revision 5d5c3a132bb446ac78a37dfaac24a46cacf0dd73
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
47void 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 = vo_round(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