Home | History | Annotate | Download | only in src
      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  Pathname: ./audio/gsm-amr/c/src/syn_filt.c
     31 
     32 ------------------------------------------------------------------------------
     33  REVISION HISTORY
     34 
     35  Description: Making changes based on comments from the review meeting.
     36 
     37  Description: Added typedef to Input/Output Definition section.
     38 
     39  Description: Synchronized file with UMTS version 3.2.0. Updated coding
     40               template.
     41 
     42  Description: Fixed typecasting issue with the TI C compiler.
     43 
     44  Description: Modified FOR loops to count down.
     45 
     46  Description: Modified FOR loop to count up again so that the correct values
     47               are stored in the tmp buffer. Updated copyright year.
     48 
     49  Description:
     50         - Modified for loop and introduced pointers to avoid adding
     51           offsets
     52         - Eliminated check for saturation given that the max values of input
     53           data and coefficients will not saturate the multiply and
     54           accumulation
     55         - eliminated memcpy to update history buffer in every pass. This is
     56           done now just updating the pointers.
     57 
     58  Description:
     59               1. Eliminated unused include files.
     60               2. Unrolled loops to process twice as many samples as before,
     61                  this saves on memory accesses to the vector coeff. a[] and
     62                  elements in the history buffer of this recursive filter
     63 
     64  Description:
     65               1. Added overflow check inside both loops. (this is needed just
     66                  to satisfy bit exactness on the decoder, a faster
     67                  implementation will add an extra shift, do the same,
     68                  but will not be bit exact, and it may have better audio
     69                  quality because will avoid clipping)
     70               2. Added include file for constant definitions
     71 
     72  Description:  Replaced OSCL mem type functions and eliminated include
     73                files that now are chosen by OSCL definitions
     74 
     75  Description:  Replaced "int" and/or "char" with OSCL defined types.
     76 
     77  Description: Changed round function name to pv_round to avoid conflict with
     78               round function in C standard library.
     79 
     80  Description: Using fxp_arithmetic.h that includes inline assembly functions
     81               for ARM and linux-arm.
     82 
     83  Description: Replacing fxp_arithmetic.h with basic_op.h.
     84 
     85  Who:                           Date:
     86  Description:
     87 
     88 ------------------------------------------------------------------------------
     89 */
     90 
     91 /*----------------------------------------------------------------------------
     92 ; INCLUDES
     93 ----------------------------------------------------------------------------*/
     94 
     95 #include <string.h>
     96 
     97 #include    "syn_filt.h"
     98 #include    "cnst.h"
     99 #include    "basic_op.h"
    100 
    101 #include    "basic_op.h"
    102 
    103 /*----------------------------------------------------------------------------
    104 ; MACROS
    105 ; Define module specific macros here
    106 ----------------------------------------------------------------------------*/
    107 
    108 
    109 /*----------------------------------------------------------------------------
    110 ; DEFINES
    111 ; Include all pre-processor statements here. Include conditional
    112 ; compile variables also.
    113 ----------------------------------------------------------------------------*/
    114 
    115 /*----------------------------------------------------------------------------
    116 ; LOCAL FUNCTION DEFINITIONS
    117 ; Function Prototype declaration
    118 ----------------------------------------------------------------------------*/
    119 
    120 /*----------------------------------------------------------------------------
    121 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
    122 ; Variable declaration - defined here and used outside this module
    123 ----------------------------------------------------------------------------*/
    124 
    125 
    126 /*
    127 ------------------------------------------------------------------------------
    128  FUNCTION NAME: Syn_filt
    129 ------------------------------------------------------------------------------
    130  INPUT AND OUTPUT DEFINITIONS
    131 
    132  Inputs:
    133     a = buffer containing the prediction coefficients (Word16)  max 2^12
    134     x = input signal buffer (Word16)                            max 2^15
    135     y = output signal buffer (Word16)
    136     lg = size of filtering (Word16)
    137     mem = memory buffer associated with this filtering (Word16)
    138     update = flag to indicate memory update; 0=no update, 1=update memory
    139              (Word16)
    140 
    141  Outputs:
    142     mem buffer is changed to be the last M data points of the output signal
    143       if update was set to 1
    144     y buffer contains the newly calculated filter output
    145 
    146  Returns:
    147     None
    148 
    149  Global Variables Used:
    150     None
    151 
    152  Local Variables Needed:
    153     None
    154 
    155 ------------------------------------------------------------------------------
    156  FUNCTION DESCRIPTION
    157 
    158  Perform synthesis filtering through 1/A(z)
    159 
    160 ------------------------------------------------------------------------------
    161  REQUIREMENTS
    162 
    163  None
    164 
    165 ------------------------------------------------------------------------------
    166  REFERENCES
    167 
    168  syn_filt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    169 
    170 ------------------------------------------------------------------------------
    171  PSEUDO-CODE
    172 
    173 void Syn_filt (
    174     Word16 a[],     // (i)     : a[M+1] prediction coefficients   (M=10)
    175     Word16 x[],     // (i)     : input signal
    176     Word16 y[],     // (o)     : output signal
    177     Word16 lg,      // (i)     : size of filtering
    178     Word16 mem[],   // (i/o)   : memory associated with this filtering.
    179     Word16 update   // (i)     : 0=no update, 1=update of memory.
    180 )
    181 {
    182     Word16 i, j;
    183     Word32 s;
    184     Word16 tmp[80];   // This is usually done by memory allocation (lg+M)
    185     Word16 *yy;
    186 
    187     // Copy mem[] to yy[]
    188 
    189     yy = tmp;
    190 
    191     for (i = 0; i < M; i++)
    192     {
    193         *yy++ = mem[i];
    194     }
    195 
    196     // Do the filtering.
    197 
    198     for (i = 0; i < lg; i++)
    199     {
    200         s = L_mult (x[i], a[0]);
    201         for (j = 1; j <= M; j++)
    202         {
    203             s = L_msu (s, a[j], yy[-j]);
    204         }
    205         s = L_shl (s, 3);
    206         *yy++ = pv_round (s);
    207     }
    208 
    209     for (i = 0; i < lg; i++)
    210     {
    211         y[i] = tmp[i + M];
    212     }
    213 
    214     // Update of memory if update==1
    215 
    216     if (update != 0)
    217     {
    218         for (i = 0; i < M; i++)
    219         {
    220             mem[i] = y[lg - M + i];
    221         }
    222     }
    223     return;
    224 }
    225 
    226 ------------------------------------------------------------------------------
    227  RESOURCES USED [optional]
    228 
    229  When the code is written for a specific target processor the
    230  the resources used should be documented below.
    231 
    232  HEAP MEMORY USED: x bytes
    233 
    234  STACK MEMORY USED: x bytes
    235 
    236  CLOCK CYCLES: (cycle count equation for this function) + (variable
    237                 used to represent cycle count for each subroutine
    238                 called)
    239      where: (cycle count variable) = cycle count for [subroutine
    240                                      name]
    241 
    242 ------------------------------------------------------------------------------
    243  CAUTION [optional]
    244  [State any special notes, constraints or cautions for users of this function]
    245 
    246 ------------------------------------------------------------------------------
    247 */
    248 #ifdef __clang__
    249 __attribute__((no_sanitize("integer")))
    250 #endif
    251 void Syn_filt(
    252     Word16 a[],     /* (i)   : a[M+1] prediction coefficients   (M=10)  */
    253     Word16 x[],     /* (i)   : input signal                             */
    254     Word16 y[],     /* (o)   : output signal                            */
    255     Word16 lg,      /* (i)   : size of filtering   (40)                 */
    256     Word16 mem[],   /* (i/o) : memory associated with this filtering.   */
    257     Word16 update   /* (i)   : 0=no update, 1=update of memory.         */
    258 )
    259 {
    260     Word16 i, j;
    261     Word32 s1;
    262     Word32 s2;
    263     Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
    264     Word16 *yy;
    265 
    266     Word16 *p_a;
    267     Word16 *p_yy1;
    268     Word16 *p_y;
    269     Word16 *p_x;
    270     Word16 temp;
    271     /* Copy mem[] to yy[] */
    272 
    273     yy = tmp;
    274 
    275     memcpy(yy, mem, M*sizeof(Word16));
    276 
    277     yy = yy + M;
    278 
    279     /* Do the filtering. */
    280 
    281     p_y  = y;
    282     p_x  = x;
    283     p_yy1 = &yy[-1];
    284 
    285     for (i = M >> 1; i != 0; i--)
    286     {
    287         p_a  = a;
    288 
    289         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
    290         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
    291         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    292 
    293         for (j = (M >> 1) - 2; j != 0; j--)
    294         {
    295             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    296             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    297             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    298             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    299             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    300             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    301         }
    302 
    303         /* check for overflow on s1 */
    304         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
    305         {
    306             temp = (Word16)(s1 >> 12);
    307         }
    308         else if (s1 > 0x07ffffffL)
    309         {
    310             temp = MAX_16;
    311         }
    312         else
    313         {
    314             temp = MIN_16;
    315         }
    316 
    317         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
    318 
    319         *(yy++)  = temp;
    320         *(p_y++) = temp;
    321 
    322         p_yy1 = yy;
    323 
    324         /* check for overflow on s2 */
    325         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
    326         {
    327             temp = (Word16)(s2 >> 12);
    328         }
    329         else if (s2 > 0x07ffffffL)
    330         {
    331             temp = MAX_16;
    332         }
    333         else
    334         {
    335             temp = MIN_16;
    336         }
    337 
    338         *(yy++)  = temp;
    339         *(p_y++) = temp;
    340     }
    341 
    342     p_yy1 = &y[M-1];
    343 
    344     for (i = (lg - M) >> 1; i != 0; i--)
    345     {
    346         p_a  = a;
    347 
    348         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
    349         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
    350         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    351 
    352         for (j = (M >> 1) - 2; j != 0; j--)
    353         {
    354             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    355             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    356             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    357             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    358             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    359             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    360         }
    361 
    362         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
    363         {
    364             temp = (Word16)(s1 >> 12);
    365         }
    366         else if (s1 > 0x07ffffffL)
    367         {
    368             temp = MAX_16;
    369         }
    370         else
    371         {
    372             temp = MIN_16;
    373         }
    374 
    375         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
    376 
    377         *(p_y++) = temp;
    378         p_yy1 = p_y;
    379 
    380         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
    381         {
    382             *(p_y++) = (Word16)(s2 >> 12);
    383         }
    384         else if (s2 > 0x07ffffffL)
    385         {
    386             *(p_y++) = MAX_16;
    387         }
    388         else
    389         {
    390             *(p_y++) = MIN_16;
    391         }
    392     }
    393 
    394     /* Update of memory if update==1 */
    395     if (update != 0)
    396     {
    397         memcpy(mem, &y[lg-M], M*sizeof(Word16));
    398     }
    399 
    400     return;
    401 }
    402