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  Pathname: ./audio/gsm-amr/c/src/set_sign.c
35  Funtions: set_sign
36            set_sign12k2
37 
38      Date: 05/26/2000
39 
40 ------------------------------------------------------------------------------
41  REVISION HISTORY
42 
43  Description:  Placed into PV template and optimized.
44 
45  Description: Synchronized file with UMTS version 3.2.0. Updated coding
46               template. Removed unnecessary include files.
47 
48  Description: Replaced basic_op.h with the header files of the math functions
49               used in the file.
50 
51  Description: Made the following changes per comments from Phase 2/3 review:
52               1. Modified certain FOR loops to count down.
53               2. Modified code for further optimization.
54 
55  Description: Modified FOR loops in set_sign12k2 to count up. The FOR loops
56               affected are the loop that calculates the starting position of
57               each incoming pulse, and the loop that calculates the position
58               of the max correlation. Updated copyright year.
59 
60  Description: Passing in pointer to overflow flag for EPOC compatibility.
61 
62  Description:  For set_sign12k2()
63               1. Eliminated unused include files.
64               2. Replaced array addressing by pointers
65               3. Eliminated math operations that unnecessary checked for
66                  saturation, this by evaluating the operands
67               4. Replaced loop counter with decrement loops
68 
69  Description:  Replaced "int" and/or "char" with OSCL defined types.
70 
71  Description: Changed round function name to pv_round to avoid conflict with
72               round function in C standard library.
73 
74  Description:
75 
76 ------------------------------------------------------------------------------
77  MODULE DESCRIPTION
78 
79  This module contains the functions set_sign and set_sign12k2.
80  These functions are used to build a sign vector according
81  to the values in the input arrays.  These functions also
82  find the position in the input codes of the maximum correlation
83  and the starting position for each pulse.
84 
85 ------------------------------------------------------------------------------
86 */
87 
88 
89 /*----------------------------------------------------------------------------
90 ; INCLUDES
91 ----------------------------------------------------------------------------*/
92 #include "set_sign.h"
93 #include "basic_op.h"
94 #include "inv_sqrt.h"
95 #include "cnst.h"
96 
97 
98 /*----------------------------------------------------------------------------
99 ; MACROS
100 ; Define module specific macros here
101 ----------------------------------------------------------------------------*/
102 
103 
104 /*----------------------------------------------------------------------------
105 ; DEFINES
106 ; Include all pre-processor statements here. Include conditional
107 ; compile variables also.
108 ----------------------------------------------------------------------------*/
109 
110 /*----------------------------------------------------------------------------
111 ; LOCAL FUNCTION DEFINITIONS
112 ; Function Prototype declaration
113 ----------------------------------------------------------------------------*/
114 
115 /*----------------------------------------------------------------------------
116 ; LOCAL VARIABLE DEFINITIONS
117 ; Variable declaration - defined here and used outside this module
118 ----------------------------------------------------------------------------*/
119 
120 
121 /*
122 ------------------------------------------------------------------------------
123  FUNCTION NAME: set_sign
124 ------------------------------------------------------------------------------
125  INPUT AND OUTPUT DEFINITIONS
126 
127  Inputs:
128     dn = buffer of correlation values (Word16)
129     sign = buffer containing sign of dn elements (Word16)
130     dn2 = buffer containing the maximum of correlation in each track.(Word16)
131     n = number of maximum correlations in dn2 (Word16)
132 
133  Returns:
134     None
135 
136  Outputs:
137     dn buffer is modified to contain the absolute value of its input
138     sign buffer is modified to contain the sign information for the
139       values in dn buffer
140     dn2 buffer is modified to denote the location of the maximum
141       correlation for each track.
142 
143  Global Variables Used:
144     None
145 
146  Local Variables Needed:
147     None
148 
149 ------------------------------------------------------------------------------
150  FUNCTION DESCRIPTION
151 
152 
153  This function builds sign vector according to dn buffer It also finds
154  the position of maximum of correlation in each track and the starting
155  position for each pulse.
156 
157 ------------------------------------------------------------------------------
158  REQUIREMENTS
159 
160  None.
161 
162 ------------------------------------------------------------------------------
163  REFERENCES
164 
165  set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
166 
167 ------------------------------------------------------------------------------
168  PSEUDO-CODE
169 
170 void set_sign(Word16 dn[],    i/o : correlation between target and h[]
171               Word16 sign[],  o   : sign of dn[]
172               Word16 dn2[],   o   : maximum of correlation in each track.
173               Word16 n        i   : # of maximum correlations in dn2[]
174 )
175 {
176    Word16 i, j, k;
177    Word16 val, min;
178    Word16 pos = 0;    //initialization only needed to keep gcc silent
179 
180    // set sign according to dn[]
181 
182    for (i = 0; i < L_CODE; i++) {
183       val = dn[i];
184 
185       if (val >= 0) {
186          sign[i] = 32767;
187       } else {
188          sign[i] = -32767;
189          val = negate(val);
190       }
191       dn[i] = val;     // modify dn[] according to the fixed sign
192       dn2[i] = val;
193    }
194 
195    // keep 8-n maximum positions/8 of each track and store it in dn2[]
196 
197    for (i = 0; i < NB_TRACK; i++)
198    {
199       for (k = 0; k < (8-n); k++)
200       {
201          min = 0x7fff;
202          for (j = i; j < L_CODE; j += STEP)
203          {
204             if (dn2[j] >= 0)
205             {
206                val = sub(dn2[j], min);
207 
208                if (val < 0)
209                {
210                   min = dn2[j];
211                   pos = j;
212                }
213             }
214          }
215          dn2[pos] = -1;
216       }
217    }
218 
219    return;
220 }
221 
222 ------------------------------------------------------------------------------
223  RESOURCES USED [optional]
224 
225  When the code is written for a specific target processor the
226  the resources used should be documented below.
227 
228  HEAP MEMORY USED: x bytes
229 
230  STACK MEMORY USED: x bytes
231 
232  CLOCK CYCLES: (cycle count equation for this function) + (variable
233                 used to represent cycle count for each subroutine
234                 called)
235      where: (cycle count variable) = cycle count for [subroutine
236                                      name]
237 
238 ------------------------------------------------------------------------------
239  CAUTION [optional]
240  [State any special notes, constraints or cautions for users of this function]
241 
242 ------------------------------------------------------------------------------
243 */
244 
set_sign(Word16 dn[],Word16 sign[],Word16 dn2[],Word16 n)245 void set_sign(Word16 dn[],   /* i/o : correlation between target and h[]    */
246               Word16 sign[], /* o   : sign of dn[]                          */
247               Word16 dn2[],  /* o   : maximum of correlation in each track. */
248               Word16 n       /* i   : # of maximum correlations in dn2[]    */
249              )
250 {
251     Word16 i, j, k;
252     Word16 val, min;
253     Word16 pos = 0; /* initialization only needed to keep gcc silent */
254 
255     /* set sign according to dn[] */
256     for (i = L_CODE - 1; i >= 0; i--)
257     {
258         val = dn[i];
259 
260         if (val >= 0)
261         {
262             sign[i] = 32767;
263         }
264         else
265         {
266             sign[i] = -32767;
267             val = negate(val);
268             dn[i] = val;     /* modify dn[] according to the fixed sign */
269         }
270 
271         dn2[i] = val;
272     }
273 
274     /* keep 8-n maximum positions/8 of each track and store it in dn2[] */
275 
276     for (i = 0; i < NB_TRACK; i++)
277     {
278         for (k = 0; k < (8 - n); k++)
279         {
280             min = 0x7fff;
281             for (j = i; j < L_CODE; j += STEP)
282             {
283                 if (dn2[j] >= 0)
284                 {
285                     if (dn2[j] < min)
286                     {
287                         min = dn2[j];
288                         pos = j;
289                     }
290                 }
291             }
292             dn2[pos] = -1;
293         }
294     }
295 
296     return;
297 }
298 
299 /****************************************************************************/
300 
301 
302 /*
303 ------------------------------------------------------------------------------
304  FUNCTION NAME: set_sign12k2()
305 ------------------------------------------------------------------------------
306  INPUT AND OUTPUT DEFINITIONS
307 
308  Inputs:
309     dn = buffer of correlation values (Word16)
310     cn = buffer of residual after long term prediction (Word16)
311     sign = sign of correlation buffer elements (Word16)
312     pos_max = buffer containing position of maximum correlation (Word16)
313     nb_track = number of tracks (Word16)
314     ipos = buffer containing the starting position for each pulse (Word16)
315     step = step size in the tracks (Word16)
316     pOverflow = pointer to Overflow flag (Flag)
317 
318  Outputs:
319     sign buffer contains the sign of correlation values
320     dn buffer contains the sign-adjusted correlation values
321     pos_max buffer contains the maximum correlation position
322     ipos buffer contains the starting position of each pulse
323     pOverflow -> 1 if the math operations called by this function result in
324     saturation
325 
326 
327  Returns:
328     None
329 
330  Global Variables Used:
331     None
332 
333  Local Variables Needed:
334     None
335 
336 ------------------------------------------------------------------------------
337  FUNCTION DESCRIPTION
338 
339  This function builds the sign vector according to dn and cn, and modifies
340  dn to include the sign information (dn[i]=sign[i]*dn[i]). It also finds
341  the position of maximum of correlation in each track and the starting
342  position for each pulse.
343 
344 ------------------------------------------------------------------------------
345  REQUIREMENTS
346 
347  None
348 
349 ------------------------------------------------------------------------------
350  REFERENCES
351 
352  set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
353 
354 ------------------------------------------------------------------------------
355  PSEUDO-CODE
356 
357 void set_sign12k2 (
358     Word16 dn[],       //i/o : correlation between target and h[]
359     Word16 cn[],       //i   : residual after long term prediction
360     Word16 sign[],     //o   : sign of d[n]
361     Word16 pos_max[],  //o   : position of maximum correlation
362     Word16 nb_track,   //i   : number of tracks tracks
363     Word16 ipos[],     //o   : starting position for each pulse
364     Word16 step        //i   : the step size in the tracks
365 )
366 {
367     Word16 i, j;
368     Word16 val, cor, k_cn, k_dn, max, max_of_all;
369     Word16 pos = 0;      // initialization only needed to keep gcc silent
370     Word16 en[L_CODE];                  // correlation vector
371     Word32 s;
372 
373     // The reference ETSI code uses a global flag for Overflow. However in the
374     // actual implementation a pointer to the overflow flag is passed in. This
375     // pointer is passed into the basic math functions called by this routine.
376 
377     // calculate energy for normalization of cn[] and dn[]
378 
379     s = 256;
380     for (i = 0; i < L_CODE; i++)
381     {
382         s = L_mac (s, cn[i], cn[i]);
383     }
384     s = Inv_sqrt (s);
385     k_cn = extract_h (L_shl (s, 5));
386 
387     s = 256;
388     for (i = 0; i < L_CODE; i++)
389     {
390         s = L_mac (s, dn[i], dn[i]);
391     }
392     s = Inv_sqrt (s);
393     k_dn = extract_h (L_shl (s, 5));
394 
395     for (i = 0; i < L_CODE; i++)
396     {
397         val = dn[i];
398         cor = pv_round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10));
399 
400         if (cor >= 0)
401         {
402             sign[i] = 32767;                      // sign = +1
403         }
404         else
405         {
406             sign[i] = -32767;                     // sign = -1
407             cor = negate (cor);
408             val = negate (val);
409         }
410         // modify dn[] according to the fixed sign
411         dn[i] = val;
412         en[i] = cor;
413     }
414 
415     max_of_all = -1;
416     for (i = 0; i < nb_track; i++)
417     {
418         max = -1;
419 
420         for (j = i; j < L_CODE; j += step)
421         {
422             cor = en[j];
423             val = sub (cor, max);
424 
425             if (val > 0)
426             {
427                 max = cor;
428                 pos = j;
429             }
430         }
431         // store maximum correlation position
432         pos_max[i] = pos;
433         val = sub (max, max_of_all);
434 
435         if (val > 0)
436         {
437             max_of_all = max;
438             // starting position for i0
439             ipos[0] = i;
440         }
441     }
442 
443     //
444     //     Set starting position of each pulse.
445     //
446 
447     pos = ipos[0];
448     ipos[nb_track] = pos;
449 
450     for (i = 1; i < nb_track; i++)
451     {
452         pos = add (pos, 1);
453 
454         if (sub (pos, nb_track) >= 0)
455         {
456            pos = 0;
457         }
458         ipos[i] = pos;
459         ipos[add(i, nb_track)] = pos;
460     }
461 }
462 
463 ------------------------------------------------------------------------------
464  RESOURCES USED [optional]
465 
466  When the code is written for a specific target processor the
467  the resources used should be documented below.
468 
469  HEAP MEMORY USED: x bytes
470 
471  STACK MEMORY USED: x bytes
472 
473  CLOCK CYCLES: (cycle count equation for this function) + (variable
474                 used to represent cycle count for each subroutine
475                 called)
476      where: (cycle count variable) = cycle count for [subroutine
477                                      name]
478 
479 ------------------------------------------------------------------------------
480  CAUTION [optional]
481  [State any special notes, constraints or cautions for users of this function]
482 
483 ------------------------------------------------------------------------------
484 */
485 
set_sign12k2(Word16 dn[],Word16 cn[],Word16 sign[],Word16 pos_max[],Word16 nb_track,Word16 ipos[],Word16 step,Flag * pOverflow)486 void set_sign12k2(
487     Word16 dn[],        /* i/o : correlation between target and h[]         */
488     Word16 cn[],        /* i   : residual after long term prediction        */
489     Word16 sign[],      /* o   : sign of d[n]                               */
490     Word16 pos_max[],   /* o   : position of maximum correlation            */
491     Word16 nb_track,    /* i   : number of tracks tracks                    */
492     Word16 ipos[],      /* o   : starting position for each pulse           */
493     Word16 step,        /* i   : the step size in the tracks                */
494     Flag   *pOverflow   /* i/o: overflow flag                               */
495 )
496 {
497     Word16 i, j;
498     Word16 val;
499     Word16 cor;
500     Word16 k_cn;
501     Word16 k_dn;
502     Word16 max;
503     Word16 max_of_all;
504     Word16 pos = 0; /* initialization only needed to keep gcc silent */
505     Word16 en[L_CODE];                  /* correlation vector */
506     Word32 s;
507     Word32 t;
508     Word32 L_temp;
509     Word16 *p_cn;
510     Word16 *p_dn;
511     Word16 *p_sign;
512     Word16 *p_en;
513 
514     /* calculate energy for normalization of cn[] and dn[] */
515 
516     s = 256;
517     t = 256;
518     p_cn = cn;
519     p_dn = dn;      /* crosscorrelation values do not have strong peaks, so
520                        scaling applied in cor_h_x (sf=2) guaranteed that the
521                        mac of the energy for this vector will not overflow */
522 
523     for (i = L_CODE; i != 0; i--)
524     {
525         val = *(p_cn++);
526         s = L_mac(s, val, val, pOverflow);
527         val = *(p_dn++);
528         t += ((Word32) val * val) << 1;
529     }
530     s = Inv_sqrt(s, pOverflow);
531     k_cn = (Word16)((L_shl(s, 5, pOverflow)) >> 16);
532 
533     t = Inv_sqrt(t, pOverflow);
534     k_dn = (Word16)(t >> 11);
535 
536     p_cn   = &cn[L_CODE-1];
537     p_sign = &sign[L_CODE-1];
538     p_en   = &en[L_CODE-1];
539 
540     for (i = L_CODE - 1; i >= 0; i--)
541     {
542         L_temp = ((Word32)k_cn * *(p_cn--)) << 1;
543         val = dn[i];
544         s = L_mac(L_temp, k_dn, val, pOverflow);
545         L_temp = L_shl(s, 10, pOverflow);
546         cor = pv_round(L_temp, pOverflow);
547 
548         if (cor >= 0)
549         {
550             *(p_sign--) = 32767;                      /* sign = +1 */
551         }
552         else
553         {
554             *(p_sign--) = -32767;                     /* sign = -1 */
555             cor = negate(cor);
556 
557             /* modify dn[] according to the fixed sign */
558             dn[i] = negate(val);
559         }
560 
561         *(p_en--) = cor;
562     }
563 
564     max_of_all = -1;
565     for (i = 0; i < nb_track; i++)
566     {
567         max = -1;
568 
569         for (j = i; j < L_CODE; j += step)
570         {
571             cor = en[j];
572             if (cor > max)
573             {
574                 max = cor;
575                 pos = j;
576             }
577         }
578         /* store maximum correlation position */
579         pos_max[i] = pos;
580         if (max > max_of_all)
581         {
582             max_of_all = max;
583             /* starting position for i0 */
584             ipos[0] = i;
585         }
586     }
587 
588     /*----------------------------------------------------------------*
589      *     Set starting position of each pulse.                       *
590      *----------------------------------------------------------------*/
591 
592     pos = ipos[0];
593     ipos[nb_track] = pos;
594 
595     for (i = 1; i < nb_track; i++)
596     {
597         pos++;
598 
599         if (pos >= nb_track)
600         {
601             pos = 0;
602         }
603         ipos[ i] = pos;
604         ipos[ i + nb_track] = pos;
605     }
606 
607     return;
608 }
609 
610