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