Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / cor_h.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: cor_h.cpp
35
36 ------------------------------------------------------------------------------
37 */
38
39 /*----------------------------------------------------------------------------
40 ; INCLUDES
41 ----------------------------------------------------------------------------*/
42 #include "cnst.h"
43 #include "cor_h.h"
44 #include "basicop_malloc.h"
45 #include "inv_sqrt.h"
46 #include "basic_op.h"
47
48 /*----------------------------------------------------------------------------
49 ; MACROS
50 ; Define module specific macros here
51 ----------------------------------------------------------------------------*/
52
53 /*----------------------------------------------------------------------------
54 ; DEFINES
55 ; Include all pre-processor statements here. Include conditional
56 ; compile variables also.
57 ----------------------------------------------------------------------------*/
58
59 /*----------------------------------------------------------------------------
60 ; LOCAL FUNCTION DEFINITIONS
61 ; Function Prototype declaration
62 ----------------------------------------------------------------------------*/
63
64 /*----------------------------------------------------------------------------
65 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
66 ; Variable declaration - defined here and used outside this module
67 ----------------------------------------------------------------------------*/
68
69 /*
70 ------------------------------------------------------------------------------
71  FUNCTION NAME: cor_h
72 ------------------------------------------------------------------------------
73  INPUT AND OUTPUT DEFINITIONS
74
75  Inputs:
76     h = vector containing the impulse response of the weighted synthesis
77         filter; vector contents are of type Word16; vector length is
78         2 * L_SUBFR
79     sign = vector containing the sign information for the correlation
80            values; vector contents are of type Word16; vector length is
81            L_CODE
82     rr = autocorrelation matrix; matrix contents are of type Word16;
83          matrix dimension is L_CODE by L_CODE
84
85  Outputs:
86     rr contents are the newly calculated autocorrelation values
87
88  Returns:
89     None
90
91  Global Variables Used:
92     None
93
94  Local Variables Needed:
95     None
96
97 ------------------------------------------------------------------------------
98  FUNCTION DESCRIPTION
99
100  This function computes correlations of the impulse response (h) needed for
101  the codebook search, and includes the sign information into the correlations.
102
103  The correlations are given by:
104     rr[i][j] = sum_{n=i}^{L-1} h[n-i] h[n-j];   i>=j; i,j=0,...,L-1
105
106  The sign information is included by:
107     rr[i][j] = rr[i][j]*sign[i]*sign[j]
108
109 ------------------------------------------------------------------------------
110  REQUIREMENTS
111
112  None
113
114 ------------------------------------------------------------------------------
115  REFERENCES
116
117  cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
118
119 ------------------------------------------------------------------------------
120  PSEUDO-CODE
121
122 void cor_h (
123     Word16 h[],         // (i) : impulse response of weighted synthesis
124                                  filter
125     Word16 sign[],      // (i) : sign of d[n]
126     Word16 rr[][L_CODE] // (o) : matrix of autocorrelation
127 )
128 {
129     Word16 i, j, k, dec, h2[L_CODE];
130     Word32 s;
131
132     // Scaling for maximum precision
133
134     s = 2;
135     for (i = 0; i < L_CODE; i++)
136         s = L_mac (s, h[i], h[i]);
137
138     j = sub (extract_h (s), 32767);
139     if (j == 0)
140     {
141         for (i = 0; i < L_CODE; i++)
142         {
143             h2[i] = shr (h[i], 1);
144         }
145     }
146     else
147     {
148         s = L_shr (s, 1);
149         k = extract_h (L_shl (Inv_sqrt (s), 7));
150         k = mult (k, 32440);                     // k = 0.99*k
151
152         for (i = 0; i < L_CODE; i++)
153         {
154             h2[i] = pv_round (L_shl (L_mult (h[i], k), 9));
155         }
156     }
157
158     // build matrix rr[]
159     s = 0;
160     i = L_CODE - 1;
161     for (k = 0; k < L_CODE; k++, i--)
162     {
163         s = L_mac (s, h2[k], h2[k]);
164         rr[i][i] = pv_round (s);
165     }
166
167     for (dec = 1; dec < L_CODE; dec++)
168     {
169         s = 0;
170         j = L_CODE - 1;
171         i = sub (j, dec);
172         for (k = 0; k < (L_CODE - dec); k++, i--, j--)
173         {
174             s = L_mac (s, h2[k], h2[k + dec]);
175             rr[j][i] = mult (pv_round (s), mult (sign[i], sign[j]));
176             rr[i][j] = rr[j][i];
177         }
178     }
179 }
180
181 ---------------------------------------------------------------------------
182  CAUTION [optional]
183  [State any special notes, constraints or cautions for users of this function]
184
185 ------------------------------------------------------------------------------
186 */
187
188 void cor_h(
189     Word16 h[],          /* (i) : impulse response of weighted synthesis
190                                   filter                                  */
191     Word16 sign[],       /* (i) : sign of d[n]                            */
192     Word16 rr[][L_CODE], /* (o) : matrix of autocorrelation               */
193     Flag  *pOverflow
194 )
195 {
196     register Word16 i;
197     register Word16 dec;
198
199     Word16 h2[L_CODE];
200     Word32 s;
201     Word32 s2;
202     Word16 tmp1;
203     Word16 tmp2;
204     Word16 tmp11;
205     Word16 tmp22;
206
207     Word16 *p_h;
208     Word16 *p_h2;
209     Word16 *rr1;
210     Word16 *rr2;
211     Word16 *rr3;
212     Word16 *p_rr_ref1;
213     Word16 *p_sign1;
214     Word16 *p_sign2;
215
216     /* Scaling for maximum precision */
217
218     /* Initialize accumulator to 1 since left shift happens    */
219     /* after the accumulation of the sum of squares (original  */
220     /* code initialized s to 2)                                */
221     s = 1;
222     p_h = h;
223
224     for (i = (L_CODE >> 1); i != 0 ; i--)
225     {
226         tmp1 = *(p_h++);
227         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
228         tmp1 = *(p_h++);
229         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
230
231     }
232
233     s <<= 1;
234
235     if (s & MIN_32)
236     {
237         p_h2 = h2;
238         p_h  = h;
239
240         for (i = (L_CODE >> 1); i != 0; i--)
241         {
242             *(p_h2++) =  *(p_h++)  >> 1;
243             *(p_h2++) =  *(p_h++)  >> 1;
244         }
245     }
246     else
247     {
248
249         s >>= 1;
250
251         s = Inv_sqrt(s, pOverflow);
252
253         if (s < (Word32) 0x00ffffffL)
254         {
255             /* k = 0.99*k */
256             dec = (Word16)(((s >> 9) * 32440) >> 15);
257         }
258         else
259         {
260             dec = 32440;  /* 0.99 */
261         }
262
263         p_h  = h;
264         p_h2 = h2;
265
266         for (i = (L_CODE >> 1); i != 0; i--)
267         {
268             *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
269             *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
270         }
271     }
272     /* build matrix rr[] */
273
274     s = 0;
275
276     p_h2 = h2;
277
278     rr1 = &rr[L_CODE-1][L_CODE-1];
279
280     for (i = L_CODE >> 1; i != 0 ; i--)
281     {
282         tmp1   = *(p_h2++);
283         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
284         *rr1 = (Word16)((s + 0x00004000L) >> 15);
285         rr1 -= (L_CODE + 1);
286         tmp1   = *(p_h2++);
287         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
288         *rr1 = (Word16)((s + 0x00004000L) >> 15);
289         rr1 -= (L_CODE + 1);
290     }
291
292
293     p_rr_ref1 = rr[L_CODE-1];
294
295     for (dec = 1; dec < L_CODE; dec += 2)
296     {
297         rr1 = &p_rr_ref1[L_CODE-1-dec];
298
299         rr2 = &rr[L_CODE-1-dec][L_CODE-1];
300         rr3 = &rr[L_CODE-1-(dec+1)][L_CODE-1];
301
302         s  = 0;
303         s2 = 0;
304
305         p_sign1 = &sign[L_CODE - 1];
306         p_sign2 = &sign[L_CODE - 1 - dec];
307
308         p_h2 = h2;
309         p_h  = &h2[dec];
310
311         for (i = (L_CODE - dec - 1); i != 0 ; i--)
312         {
313             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h++), s);
314             s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2++), (Word32) * (p_h), s2);
315
316             tmp1  = (Word16)((s + 0x00004000L) >> 15);
317             tmp11 = (Word16)((s2 + 0x00004000L) >> 15);
318
319             tmp2  = ((Word32) * (p_sign1) * *(p_sign2--)) >> 15;
320             tmp22 = ((Word32) * (p_sign1--) * *(p_sign2)) >> 15;
321
322             *rr2 = ((Word32) tmp1 * tmp2) >> 15;
323             *(rr1--) = *rr2;
324             *rr1 = ((Word32) tmp11 * tmp22) >> 15;
325             *rr3 = *rr1;
326
327             rr1 -= (L_CODE);
328             rr2 -= (L_CODE + 1);
329             rr3 -= (L_CODE + 1);
330
331         }
332
333         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h), s);
334
335         tmp1 = (Word16)((s + 0x00004000L) >> 15);
336
337         tmp2 = ((Word32) * (p_sign1) * *(p_sign2)) >> 15;
338         *rr1 = ((Word32) tmp1 * tmp2) >> 15;
339
340         *rr2 = *rr1;
341
342         rr1 -= (L_CODE + 1);
343         rr2 -= (L_CODE + 1);
344
345     }
346
347     return;
348
349 }
350