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