OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / codecs / aacdec / apply_tns.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
20  Pathname: apply_tns.c
21
22 ------------------------------------------------------------------------------
23  INPUT AND OUTPUT DEFINITIONS
24
25  Inputs:
26     coef =       Array of input coefficients.
27                  [Int32 *, length 1024]
28
29     q_format   = Array of q-formats, one per scalefactor band, for the
30                  entire frame.  In the case of tns_inv_filter, only the
31                  first element is used, since the input to tns_inv_filter
32                  is all of the same q-format.
33                  [Int * const, length MAX_SFB]
34
35     pFrameInfo = Pointer to structure that holds information about each group.
36                  (long block flag, number of windows, scalefactor bands
37                   per group, etc.)
38                  [const FrameInfo * const]
39
40     pTNS_frame_info = pointer to structure containing the details on each
41                       TNS filter (order, filter coefficients,
42                       coefficient res., etc.)
43                       [TNS_frame_info * const]
44
45     inverse_flag   = TRUE  if inverse filter is to be applied.
46                      FALSE if forward filter is to be applied.
47                      [Bool]
48
49     scratch_Int_buffer = Pointer to scratch memory to store the
50                            filter's state memory.  Used by both
51                            tns_inv_filter.
52                            [Int *, length TNS_MAX_ORDER]
53
54  Local Stores/Buffers/Pointers Needed:
55     None
56
57  Global Stores/Buffers/Pointers Needed:
58     None
59
60  Outputs:
61     None
62
63  Pointers and Buffers Modified:
64     coef[]   = TNS altered data.
65     q_format = q-formats in TNS scalefactor bands may be modified.
66
67  Local Stores Modified:
68     None
69
70  Global Stores Modified:
71     None
72
73 ------------------------------------------------------------------------------
74  FUNCTION DESCRIPTION
75
76     This function applies either the TNS forward or TNS inverse filter, based
77     on inverse_flag being FALSE or TRUE, respectively.
78
79     For the TNS forward filter, the data fed into tns_ar_filter is normalized
80     all to the same q-format.
81
82 ------------------------------------------------------------------------------
83  REQUIREMENTS
84
85     The input, coef, should use all 32-bits, else the scaling by tns_ar_filter
86     may eliminate the data.
87
88 ------------------------------------------------------------------------------
89  REFERENCES
90
91  (1) ISO/IEC 14496-3:1999(E)
92      Part 3
93         Subpart 4.6.8 (Temporal Noise Shaping)
94
95 ------------------------------------------------------------------------------
96  PSEUDO-CODE
97
98     NO PSEUDO-CODE
99
100 ------------------------------------------------------------------------------
101  RESOURCES USED
102    When the code is written for a specific target processor
103      the resources used should be documented below.
104
105  STACK USAGE: [stack count for this module] + [variable to represent
106           stack usage for each subroutine called]
107
108      where: [stack usage variable] = stack usage for [subroutine
109          name] (see [filename].ext)
110
111  DATA MEMORY USED: x words
112
113  PROGRAM MEMORY USED: x words
114
115  CLOCK CYCLES: [cycle count equation for this module] + [variable
116            used to represent cycle count for each subroutine
117            called]
118
119      where: [cycle count variable] = cycle count for [subroutine
120         name] (see [filename].ext)
121
122 ------------------------------------------------------------------------------
123 */
124
125 /*----------------------------------------------------------------------------
126 ; INCLUDES
127 ----------------------------------------------------------------------------*/
128 #include "pv_audio_type_defs.h"
129 #include "s_tns_frame_info.h"
130 #include "s_tnsfilt.h"
131 #include "s_frameinfo.h"
132 #include "tns_inv_filter.h"
133 #include "tns_ar_filter.h"
134 #include "apply_tns.h"
135
136 /*----------------------------------------------------------------------------
137 ; MACROS
138 ; Define module specific macros here
139 ----------------------------------------------------------------------------*/
140
141 /*----------------------------------------------------------------------------
142 ; DEFINES
143 ; Include all pre-processor statements here. Include conditional
144 ; compile variables also.
145 ----------------------------------------------------------------------------*/
146
147 /*----------------------------------------------------------------------------
148 ; LOCAL FUNCTION DEFINITIONS
149 ; Function Prototype declaration
150 ----------------------------------------------------------------------------*/
151
152 /*----------------------------------------------------------------------------
153 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
154 ; Variable declaration - defined here and used outside this module
155 ----------------------------------------------------------------------------*/
156
157 /*----------------------------------------------------------------------------
158 ; EXTERNAL FUNCTION REFERENCES
159 ; Declare functions defined elsewhere and referenced in this module
160 ----------------------------------------------------------------------------*/
161
162 /*----------------------------------------------------------------------------
163 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
164 ; Declare variables used in this module but defined elsewhere
165 ----------------------------------------------------------------------------*/
166
167 /*----------------------------------------------------------------------------
168 ; FUNCTION CODE
169 ----------------------------------------------------------------------------*/
170
171 void apply_tns(
172     Int32                  coef[],
173     Int                    q_format[],
174     const FrameInfo      * const pFrameInfo,
175     TNS_frame_info * const pTNS_frame_info,
176     const Bool                   inverse_flag,
177     Int32                  scratch_Int_buffer[])
178 {
179     Int num_tns_bands;
180     Int num_TNS_coef;
181
182     Int f;
183
184     Int tempInt;
185     Int tempInt2;
186
187     Int sfb_per_win;
188     Int sfbWidth;
189
190     Int coef_per_win;
191     Int min_q;
192     Int win;
193
194     Int32 *pCoef = coef;
195     Int32 *pTempCoef;
196
197     Int   *pStartQformat = q_format;
198
199     Int   *pQformat;
200     Int32 *pLpcCoef;
201
202     Int sfb_offset;
203
204     const Int16 *pWinSfbTop;
205
206     TNSfilt *pFilt;
207
208     coef_per_win = pFrameInfo->coef_per_win[0];
209     sfb_per_win  = pFrameInfo->sfb_per_win[0];
210
211     win = 0;
212
213     pLpcCoef = pTNS_frame_info->lpc_coef;
214
215     pFilt = pTNS_frame_info->filt;
216
217     do
218     {
219         for (f = pTNS_frame_info->n_filt[win]; f > 0; f--)
220         {
221             /* Skip to the next filter if the order is 0 */
222             tempInt = pFilt->order;
223
224             if (tempInt > 0)
225             {
226                 /*
227                  * Do not call tns_ar_filter or tns_inv_filter
228                  * if the difference
229                  * between start_coef and stop_stop is <= 0.
230                  *
231                  */
232                 num_TNS_coef = (pFilt->stop_coef - pFilt->start_coef);
233
234                 if (num_TNS_coef > 0)
235                 {
236                     if (inverse_flag != FALSE)
237                     {
238                         tns_inv_filter(
239                             &(pCoef[pFilt->start_coef]),
240                             num_TNS_coef,
241                             pFilt->direction,
242                             pLpcCoef,
243                             pFilt->q_lpc,
244                             pFilt->order,
245                             scratch_Int_buffer);
246                     }
247                     else
248                     {
249                         num_tns_bands = (pFilt->stop_band - pFilt->start_band);
250
251                         /*
252                          * pQformat is initialized only once.
253                          *
254                          * Here is how TNS is applied on scalefactor bands
255                          *
256                          * [0][1][2][3][4][5][6][7][8]
257                          *  |                        \
258                          * start_band               stop_band
259                          *
260                          * In this example, TNS would be applied to 8
261                          * scalefactor bands, 0-7.
262                          *
263                          * pQformat is initially set to &(pStartQformat[8])
264                          *
265                          * 1st LOOP
266                          *      Entry: pQformat = &(pStartQformat[8])
267                          *
268                          *      pQformat is pre-decremented 8 times in the
269                          *      search for min_q
270                          *
271                          *      Exit:  pQformat = &(pStartQformat[0])
272                          *
273                          * 2nd LOOP
274                          *      Entry: pQformat = &(pStartQformat[0])
275                          *
276                          *      pQformat is post-incremented 8 times in the
277                          *      normalization of the data loop.
278                          *
279                          *      Exit:  pQformat = &(pStartQformat[8]
280                          *
281                          *
282                          * shift_amt = tns_ar_filter(...)
283                          *
284                          * 3rd LOOP
285                          *      Entry: pQformat = &(pStartQformat[8])
286                          *
287                          *      pQformat is pre-decremented 8 times in the
288                          *      adjustment of the q-format to min_q - shift_amt
289                          *
290                          *      Exit:  pQformat = &(pStartQformat[0])
291                          *
292                          */
293
294                         pQformat =
295                             &(pStartQformat[pFilt->stop_band]);
296
297                         /*
298                          * Scan the array of q-formats and find the minimum over
299                          * the range where the filter is to be applied.
300                          *
301                          * At the end of this scan,
302                          * pQformat = &(q-format[pFilt->start_band]);
303                          *
304                          */
305
306                         min_q = INT16_MAX;
307
308                         for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
309                         {
310                             tempInt2 = *(--pQformat);
311
312                             if (tempInt2 < min_q)
313                             {
314                                 min_q = tempInt2;
315                             }
316                         } /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
317
318                         /*
319                          * Set up the pointers so we can index into coef[]
320                          * on a scalefactor band basis.
321                          */
322                         tempInt = pFilt->start_band;
323
324                         tempInt--;
325
326                         /* Initialize sfb_offset and pWinSfbTop */
327                         if (tempInt >= 0)
328                         {
329                             pWinSfbTop =
330                                 &(pFrameInfo->win_sfb_top[win][tempInt]);
331
332                             sfb_offset = *(pWinSfbTop++);
333                         }
334                         else
335                         {
336                             pWinSfbTop = pFrameInfo->win_sfb_top[win];
337                             sfb_offset = 0;
338                         }
339
340                         pTempCoef = pCoef + pFilt->start_coef;
341
342                         /* Scale the data in the TNS bands to min_q q-format */
343                         for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
344                         {
345                             sfbWidth  = *(pWinSfbTop++) - sfb_offset;
346
347                             sfb_offset += sfbWidth;
348
349                             tempInt2 = *(pQformat++) - min_q;
350
351                             /*
352                              * This should zero out the data in one scalefactor
353                              * band if it is so much less than the neighboring
354                              * scalefactor bands.
355                              *
356                              * The only way this "should" happen is if one
357                              * scalefactor band contains zero data.
358                              *
359                              * Zero data can be of any q-format, but we always
360                              * set it very high to avoid the zero-data band being
361                              * picked as the one to normalize to in the scan for
362                              * min_q.
363                              *
364                              */
365                             if (tempInt2 > 31)
366                             {
367                                 tempInt2 = 31;
368                             }
369
370                             for (sfbWidth >>= 2; sfbWidth > 0; sfbWidth--)
371                             {
372                                 *(pTempCoef++) >>= tempInt2;
373                                 *(pTempCoef++) >>= tempInt2;
374                                 *(pTempCoef++) >>= tempInt2;
375                                 *(pTempCoef++) >>= tempInt2;
376                             }
377
378                         } /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
379
380                         tempInt2 =
381                             tns_ar_filter(
382                                 &(pCoef[pFilt->start_coef]),
383                                 num_TNS_coef,
384                                 pFilt->direction,
385                                 pLpcCoef,
386                                 pFilt->q_lpc,
387                                 pFilt->order);
388
389                         /*
390                          * Update the q-format for all the scalefactor bands
391                          * taking into account the adjustment caused by
392                          * tns_ar_filter
393                          */
394
395                         min_q -= tempInt2;
396
397                         for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
398                         {
399                             *(--pQformat) = min_q;
400                         }
401
402                     } /* if (inverse_flag != FALSE) */
403
404                 } /* if (num_TNS_coef > 0) */
405
406                 pLpcCoef += pFilt->order;
407
408             } /* if (tempInt > 0) */
409
410             pFilt++;
411
412         } /* for (f = pTNSinfo->n_filt; f > 0; f--) */
413
414         pCoef += coef_per_win;
415         pStartQformat += sfb_per_win;
416
417         win++;
418
419     }
420     while (win < pFrameInfo->num_win);
421
422     return;
423
424 } /* apply_tns() */