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 
    249 void Syn_filt(
    250     Word16 a[],     /* (i)   : a[M+1] prediction coefficients   (M=10)  */
    251     Word16 x[],     /* (i)   : input signal                             */
    252     Word16 y[],     /* (o)   : output signal                            */
    253     Word16 lg,      /* (i)   : size of filtering   (40)                 */
    254     Word16 mem[],   /* (i/o) : memory associated with this filtering.   */
    255     Word16 update   /* (i)   : 0=no update, 1=update of memory.         */
    256 )
    257 {
    258     Word16 i, j;
    259     Word32 s1;
    260     Word32 s2;
    261     Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
    262     Word16 *yy;
    263 
    264     Word16 *p_a;
    265     Word16 *p_yy1;
    266     Word16 *p_y;
    267     Word16 *p_x;
    268     Word16 temp;
    269     /* Copy mem[] to yy[] */
    270 
    271     yy = tmp;
    272 
    273     memcpy(yy, mem, M*sizeof(Word16));
    274 
    275     yy = yy + M;
    276 
    277     /* Do the filtering. */
    278 
    279     p_y  = y;
    280     p_x  = x;
    281     p_yy1 = &yy[-1];
    282 
    283     for (i = M >> 1; i != 0; i--)
    284     {
    285         p_a  = a;
    286 
    287         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
    288         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
    289         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    290 
    291         for (j = (M >> 1) - 2; j != 0; j--)
    292         {
    293             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    294             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    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         }
    300 
    301         /* check for overflow on s1 */
    302         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
    303         {
    304             temp = (Word16)(s1 >> 12);
    305         }
    306         else if (s1 > 0x07ffffffL)
    307         {
    308             temp = MAX_16;
    309         }
    310         else
    311         {
    312             temp = MIN_16;
    313         }
    314 
    315         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
    316 
    317         *(yy++)  = temp;
    318         *(p_y++) = temp;
    319 
    320         p_yy1 = yy;
    321 
    322         /* check for overflow on s2 */
    323         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
    324         {
    325             temp = (Word16)(s2 >> 12);
    326         }
    327         else if (s2 > 0x07ffffffL)
    328         {
    329             temp = MAX_16;
    330         }
    331         else
    332         {
    333             temp = MIN_16;
    334         }
    335 
    336         *(yy++)  = temp;
    337         *(p_y++) = temp;
    338     }
    339 
    340     p_yy1 = &y[M-1];
    341 
    342     for (i = (lg - M) >> 1; i != 0; i--)
    343     {
    344         p_a  = a;
    345 
    346         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
    347         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
    348         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    349 
    350         for (j = (M >> 1) - 2; j != 0; j--)
    351         {
    352             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
    353             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
    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         }
    359 
    360         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
    361         {
    362             temp = (Word16)(s1 >> 12);
    363         }
    364         else if (s1 > 0x07ffffffL)
    365         {
    366             temp = MAX_16;
    367         }
    368         else
    369         {
    370             temp = MIN_16;
    371         }
    372 
    373         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
    374 
    375         *(p_y++) = temp;
    376         p_yy1 = p_y;
    377 
    378         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
    379         {
    380             *(p_y++) = (Word16)(s2 >> 12);
    381         }
    382         else if (s2 > 0x07ffffffL)
    383         {
    384             *(p_y++) = MAX_16;
    385         }
    386         else
    387         {
    388             *(p_y++) = MIN_16;
    389         }
    390     }
    391 
    392     /* Update of memory if update==1 */
    393     if (update != 0)
    394     {
    395         memcpy(mem, &y[lg-M], M*sizeof(Word16));
    396     }
    397 
    398     return;
    399 }
    400