Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / hp_max.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: hp_max.cpp
35
36 ------------------------------------------------------------------------------
37 */
38
39 /*----------------------------------------------------------------------------
40 ; INCLUDES
41 ----------------------------------------------------------------------------*/
42 #include    "hp_max.h"
43 #include    "basic_op.h"
44 #include    "cnst.h"
45 #include    "l_abs.h"
46
47 /*----------------------------------------------------------------------------
48 ; MACROS
49 ; [Define module specific macros here]
50 ----------------------------------------------------------------------------*/
51
52 /*----------------------------------------------------------------------------
53 ; DEFINES
54 ; [Include all pre-processor statements here. Include conditional
55 ; compile variables also.]
56 ----------------------------------------------------------------------------*/
57
58 /*----------------------------------------------------------------------------
59 ; LOCAL FUNCTION DEFINITIONS
60 ; [List function prototypes here]
61 ----------------------------------------------------------------------------*/
62
63 /*----------------------------------------------------------------------------
64 ; LOCAL VARIABLE DEFINITIONS
65 ; [Variable declaration - defined here and used outside this module]
66 ----------------------------------------------------------------------------*/
67
68 /*
69 ------------------------------------------------------------------------------
70  FUNCTION NAME: hp_max
71 ------------------------------------------------------------------------------
72  INPUT AND OUTPUT DEFINITIONS
73
74  Inputs:
75     corr[] = correlation vector (Word16)
76     scal_sig[] = scaled signal vector (Word16)
77     L_frame = length of frame to compute pitch (Word16
78     lag_max = maximum lag (Word16)
79     lag_min = minimum lag (Word16)
80     cor_hp_max = pointer to max high-pass filtered norm. correlation (Word16)
81     pOverflow = pointer to overflow (Flag)
82
83  Outputs:
84     cor_hp_max contains max high-pass filtered norm. correlation (Word16)
85     pOverflow -> 1 if the maximum correlation computation resulted in overflow
86
87  Returns:
88     0 (Word16)
89
90  Global Variables Used:
91     None
92
93  Local Variables Needed:
94     None
95
96 ------------------------------------------------------------------------------
97  FUNCTION DESCRIPTION
98
99  This function finds the maximum high-pass filtered correlation of scal_sig[]
100  in a given delay range.
101
102  The correlation is given by
103     corr[t] = <scal_sig[n],scal_sig[n-t]>,  t=lag_min,...,lag_max
104  The functions outputs the maximum high-pass filtered correlation after
105  normalization.
106
107 ------------------------------------------------------------------------------
108  REQUIREMENTS
109
110  None
111
112 ------------------------------------------------------------------------------
113  REFERENCES
114
115  [1] hp_max.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
116
117 ------------------------------------------------------------------------------
118  PSEUDO-CODE
119
120 Word16 hp_max (
121     Word32 corr[],      // i   : correlation vector
122     Word16 scal_sig[],  // i   : scaled signal
123     Word16 L_frame,     // i   : length of frame to compute pitch
124     Word16 lag_max,     // i   : maximum lag
125     Word16 lag_min,     // i   : minimum lag
126     Word16 *cor_hp_max) // o   : max high-pass filtered norm. correlation
127 {
128     Word16 i;
129     Word16 *p, *p1;
130     Word32 max, t0, t1;
131     Word16 max16, t016, cor_max;
132     Word16 shift, shift1, shift2;
133
134     max = MIN_32;
135     t0 = 0L;
136 * The reference ETSI code uses a global flag for Overflow inside the math functions
137 * saturate(). In the actual implementation a pointer to Overflow flag is passed in
138 * as a parameter to the function
139
140     for (i = lag_max-1; i > lag_min; i--)
141     {
142        // high-pass filtering
143        t0 = L_sub (L_sub(L_shl(corr[-i], 1), corr[-i-1]), corr[-i+1]);
144        t0 = L_abs (t0);
145
146        if (L_sub (t0, max) >= 0)
147        {
148           max = t0;
149        }
150     }
151
152     // compute energy
153     p = scal_sig;
154     p1 = &scal_sig[0];
155     t0 = 0L;
156     for (i = 0; i < L_frame; i++, p++, p1++)
157     {
158        t0 = L_mac (t0, *p, *p1);
159     }
160
161     p = scal_sig;
162     p1 = &scal_sig[-1];
163     t1 = 0L;
164     for (i = 0; i < L_frame; i++, p++, p1++)
165     {
166        t1 = L_mac (t1, *p, *p1);
167     }
168
169     // high-pass filtering
170     t0 = L_sub(L_shl(t0, 1), L_shl(t1, 1));
171     t0 = L_abs (t0);
172
173     // max/t0
174     shift1 = sub(norm_l(max), 1);
175     max16  = extract_h(L_shl(max, shift1));
176     shift2 = norm_l(t0);
177     t016 =  extract_h(L_shl(t0, shift2));
178
179     if (t016 != 0)
180     {
181        cor_max = div_s(max16, t016);
182     }
183     else
184     {
185        cor_max = 0;
186     }
187
188     shift = sub(shift1, shift2);
189
190     if (shift >= 0)
191     {
192        *cor_hp_max = shr(cor_max, shift); // Q15
193     }
194     else
195     {
196        *cor_hp_max = shl(cor_max, negate(shift)); // Q15
197     }
198
199     return 0;
200 }
201
202
203 ------------------------------------------------------------------------------
204  CAUTION [optional]
205  [State any special notes, constraints or cautions for users of this function]
206
207 ------------------------------------------------------------------------------
208 */
209
210 /*----------------------------------------------------------------------------
211 ; FUNCTION CODE
212 ----------------------------------------------------------------------------*/
213 Word16 hp_max(
214     Word32 corr[],      /* i   : correlation vector.                      */
215     Word16 scal_sig[],  /* i   : scaled signal.                           */
216     Word16 L_frame,     /* i   : length of frame to compute pitch         */
217     Word16 lag_max,     /* i   : maximum lag                              */
218     Word16 lag_min,     /* i   : minimum lag                              */
219     Word16 *cor_hp_max, /* o   : max high-pass filtered norm. correlation */
220     Flag   *pOverflow   /* i/o : overflow Flag                            */
221 )
222 {
223     Word16 i;
224     Word16 *p, *p1;
225     Word32 max, t0, t1;
226     Word16 max16, t016, cor_max;
227     Word16 shift, shift1, shift2;
228     Word32 L_temp;
229
230     max = MIN_32;
231     t0 = 0L;
232
233     for (i = lag_max - 1; i > lag_min; i--)
234     {
235         /* high-pass filtering */
236         t0 = L_shl(corr[-i], 1, pOverflow);
237         L_temp = L_sub(t0, corr[-i-1], pOverflow);
238         t0 = L_sub(L_temp, corr[-i+1], pOverflow);
239         t0 = L_abs(t0);
240
241         if (t0 >= max)
242         {
243             max = t0;
244         }
245     }
246
247     /* compute energy */
248     p = scal_sig;
249     p1 = &scal_sig[0];
250     t0 = 0L;
251     for (i = 0; i < L_frame; i++, p++, p1++)
252     {
253         t0 = L_mac(t0, *p, *p1, pOverflow);
254     }
255
256     p = scal_sig;
257     p1 = &scal_sig[-1];
258     t1 = 0L;
259     for (i = 0; i < L_frame; i++, p++, p1++)
260     {
261         t1 = L_mac(t1, *p, *p1, pOverflow);
262     }
263
264     /* high-pass filtering */
265     L_temp = L_shl(t0, 1, pOverflow);
266     t1 = L_shl(t1, 1, pOverflow);
267     t0 = L_sub(L_temp, t1, pOverflow);
268     t0 = L_abs(t0);
269
270     /* max/t0 */
271     /*  shift1 = sub(norm_l(max), 1);
272         max16  = extract_h(L_shl(max, shift1));
273         shift2 = norm_l(t0);
274         t016 =  extract_h(L_shl(t0, shift2));   */
275
276     t016 = norm_l(max);
277     shift1 = t016 - 1;
278
279     L_temp = L_shl(max, shift1, pOverflow);
280     max16  = (Word16)(L_temp >> 16);
281
282     shift2 = norm_l(t0);
283     L_temp = L_shl(t0, shift2, pOverflow);
284     t016 = (Word16)(L_temp >> 16);
285
286     if (t016 != 0)
287     {
288         cor_max = div_s(max16, t016);
289     }
290     else
291     {
292         cor_max = 0;
293     }
294
295     shift = shift1 - shift2;
296
297     if (shift >= 0)
298     {
299         *cor_hp_max = shr(cor_max, shift, pOverflow); /* Q15 */
300     }
301     else
302     {
303         *cor_hp_max = shl(cor_max, negate(shift), pOverflow); /* Q15 */
304     }
305
306     return 0;
307 }
308