Initialize Tizen 2.3
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / set_sign.cpp
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
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
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21     3GPP TS 26.073
22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23     Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 ------------------------------------------------------------------------------
31
32
33
34  Filename: set_sign.cpp
35  Funtions: set_sign
36            set_sign12k2
37
38 ------------------------------------------------------------------------------
39  MODULE DESCRIPTION
40
41  This module contains the functions set_sign and set_sign12k2.
42  These functions are used to build a sign vector according
43  to the values in the input arrays.  These functions also
44  find the position in the input codes of the maximum correlation
45  and the starting position for each pulse.
46
47 ------------------------------------------------------------------------------
48 */
49
50
51 /*----------------------------------------------------------------------------
52 ; INCLUDES
53 ----------------------------------------------------------------------------*/
54 #include "set_sign.h"
55 #include "basic_op.h"
56 #include "inv_sqrt.h"
57 #include "cnst.h"
58
59
60 /*----------------------------------------------------------------------------
61 ; MACROS
62 ; Define module specific macros here
63 ----------------------------------------------------------------------------*/
64
65
66 /*----------------------------------------------------------------------------
67 ; DEFINES
68 ; Include all pre-processor statements here. Include conditional
69 ; compile variables also.
70 ----------------------------------------------------------------------------*/
71
72 /*----------------------------------------------------------------------------
73 ; LOCAL FUNCTION DEFINITIONS
74 ; Function Prototype declaration
75 ----------------------------------------------------------------------------*/
76
77 /*----------------------------------------------------------------------------
78 ; LOCAL VARIABLE DEFINITIONS
79 ; Variable declaration - defined here and used outside this module
80 ----------------------------------------------------------------------------*/
81
82
83 /*
84 ------------------------------------------------------------------------------
85  FUNCTION NAME: set_sign
86 ------------------------------------------------------------------------------
87  INPUT AND OUTPUT DEFINITIONS
88
89  Inputs:
90     dn = buffer of correlation values (Word16)
91     sign = buffer containing sign of dn elements (Word16)
92     dn2 = buffer containing the maximum of correlation in each track.(Word16)
93     n = number of maximum correlations in dn2 (Word16)
94
95  Returns:
96     None
97
98  Outputs:
99     dn buffer is modified to contain the absolute value of its input
100     sign buffer is modified to contain the sign information for the
101       values in dn buffer
102     dn2 buffer is modified to denote the location of the maximum
103       correlation for each track.
104
105  Global Variables Used:
106     None
107
108  Local Variables Needed:
109     None
110
111 ------------------------------------------------------------------------------
112  FUNCTION DESCRIPTION
113
114
115  This function builds sign vector according to dn buffer It also finds
116  the position of maximum of correlation in each track and the starting
117  position for each pulse.
118
119 ------------------------------------------------------------------------------
120  REQUIREMENTS
121
122  None.
123
124 ------------------------------------------------------------------------------
125  REFERENCES
126
127  set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
128
129 ------------------------------------------------------------------------------
130  PSEUDO-CODE
131
132 void set_sign(Word16 dn[],    i/o : correlation between target and h[]
133               Word16 sign[],  o   : sign of dn[]
134               Word16 dn2[],   o   : maximum of correlation in each track.
135               Word16 n        i   : # of maximum correlations in dn2[]
136 )
137 {
138    Word16 i, j, k;
139    Word16 val, min;
140    Word16 pos = 0;    //initialization only needed to keep gcc silent
141
142    // set sign according to dn[]
143
144    for (i = 0; i < L_CODE; i++) {
145       val = dn[i];
146
147       if (val >= 0) {
148          sign[i] = 32767;
149       } else {
150          sign[i] = -32767;
151          val = negate(val);
152       }
153       dn[i] = val;     // modify dn[] according to the fixed sign
154       dn2[i] = val;
155    }
156
157    // keep 8-n maximum positions/8 of each track and store it in dn2[]
158
159    for (i = 0; i < NB_TRACK; i++)
160    {
161       for (k = 0; k < (8-n); k++)
162       {
163          min = 0x7fff;
164          for (j = i; j < L_CODE; j += STEP)
165          {
166             if (dn2[j] >= 0)
167             {
168                val = sub(dn2[j], min);
169
170                if (val < 0)
171                {
172                   min = dn2[j];
173                   pos = j;
174                }
175             }
176          }
177          dn2[pos] = -1;
178       }
179    }
180
181    return;
182 }
183
184 ------------------------------------------------------------------------------
185  CAUTION [optional]
186  [State any special notes, constraints or cautions for users of this function]
187
188 ------------------------------------------------------------------------------
189 */
190
191 void set_sign(Word16 dn[],   /* i/o : correlation between target and h[]    */
192               Word16 sign[], /* o   : sign of dn[]                          */
193               Word16 dn2[],  /* o   : maximum of correlation in each track. */
194               Word16 n       /* i   : # of maximum correlations in dn2[]    */
195              )
196 {
197     register Word16 i, j, k;
198     Word16 val, min;
199     Word16 pos = 0; /* initialization only needed to keep gcc silent */
200
201     /* set sign according to dn[] */
202     for (i = L_CODE - 1; i >= 0; i--)
203     {
204         val = dn[i];
205
206         if (val >= 0)
207         {
208             sign[i] = 32767;
209         }
210         else
211         {
212             sign[i] = -32767;
213             val = negate(val);
214             dn[i] = val;     /* modify dn[] according to the fixed sign */
215         }
216
217         dn2[i] = val;
218     }
219
220     /* keep 8-n maximum positions/8 of each track and store it in dn2[] */
221
222     for (i = 0; i < NB_TRACK; i++)
223     {
224         for (k = 0; k < (8 - n); k++)
225         {
226             min = 0x7fff;
227             for (j = i; j < L_CODE; j += STEP)
228             {
229                 if (dn2[j] >= 0)
230                 {
231                     if (dn2[j] < min)
232                     {
233                         min = dn2[j];
234                         pos = j;
235                     }
236                 }
237             }
238             dn2[pos] = -1;
239         }
240     }
241
242     return;
243 }
244
245 /****************************************************************************/
246
247
248 /*
249 ------------------------------------------------------------------------------
250  FUNCTION NAME: set_sign12k2()
251 ------------------------------------------------------------------------------
252  INPUT AND OUTPUT DEFINITIONS
253
254  Inputs:
255     dn = buffer of correlation values (Word16)
256     cn = buffer of residual after long term prediction (Word16)
257     sign = sign of correlation buffer elements (Word16)
258     pos_max = buffer containing position of maximum correlation (Word16)
259     nb_track = number of tracks (Word16)
260     ipos = buffer containing the starting position for each pulse (Word16)
261     step = step size in the tracks (Word16)
262     pOverflow = pointer to Overflow flag (Flag)
263
264  Outputs:
265     sign buffer contains the sign of correlation values
266     dn buffer contains the sign-adjusted correlation values
267     pos_max buffer contains the maximum correlation position
268     ipos buffer contains the starting position of each pulse
269     pOverflow -> 1 if the math operations called by this function result in
270     saturation
271
272
273  Returns:
274     None
275
276  Global Variables Used:
277     None
278
279  Local Variables Needed:
280     None
281
282 ------------------------------------------------------------------------------
283  FUNCTION DESCRIPTION
284
285  This function builds the sign vector according to dn and cn, and modifies
286  dn to include the sign information (dn[i]=sign[i]*dn[i]). It also finds
287  the position of maximum of correlation in each track and the starting
288  position for each pulse.
289
290 ------------------------------------------------------------------------------
291  REQUIREMENTS
292
293  None
294
295 ------------------------------------------------------------------------------
296  REFERENCES
297
298  set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
299
300 ------------------------------------------------------------------------------
301  PSEUDO-CODE
302
303 void set_sign12k2 (
304     Word16 dn[],       //i/o : correlation between target and h[]
305     Word16 cn[],       //i   : residual after long term prediction
306     Word16 sign[],     //o   : sign of d[n]
307     Word16 pos_max[],  //o   : position of maximum correlation
308     Word16 nb_track,   //i   : number of tracks tracks
309     Word16 ipos[],     //o   : starting position for each pulse
310     Word16 step        //i   : the step size in the tracks
311 )
312 {
313     Word16 i, j;
314     Word16 val, cor, k_cn, k_dn, max, max_of_all;
315     Word16 pos = 0;      // initialization only needed to keep gcc silent
316     Word16 en[L_CODE];                  // correlation vector
317     Word32 s;
318
319     // The reference ETSI code uses a global flag for Overflow. However in the
320     // actual implementation a pointer to the overflow flag is passed in. This
321     // pointer is passed into the basic math functions called by this routine.
322
323     // calculate energy for normalization of cn[] and dn[]
324
325     s = 256;
326     for (i = 0; i < L_CODE; i++)
327     {
328         s = L_mac (s, cn[i], cn[i]);
329     }
330     s = Inv_sqrt (s);
331     k_cn = extract_h (L_shl (s, 5));
332
333     s = 256;
334     for (i = 0; i < L_CODE; i++)
335     {
336         s = L_mac (s, dn[i], dn[i]);
337     }
338     s = Inv_sqrt (s);
339     k_dn = extract_h (L_shl (s, 5));
340
341     for (i = 0; i < L_CODE; i++)
342     {
343         val = dn[i];
344         cor = pv_round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10));
345
346         if (cor >= 0)
347         {
348             sign[i] = 32767;                      // sign = +1
349         }
350         else
351         {
352             sign[i] = -32767;                     // sign = -1
353             cor = negate (cor);
354             val = negate (val);
355         }
356         // modify dn[] according to the fixed sign
357         dn[i] = val;
358         en[i] = cor;
359     }
360
361     max_of_all = -1;
362     for (i = 0; i < nb_track; i++)
363     {
364         max = -1;
365
366         for (j = i; j < L_CODE; j += step)
367         {
368             cor = en[j];
369             val = sub (cor, max);
370
371             if (val > 0)
372             {
373                 max = cor;
374                 pos = j;
375             }
376         }
377         // store maximum correlation position
378         pos_max[i] = pos;
379         val = sub (max, max_of_all);
380
381         if (val > 0)
382         {
383             max_of_all = max;
384             // starting position for i0
385             ipos[0] = i;
386         }
387     }
388
389     //
390     //     Set starting position of each pulse.
391     //
392
393     pos = ipos[0];
394     ipos[nb_track] = pos;
395
396     for (i = 1; i < nb_track; i++)
397     {
398         pos = add (pos, 1);
399
400         if (sub (pos, nb_track) >= 0)
401         {
402            pos = 0;
403         }
404         ipos[i] = pos;
405         ipos[add(i, nb_track)] = pos;
406     }
407 }
408
409 ------------------------------------------------------------------------------
410  CAUTION [optional]
411  [State any special notes, constraints or cautions for users of this function]
412
413 ------------------------------------------------------------------------------
414 */
415
416 void set_sign12k2(
417     Word16 dn[],        /* i/o : correlation between target and h[]         */
418     Word16 cn[],        /* i   : residual after long term prediction        */
419     Word16 sign[],      /* o   : sign of d[n]                               */
420     Word16 pos_max[],   /* o   : position of maximum correlation            */
421     Word16 nb_track,    /* i   : number of tracks tracks                    */
422     Word16 ipos[],      /* o   : starting position for each pulse           */
423     Word16 step,        /* i   : the step size in the tracks                */
424     Flag   *pOverflow   /* i/o: overflow flag                               */
425 )
426 {
427     Word16 i, j;
428     Word16 val;
429     Word16 cor;
430     Word16 k_cn;
431     Word16 k_dn;
432     Word16 max;
433     Word16 max_of_all;
434     Word16 pos = 0; /* initialization only needed to keep gcc silent */
435     Word16 en[L_CODE];                  /* correlation vector */
436     Word32 s;
437     Word32 t;
438     Word32 L_temp;
439     Word16 *p_cn;
440     Word16 *p_dn;
441     Word16 *p_sign;
442     Word16 *p_en;
443
444     /* calculate energy for normalization of cn[] and dn[] */
445
446     s = 256;
447     t = 256;
448     p_cn = cn;
449     p_dn = dn;      /* crosscorrelation values do not have strong peaks, so
450                        scaling applied in cor_h_x (sf=2) guaranteed that the
451                        mac of the energy for this vector will not overflow */
452
453     for (i = L_CODE; i != 0; i--)
454     {
455         val = *(p_cn++);
456         s = L_mac(s, val, val, pOverflow);
457         val = *(p_dn++);
458         t += ((Word32) val * val) << 1;
459     }
460     s = Inv_sqrt(s, pOverflow);
461     k_cn = (Word16)((L_shl(s, 5, pOverflow)) >> 16);
462
463     t = Inv_sqrt(t, pOverflow);
464     k_dn = (Word16)(t >> 11);
465
466     p_cn   = &cn[L_CODE-1];
467     p_sign = &sign[L_CODE-1];
468     p_en   = &en[L_CODE-1];
469
470     for (i = L_CODE - 1; i >= 0; i--)
471     {
472         L_temp = ((Word32)k_cn * *(p_cn--)) << 1;
473         val = dn[i];
474         s = L_mac(L_temp, k_dn, val, pOverflow);
475         L_temp = L_shl(s, 10, pOverflow);
476         cor = pv_round(L_temp, pOverflow);
477
478         if (cor >= 0)
479         {
480             *(p_sign--) = 32767;                      /* sign = +1 */
481         }
482         else
483         {
484             *(p_sign--) = -32767;                     /* sign = -1 */
485             cor = negate(cor);
486
487             /* modify dn[] according to the fixed sign */
488             dn[i] = negate(val);
489         }
490
491         *(p_en--) = cor;
492     }
493
494     max_of_all = -1;
495     for (i = 0; i < nb_track; i++)
496     {
497         max = -1;
498
499         for (j = i; j < L_CODE; j += step)
500         {
501             cor = en[j];
502             if (cor > max)
503             {
504                 max = cor;
505                 pos = j;
506             }
507         }
508         /* store maximum correlation position */
509         pos_max[i] = pos;
510         if (max > max_of_all)
511         {
512             max_of_all = max;
513             /* starting position for i0 */
514             ipos[0] = i;
515         }
516     }
517
518     /*----------------------------------------------------------------*
519      *     Set starting position of each pulse.                       *
520      *----------------------------------------------------------------*/
521
522     pos = ipos[0];
523     ipos[nb_track] = pos;
524
525     for (i = 1; i < nb_track; i++)
526     {
527         pos++;
528
529         if (pos >= nb_track)
530         {
531             pos = 0;
532         }
533         ipos[ i] = pos;
534         ipos[ i + nb_track] = pos;
535     }
536
537     return;
538 }
539