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
171void 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() */
425