Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / c3_14pf.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: c3_14pf.cpp
35
36 ------------------------------------------------------------------------------
37  MODULE DESCRIPTION
38
39 ------------------------------------------------------------------------------
40 */
41
42 /*----------------------------------------------------------------------------
43 ; INCLUDES
44 ----------------------------------------------------------------------------*/
45 #include "c3_14pf.h"
46 #include "typedef.h"
47 #include "inv_sqrt.h"
48 #include "cnst.h"
49 #include "cor_h.h"
50 #include "set_sign.h"
51 #include "basic_op.h"
52
53 /*----------------------------------------------------------------------------
54 ; MACROS
55 ; Define module specific macros here
56 ----------------------------------------------------------------------------*/
57
58 /*----------------------------------------------------------------------------
59 ; DEFINES
60 ; Include all pre-processor statements here. Include conditional
61 ; compile variables also.
62 ----------------------------------------------------------------------------*/
63
64 #define NB_PULSE  3
65
66 /*----------------------------------------------------------------------------
67 ; LOCAL FUNCTION DEFINITIONS
68 ; Function Prototype declaration
69 ----------------------------------------------------------------------------*/
70 static void search_3i40(
71     Word16 dn[],        /* i : correlation between target and h[]            */
72     Word16 dn2[],       /* i : maximum of corr. in each track.               */
73     Word16 rr[][L_CODE],/* i : matrix of autocorrelation                     */
74     Word16 codvec[],    /* o : algebraic codebook vector                     */
75     Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
76 );
77
78 static Word16 build_code(
79     Word16 codvec[],    /* i : algebraic codebook vector                     */
80     Word16 dn_sign[],   /* i : sign of dn[]                                  */
81     Word16 cod[],       /* o : algebraic (fixed) codebook excitation         */
82     Word16 h[],         /* i : impulse response of weighted synthesis filter */
83     Word16 y[],         /* o : filtered fixed codebook excitation            */
84     Word16 sign[],      /* o : sign of 3 pulses                              */
85     Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
86 );
87
88 /*----------------------------------------------------------------------------
89 ; LOCAL VARIABLE DEFINITIONS
90 ; Variable declaration - defined here and used outside this module
91 ----------------------------------------------------------------------------*/
92
93 /*----------------------------------------------------------------------------
94 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
95 ; Declare variables used in this module but defined elsewhere
96 ----------------------------------------------------------------------------*/
97
98 /*
99 ------------------------------------------------------------------------------
100  FUNCTION NAME: code_3i40_14bits
101 ------------------------------------------------------------------------------
102  INPUT AND OUTPUT DEFINITIONS
103
104  Inputs:
105     x[]   Array of type Word16 -- target vector
106     h[]   Array of type Word16 -- impulse response of weighted synthesis filter
107                                   h[-L_subfr..-1] must be set to zero.
108
109     T0           Array of type Word16 -- Pitch lag
110     pitch_sharp, Array of type Word16 --  Last quantized pitch gain
111
112  Outputs:
113     code[]  Array of type Word16 -- Innovative codebook
114     y[]     Array of type Word16 -- filtered fixed codebook excitation
115     * sign  Pointer of type Word16 -- Pointer to the signs of 3 pulses
116     pOverflow    Pointer to Flag      -- set when overflow occurs
117
118  Returns:
119     index
120
121  Global Variables Used:
122     None
123
124  Local Variables Needed:
125     None
126
127 ------------------------------------------------------------------------------
128  FUNCTION DESCRIPTION
129
130  PURPOSE:  Searches a 14 bit algebraic codebook containing 3 pulses
131            in a frame of 40 samples.
132
133  DESCRIPTION:
134     The code length is 40, containing 3 nonzero pulses: i0...i2.
135     All pulses can have two possible amplitudes: +1 or -1.
136     Pulse i0 can have 8 possible positions, pulses i1 and i2 can have
137     2x8=16 positions.
138
139         i0 :  0, 5, 10, 15, 20, 25, 30, 35.
140         i1 :  1, 6, 11, 16, 21, 26, 31, 36.
141               3, 8, 13, 18, 23, 28, 33, 38.
142         i2 :  2, 7, 12, 17, 22, 27, 32, 37.
143               4, 9, 14, 19, 24, 29, 34, 39.
144
145 ------------------------------------------------------------------------------
146  REQUIREMENTS
147
148  None
149
150 ------------------------------------------------------------------------------
151  REFERENCES
152
153  [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
154
155 ------------------------------------------------------------------------------
156  PSEUDO-CODE
157
158 ------------------------------------------------------------------------------
159  CAUTION [optional]
160  [State any special notes, constraints or cautions for users of this function]
161
162 ------------------------------------------------------------------------------
163 */
164
165 Word16 code_3i40_14bits(
166     Word16 x[],         /* i : target vector                                 */
167     Word16 h[],         /* i : impulse response of weighted synthesis filter */
168     /*     h[-L_subfr..-1] must be set to zero.          */
169     Word16 T0,          /* i : Pitch lag                                     */
170     Word16 pitch_sharp, /* i : Last quantized pitch gain                     */
171     Word16 code[],      /* o : Innovative codebook                           */
172     Word16 y[],         /* o : filtered fixed codebook excitation            */
173     Word16 * sign,      /* o : Signs of 3 pulses                             */
174     Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
175 )
176 {
177     Word16 codvec[NB_PULSE];
178     Word16 dn[L_CODE];
179     Word16 dn2[L_CODE];
180     Word16 dn_sign[L_CODE];
181     Word16 rr[L_CODE][L_CODE];
182     Word16 i;
183     Word16 index;
184     Word16 sharp;
185     Word16 tempWord;
186
187     /* sharp = shl(pitch_sharp, 1, pOverflow); */
188     sharp = pitch_sharp << 1;
189
190     if (T0 < L_CODE)
191     {
192         for (i = T0; i < L_CODE; i++)
193         {
194             tempWord =
195                 mult(
196                     h[i - T0],
197                     sharp,
198                     pOverflow);
199
200             h[i] =
201                 add_16(
202                     h[i],
203                     tempWord,
204                     pOverflow);
205         }
206     }
207
208     cor_h_x(
209         h,
210         x,
211         dn,
212         1,
213         pOverflow);
214
215     set_sign(
216         dn,
217         dn_sign,
218         dn2,
219         6);
220
221     cor_h(
222         h,
223         dn_sign,
224         rr,
225         pOverflow);
226
227     search_3i40(
228         dn,
229         dn2,
230         rr,
231         codvec,
232         pOverflow);
233
234     /* function result */
235     index =
236         build_code(
237             codvec,
238             dn_sign,
239             code,
240             h,
241             y,
242             sign,
243             pOverflow);
244
245     /*-----------------------------------------------------------------*
246     * Compute innovation vector gain.                                 *
247     * Include fixed-gain pitch contribution into code[].              *
248     *-----------------------------------------------------------------*/
249
250     if (T0 < L_CODE)
251     {
252         for (i = T0; i < L_CODE; i++)
253         {
254             tempWord =
255                 mult(
256                     code[i - T0],
257                     sharp,
258                     pOverflow);
259
260             code[i] =
261                 add_16(
262                     code[i],
263                     tempWord,
264                     pOverflow);
265         }
266     }
267     return index;
268 }
269
270 /****************************************************************************/
271
272 /*
273 ------------------------------------------------------------------------------
274  FUNCTION NAME: search_3i40
275 ------------------------------------------------------------------------------
276  INPUT AND OUTPUT DEFINITIONS
277
278  Inputs:
279     dn[]         Array of type Word16 -- correlation between target and h[]
280     dn2[]        Array of type Word16 -- maximum of corr. in each track.
281     rr[][L_CODE] Double Array of type Word16 -- autocorrelation matrix
282
283  Outputs:
284     codvec[]     Array of type Word16 -- algebraic codebook vector
285     pOverflow    Pointer to Flag      -- set when overflow occurs
286
287  Returns:
288     None
289
290  Global Variables Used:
291     None
292
293  Local Variables Needed:
294     None
295
296 ------------------------------------------------------------------------------
297  FUNCTION DESCRIPTION
298
299  PURPOSE: Search the best codevector; determine positions of the 3 pulses
300           in the 40-sample frame.
301 ------------------------------------------------------------------------------
302  REQUIREMENTS
303
304  None
305
306 ------------------------------------------------------------------------------
307  REFERENCES
308
309  [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
310
311 ------------------------------------------------------------------------------
312  PSEUDO-CODE
313
314 ------------------------------------------------------------------------------
315  CAUTION [optional]
316  [State any special notes, constraints or cautions for users of this function]
317
318 ------------------------------------------------------------------------------
319 */
320 static void search_3i40(
321     Word16 dn[],         /* i : correlation between target and h[] */
322     Word16 dn2[],        /* i : maximum of corr. in each track.    */
323     Word16 rr[][L_CODE], /* i : matrix of autocorrelation          */
324     Word16 codvec[],     /* o : algebraic codebook vector          */
325     Flag   * pOverflow   /* o : Flag set when overflow occurs      */
326 )
327 {
328     Word16 i0;
329     Word16 i1;
330     Word16 i2;
331
332     Word16 ix = 0; /* initialization only needed to keep gcc silent */
333     Word16 ps = 0; /* initialization only needed to keep gcc silent */
334
335     Word16 i;
336     Word16 pos;
337     Word16 track1;
338     Word16 track2;
339     Word16 ipos[NB_PULSE];
340
341     Word16 psk;
342     Word16 ps0;
343     Word16 ps1;
344     Word16 sq;
345     Word16 sq1;
346     Word16 alpk;
347     Word16 alp;
348     Word16 alp_16;
349
350     Word16 *p_codvec = &codvec[0];
351
352     Word32 s;
353     Word32 alp0;
354     Word32 alp1;
355
356     psk = -1;
357     alpk = 1;
358
359     for (i = 0; i < NB_PULSE; i++)
360     {
361         *(p_codvec++) = i;
362     }
363
364     for (track1 = 1; track1 < 4; track1 += 2)
365     {
366         for (track2 = 2; track2 < 5; track2 += 2)
367         {
368             /* fix starting position */
369
370             ipos[0] = 0;
371             ipos[1] = track1;
372             ipos[2] = track2;
373
374             /*------------------------------------------------------------------*
375              * main loop: try 3 tracks.                                         *
376              *------------------------------------------------------------------*/
377
378             for (i = 0; i < NB_PULSE; i++)
379             {
380                 /*----------------------------------------------------------------*
381                  * i0 loop: try 8 positions.                                      *
382                  *----------------------------------------------------------------*/
383
384                 /* account for ptr. init. (rr[io]) */
385                 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
386                 {
387                     if (dn2[i0] >= 0)
388                     {
389                         ps0 = dn[i0];
390
391                         /* alp0 = L_mult(rr[i0][i0],_1_4, pOverflow); */
392                         alp0 = (Word32) rr[i0][i0] << 14;
393
394                         /*----------------------------------------------------------------*
395                          * i1 loop: 8 positions.                                          *
396                          *----------------------------------------------------------------*/
397
398                         sq = -1;
399                         alp = 1;
400                         ps = 0;
401                         ix = ipos[1];
402
403                         /* initialize 4 index for next loop. */
404                         /*-------------------------------------------------------------------*
405                          *  These index have low complexity address computation because      *
406                          *  they are, in fact, pointers with fixed increment.  For example,  *
407                          *  "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]"      *
408                          *  and incremented by "STEP".                                       *
409                          *-------------------------------------------------------------------*/
410
411                         for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
412                         {
413                             /* idx increment = STEP */
414                             /* ps1 = add(ps0, dn[i1], pOverflow); */
415                             ps1 = ps0 + dn[i1];
416
417                             /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
418
419                             /* idx incr = STEP */
420                             /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
421                             alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
422
423                             /* idx incr = STEP */
424                             /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
425                             alp1 += (Word32) rr[i0][i1] << 15;
426
427                             /* sq1 = mult(ps1, ps1, pOverflow); */
428                             sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
429
430                             /* alp_16 = pv_round(alp1, pOverflow); */
431                             alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
432
433                             /* s = L_mult(alp, sq1, pOverflow); */
434                             s = ((Word32) alp * sq1) << 1;
435
436                             /* s = L_msu(s, sq, alp_16, pOverflow); */
437                             s -= (((Word32) sq * alp_16) << 1);
438
439                             if (s > 0)
440                             {
441                                 sq = sq1;
442                                 ps = ps1;
443                                 alp = alp_16;
444                                 ix = i1;
445                             }
446                         }
447                         i1 = ix;
448
449                         /*----------------------------------------------------------------*
450                          * i2 loop: 8 positions.                                          *
451                          *----------------------------------------------------------------*/
452
453                         ps0 = ps;
454
455                         /* alp0 = L_mult(alp, _1_4, pOverflow); */
456                         alp0 = (Word32) alp << 14;
457
458                         sq = -1;
459                         alp = 1;
460                         ps = 0;
461                         ix = ipos[2];
462
463                         /* initialize 4 index for next loop (see i1 loop) */
464
465                         for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
466                         {
467                             /* index increment = STEP */
468                             /* ps1 = add(ps0, dn[i2], pOverflow); */
469                             ps1 = ps0 + dn[i2];
470
471                             /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
472
473                             /* idx incr = STEP */
474                             /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
475                             alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
476
477                             /* idx incr = STEP */
478                             /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
479                             alp1 += (Word32) rr[i1][i2] << 13;
480
481                             /* idx incr = STEP */
482                             /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
483                             alp1 += (Word32) rr[i0][i2] << 13;
484
485                             /* sq1 = mult(ps1, ps1, pOverflow); */
486                             sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
487
488                             /* alp_16 = pv_round(alp1, pOverflow); */
489                             alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
490
491                             /* s = L_mult(alp, sq1, pOverflow); */
492                             s = ((Word32) alp * sq1) << 1;
493
494                             /* s = L_msu(s, sq, alp_16, pOverflow); */
495                             s -= (((Word32) sq * alp_16) << 1);
496
497                             if (s > 0)
498                             {
499                                 sq = sq1;
500                                 ps = ps1;
501                                 alp = alp_16;
502                                 ix = i2;
503                             }
504                         }
505                         i2 = ix;
506
507                         /* memorize codevector if this one
508                          * is better than the last one.
509                          */
510
511                         s = L_mult(alpk, sq, pOverflow);
512                         //s = ((Word32) alpk * sq) << 1;
513
514                         s = L_msu(s, psk, alp, pOverflow);
515                         //s -= (((Word32) psk * alp) << 1);
516
517                         if (s > 0)
518                         {
519                             psk = sq;
520                             alpk = alp;
521                             p_codvec = &codvec[0];
522
523                             *(p_codvec++) = i0;
524                             *(p_codvec++) = i1;
525                             *(p_codvec) = i2;
526                         }
527                     }
528                 }
529                 /*----------------------------------------------------------------*
530                  * Cyclic permutation of i0, i1 and i2.                           *
531                  *----------------------------------------------------------------*/
532
533                 pos = ipos[2];
534                 ipos[2] = ipos[1];
535                 ipos[1] = ipos[0];
536                 ipos[0] = pos;
537             }
538         }
539     }
540     return;
541 }
542
543 /****************************************************************************/
544
545 /*
546 ------------------------------------------------------------------------------
547  FUNCTION NAME:  build_code()
548 ------------------------------------------------------------------------------
549  INPUT AND OUTPUT DEFINITIONS
550
551  Inputs:
552     codvec[]   Array of type Word16 -- position of pulses
553     dn_sign[]  Array of type Word16 -- sign of pulses
554     h[]        Array of type Word16 -- impulse response of
555                                        weighted synthesis filter
556
557  Outputs:
558     cod[]  Array of type Word16 -- innovative code vector
559     y[]    Array of type Word16 -- filtered innovative code
560     sign[] Array of type Word16 -- sign of 3 pulses
561     pOverflow  Pointer to Flag  -- set when overflow occurs
562
563  Returns:
564     indx
565
566  Global Variables Used:
567     None
568
569  Local Variables Needed:
570     None
571
572 ------------------------------------------------------------------------------
573  FUNCTION DESCRIPTION
574
575  PURPOSE: Builds the codeword, the filtered codeword and index of the
576           codevector, based on the signs and positions of 3 pulses.
577
578 ------------------------------------------------------------------------------
579  REQUIREMENTS
580
581  None
582
583 ------------------------------------------------------------------------------
584  REFERENCES
585
586  [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
587
588 ------------------------------------------------------------------------------
589  PSEUDO-CODE
590
591 ------------------------------------------------------------------------------
592  CAUTION [optional]
593  [State any special notes, constraints or cautions for users of this function]
594
595 ------------------------------------------------------------------------------
596 */
597
598 static Word16
599 build_code(
600     Word16 codvec[],  /* i : position of pulses                            */
601     Word16 dn_sign[], /* i : sign of pulses                                */
602     Word16 cod[],     /* o : innovative code vector                        */
603     Word16 h[],       /* i : impulse response of weighted synthesis filter */
604     Word16 y[],       /* o : filtered innovative code                      */
605     Word16 sign[],    /* o : sign of 3 pulses                              */
606     Flag  *pOverflow  /* o : Flag set when overflow occurs                 */
607 )
608 {
609     Word16 i;
610     Word16 j;
611     Word16 k;
612     Word16 track;
613     Word16 index;
614     Word16 _sign[NB_PULSE];
615     Word16 indx;
616     Word16 rsign;
617
618     Word16 *p0;
619     Word16 *p1;
620     Word16 *p2;
621
622     Word32 s;
623
624     for (i = 0; i < L_CODE; i++)
625     {
626         cod[i] = 0;
627     }
628
629     indx = 0;
630     rsign = 0;
631
632     for (k = 0; k < NB_PULSE; k++)
633     {
634         i = codvec[k];  /* read pulse position */
635         j = dn_sign[i];  /* read sign           */
636
637         /* index = pos/5 */
638         /* index = mult(i, 6554, pOverflow); */
639         index = (Word16)(((Word32) i * 6554) >> 15);
640
641         /* track = pos%5 */
642         /* s = L_mult(index, 5, pOverflow); */
643         s = ((Word32) index * 5) << 1;
644
645         /* s = L_shr(s, 1, pOverflow); */
646         s >>= 1;
647
648         /* track = sub(i, (Word16) s, pOverflow); */
649         track = i - (Word16) s;
650
651         if (track == 1)
652         {
653             /* index = shl(index, 4, pOverflow); */
654             index <<= 4;
655         }
656         else if (track == 2)
657         {
658             track = 2;
659
660             /* index = shl(index, 8, pOverflow); */
661             index <<= 8;
662         }
663         else if (track == 3)
664         {
665             track = 1;
666
667             /* index = shl(index, 4, pOverflow); */
668             index <<= 4;
669
670             /* index = add(index, 8, pOverflow); */
671             index += 8;
672         }
673         else if (track == 4)
674         {
675             track = 2;
676
677             /* index = shl(index, 8, pOverflow); */
678             index <<= 8;
679
680             /* index = add(index, 128, pOverflow); */
681             index += 128;
682         }
683
684         if (j > 0)
685         {
686             cod[i] = 8191;
687             _sign[k] = 32767;
688
689             /* track = shl(1, track, pOverflow); */
690             track = 1 << track;
691
692             /* rsign = add(rsign, track, pOverflow); */
693             rsign += track;
694         }
695         else
696         {
697             cod[i] = -8192;
698             _sign[k] = (Word16) - 32768L;
699         }
700
701         /* indx = add(indx, index, pOverflow); */
702         indx += index;
703     }
704     *sign = rsign;
705
706     p0 = h - codvec[0];
707     p1 = h - codvec[1];
708     p2 = h - codvec[2];
709
710     for (i = 0; i < L_CODE; i++)
711     {
712         s = 0;
713         s =
714             L_mac(
715                 s,
716                 *p0++,
717                 _sign[0],
718                 pOverflow);
719
720         s =
721             L_mac(
722                 s,
723                 *p1++,
724                 _sign[1],
725                 pOverflow);
726
727         s =
728             L_mac(
729                 s,
730                 *p2++,
731                 _sign[2],
732                 pOverflow);
733
734         y[i] =
735             pv_round(
736                 s,
737                 pOverflow);
738     }
739
740     return indx;
741 }
742
743
744
745
746
747
748