Home | History | Annotate | Download | only in aacdec
      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: tns_inv_filter.c
     21 
     22 ------------------------------------------------------------------------------
     23  REVISION HISTORY
     24 
     25  Description: Changes made per review comments.
     26 
     27  Description: As requested by JT, the q-format for the LPC coefficients is
     28  now passed via the parameter lpc_qformat.
     29 
     30  Description: For speed, the calculation of the shift amount was pulled
     31  outside of the loop.
     32 
     33  Description:
     34     Modified casting to ensure proper operations for different platforms
     35 
     36  Description:
     37     Simplified MAC operations for filter by eliminating extra variables
     38 
     39  Who:                       Date:
     40  Description:
     41 
     42 ------------------------------------------------------------------------------
     43  INPUT AND OUTPUT DEFINITIONS
     44 
     45  Inputs:
     46 
     47     coef           = spectral input to be shaped by the filter.
     48                      Fixed point format
     49                      [Int32[], length = num_coef]
     50 
     51     num_coef       = length of spec array.
     52                      [const Int]
     53 
     54     direction      = direction for application of tns filter.
     55                      +1 applies forward filter
     56                      (first input to filter is coef[0])
     57                      -1 applies reversed filter
     58                      (first input to filter is coef[num_coef-1])
     59                      [const Int]
     60 
     61     lpc            = array of lpc coefficients.
     62                      Fixed point format Q-11
     63                      [const Int[], length = TNS_MAX_ORDER]
     64 
     65     lpc_qformat    = The q-format of the lpc coefficients.
     66                      [const Int]
     67 
     68     order          = order of the TNS filter (Range of 1 : TNS_MAX_ORDER)
     69                      [const Int]
     70 
     71     scratch_memory = scratch_memory needed for filter operation
     72                      [Int[], length = TNS_MAX_ORDER]
     73 
     74  Local Stores/Buffers/Pointers Needed:
     75     None
     76 
     77  Global Stores/Buffers/Pointers Needed:
     78     None
     79 
     80  Outputs:
     81     None
     82 
     83  Pointers and Buffers Modified:
     84     coef = contains spectral data after application of TNS filter
     85            q-format is not modified.
     86            Int32 array
     87            length = num_coef
     88 
     89  Local Stores Modified:
     90     None
     91 
     92  Global Stores Modified:
     93     None
     94 
     95 ------------------------------------------------------------------------------
     96  FUNCTION DESCRIPTION
     97 
     98     A block of spectral data (Int32 coef[]) of length (const Int num_coef)
     99     is processed by a simple all-zero filter defined by
    100     LPC coefficients passed via (const Int lpc[])
    101 
    102     TNS filter equation
    103         y(n) =  x(n) + lpc(2)*x(n-1) + ... + lpc(order+1)*x(n-order)
    104 
    105     The filter calculation is performed in place, i.e. the output is passed
    106     back to the calling function via (Int32 coef[])
    107 
    108     In order to avoid overflow, the filter input (Int32 coef[]) must utilize
    109     only the lower 16-bits.  The upper 16-bits must be available.
    110 
    111     The filter's order is defined by the variable (const Int order)
    112 
    113     The direction of the filter's application is defined by
    114     (const Int direction)
    115 
    116 ------------------------------------------------------------------------------
    117  REQUIREMENTS
    118 
    119     [Int32 coef] must store no more than 16 bits of data.
    120 
    121     This is required to utilize methods that do not change the q-format of
    122     the input data [Int32 coef], and to make use of a fast
    123     16 x 16 bit multiply.
    124 
    125     This function should not be called for order <= 0.
    126 
    127     This function must not be called with lpc_qformat < 5
    128 ------------------------------------------------------------------------------
    129  REFERENCES
    130 
    131  (1) ISO/IEC 14496-3:1999(E)
    132      Part 3
    133         Subpart 4.6.6.4.1 (LTP with TNS)
    134         Subpart 4.6.8 (Temporal Noise Shaping)
    135 
    136  (2) MPEG-2 NBC Audio Decoder
    137    "This software module was originally developed by AT&T, Dolby
    138    Laboratories, Fraunhofer Gesellschaft IIS in the course of development
    139    of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
    140    3. This software module is an implementation of a part of one or more
    141    MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
    142    Audio standard. ISO/IEC  gives users of the MPEG-2 NBC/MPEG-4 Audio
    143    standards free license to this software module or modifications thereof
    144    for use in hardware or software products claiming conformance to the
    145    MPEG-2 NBC/MPEG-4 Audio  standards. Those intending to use this software
    146    module in hardware or software products are advised that this use may
    147    infringe existing patents. The original developer of this software
    148    module and his/her company, the subsequent editors and their companies,
    149    and ISO/IEC have no liability for use of this software module or
    150    modifications thereof in an implementation. Copyright is not released
    151    for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original
    152    developer retains full right to use the code for his/her  own purpose,
    153    assign or donate the code to a third party and to inhibit third party
    154    from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
    155    This copyright notice must be included in all copies or derivative
    156    works."
    157    Copyright(c)1996.
    158 
    159 ------------------------------------------------------------------------------
    160  PSEUDO-CODE
    161 
    162     IF (direction == -1)
    163     THEN
    164         pCoef = pCoef + (num_coef - 1);
    165     END IF
    166 
    167     FOR (i = order; i > 0; i--)
    168 
    169         *(pFilterInput) = 0;
    170         pFilterInput = pFilterInput + 1;
    171 
    172     END FOR
    173 
    174     wrap_point = 0;
    175 
    176     shift_amt  = (lpc_qformat - 5);
    177 
    178     FOR (i = num_coef; i > 0; i--)
    179 
    180         pLPC = lpc;
    181 
    182         mult = 0;
    183 
    184         FOR (j = wrap_point; j>0; j--)
    185 
    186            tempInt32 = (Int32)(*(pLPC) * *(pFilterInput));
    187            tempInt32 = tempInt32 >> 5;
    188 
    189            mult = mult + tempInt32;
    190 
    191            pFilterInput = pFilterInput + 1;
    192            pLPC = pLPC + 1;
    193 
    194         ENDFOR
    195 
    196         pFilterInput = scratch_memory;
    197 
    198         FOR (j = (order - wrap_point); j>0; j--)
    199 
    200            tempInt32 = (Int32)(*(pLPC) * *(pFilterInput));
    201            tempInt32 = tempInt32 >> 5;
    202 
    203            mult = mult + tempInt32;
    204 
    205            pFilterInput = pFilterInput + 1;
    206            pLPC = pLPC + 1;
    207 
    208         ENDFOR
    209 
    210         pFilterInput = pFilterInput - 1;
    211         *(pFilterInput) = (Int)(*pCoef);
    212 
    213         mult = mult >> shift_amt;
    214 
    215         *(pCoef) = *(pCoef) + mult;
    216 
    217         pCoef = pCoef + direction;
    218 
    219         wrap_point = wrap_point + 1;
    220 
    221         IF (wrap_point == order)
    222         THEN
    223             wrap_point = 0;
    224         END IF
    225 
    226     END FOR
    227 
    228 ------------------------------------------------------------------------------
    229  RESOURCES USED
    230 
    231    When the code is written for a specific target processor
    232      the resources used should be documented below.
    233 
    234  STACK USAGE: [stack count for this module] + [variable to represent
    235           stack usage for each subroutine called]
    236 
    237      where: [stack usage variable] = stack usage for [subroutine
    238          name] (see [filename].ext)
    239 
    240  DATA MEMORY USED: x words
    241 
    242  PROGRAM MEMORY USED: x words
    243 
    244  CLOCK CYCLES: [cycle count equation for this module] + [variable
    245            used to represent cycle count for each subroutine
    246            called]
    247 
    248      where: [cycle count variable] = cycle count for [subroutine
    249         name] (see [filename].ext)
    250 
    251 ------------------------------------------------------------------------------
    252 */
    253 
    254 /*----------------------------------------------------------------------------
    255 ; INCLUDES
    256 ----------------------------------------------------------------------------*/
    257 #include "pv_audio_type_defs.h"
    258 #include "tns_inv_filter.h"
    259 #include "fxp_mul32.h"
    260 
    261 /*----------------------------------------------------------------------------
    262 ; MACROS
    263 ; Define module specific macros here
    264 ----------------------------------------------------------------------------*/
    265 
    266 /*----------------------------------------------------------------------------
    267 ; DEFINES
    268 ; Include all pre-processor statements here. Include conditional
    269 ; compile variables also.
    270 ----------------------------------------------------------------------------*/
    271 
    272 /*----------------------------------------------------------------------------
    273 ; LOCAL FUNCTION DEFINITIONS
    274 ; Function Prototype declaration
    275 ----------------------------------------------------------------------------*/
    276 
    277 /*----------------------------------------------------------------------------
    278 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
    279 ; Variable declaration - defined here and used outside this module
    280 ----------------------------------------------------------------------------*/
    281 
    282 /*----------------------------------------------------------------------------
    283 ; EXTERNAL FUNCTION REFERENCES
    284 ; Declare functions defined elsewhere and referenced in this module
    285 ----------------------------------------------------------------------------*/
    286 
    287 /*----------------------------------------------------------------------------
    288 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
    289 ; Declare variables used in this module but defined elsewhere
    290 ----------------------------------------------------------------------------*/
    291 
    292 /*----------------------------------------------------------------------------
    293 ; FUNCTION CODE
    294 ----------------------------------------------------------------------------*/
    295 
    296 void tns_inv_filter(
    297     Int32 coef[],
    298     const Int num_coef,
    299     const Int direction,
    300     const Int32 lpc[],
    301     const Int lpc_qformat,
    302     const Int order,
    303     Int32 scratch_memory[])
    304 {
    305 
    306     Int i;
    307     Int j;
    308     Int shift_amt;
    309     Int wrap_point;
    310 
    311     Int32 mult;
    312 
    313     /*
    314      * Circular buffer to hold the filter's input
    315      *
    316      * (x[n-1],x[n-2],x[n-3],etc.)
    317      *
    318      * This scratch space is necessary, because
    319      * the filter's output is returned in-place.
    320      *
    321      * pFilterInput and pLPC should take advantage
    322      * of any special circular buffer instructions
    323      * if this code is hand-optimized in assembly.
    324      *
    325      */
    326     Int32 *pFilterInput = scratch_memory;
    327 
    328     const Int32 *pLPC;
    329 
    330     /*
    331      * Pointer to the I/O memory space
    332      */
    333     Int32 *pCoef = coef;
    334 
    335     if (direction == -1)
    336     {
    337         pCoef += (num_coef - 1);
    338     }
    339 
    340     /* Make sure the scratch memory is "clean" */
    341     for (i = order; i != 0; i--)
    342     {
    343         *(pFilterInput++) = 0;
    344     }
    345 
    346     wrap_point = 0;
    347 
    348     shift_amt  = (lpc_qformat - 5);
    349 
    350     for (i = num_coef; i > 0; i--)
    351     {
    352         /*
    353          * Copy spectral input into special
    354          * filter input buffer.
    355          */
    356         pLPC = lpc;
    357 
    358         mult = 0;
    359 
    360         /*
    361          * wrap_point = 0 when this code is
    362          * entered for the first iteration of
    363          * for(i=num_coef; i>0; i--)
    364          *
    365          * So, this first for-loop will be
    366          * skipped when i == num_coef.
    367          */
    368 
    369         for (j = wrap_point; j > 0; j--)
    370         {
    371             mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5;
    372 
    373         } /* for (j = wrap_point; j>0; j--) */
    374 
    375         /*
    376          * pFilterInput has reached &scratch_memory[order-1]
    377          * Reset pointer to beginning of filter's state memory
    378          */
    379         pFilterInput = scratch_memory;
    380 
    381         for (j = (order - wrap_point); j > 0; j--)
    382         {
    383             mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5;
    384 
    385         } /* for (j = wrap_point; j>0; j--) */
    386 
    387 
    388         /*
    389          * Fill the filter's state buffer
    390          * avoid obvious casting
    391          */
    392         *(--pFilterInput) = (*pCoef);
    393 
    394 
    395         /* Scale the data down so the output q-format is not adjusted.
    396          *
    397          * Here is an equation, which shows how the spectral coefficients
    398          * and lpc coefficients are multiplied and the spectral
    399          * coefficient's q-format does not change.
    400          *
    401          * Q-(coef) * Q-(lpc_qformat) >> 5 = Q-(coef + lpc_q_format - 5)
    402          *
    403          * Q-(coef + lpc_q_format - 5) >> (lpc_qformat - 5) = Q-(coef)
    404          */
    405 
    406         /* Store output in place */
    407         *(pCoef) += (mult >> shift_amt);
    408 
    409         /* Adjust pointers and placeholders */
    410         pCoef += direction;
    411 
    412         wrap_point++;
    413 
    414         if (wrap_point == order)
    415         {
    416             wrap_point = 0;
    417         }
    418 
    419     } /* for (i = num_coef; i > 0; i--) */
    420 
    421 } /* tns_inv_filter */
    422