Home | History | Annotate | Download | only in ilbc
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /******************************************************************
     12 
     13  iLBC Speech Coder ANSI-C Source Code
     14 
     15  WebRtcIlbcfix_Smooth.c
     16 
     17 ******************************************************************/
     18 
     19 #include "defines.h"
     20 #include "constants.h"
     21 #include "smooth_out_data.h"
     22 
     23 /*----------------------------------------------------------------*
     24  * find the smoothed output data
     25  *---------------------------------------------------------------*/
     26 
     27 void WebRtcIlbcfix_Smooth(
     28     int16_t *odata,   /* (o) smoothed output */
     29     int16_t *current,  /* (i) the un enhanced residual for
     30                                 this block */
     31     int16_t *surround  /* (i) The approximation from the
     32                                 surrounding sequences */
     33                           ) {
     34   int16_t maxtot, scale, scale1, scale2;
     35   int16_t A, B, C, denomW16;
     36   int32_t B_W32, denom, num;
     37   int32_t errs;
     38   int32_t w00,w10,w11, endiff, crit;
     39   int32_t w00prim, w10prim, w11_div_w00;
     40   int16_t w11prim;
     41   int16_t bitsw00, bitsw10, bitsw11;
     42   int32_t w11w00, w10w10, w00w00;
     43   int16_t max1, max2;
     44 
     45   /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
     46 
     47   w00 = w10 = w11 = 0;
     48 
     49   max1=WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL);
     50   max2=WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL);
     51   maxtot=WEBRTC_SPL_MAX(max1, max2);
     52 
     53   scale=WebRtcSpl_GetSizeInBits(maxtot);
     54   scale = (int16_t)WEBRTC_SPL_MUL_16_16(2,scale)-26;
     55   scale=WEBRTC_SPL_MAX(0, scale);
     56 
     57   w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale);
     58   w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale);
     59   w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale);
     60 
     61   if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX;
     62   if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX;
     63 
     64   /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim
     65      is in Q16 */
     66 
     67   bitsw00 = WebRtcSpl_GetSizeInBits(w00);
     68   bitsw11 = WebRtcSpl_GetSizeInBits(w11);
     69   bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10));
     70   scale1 = 31 - bitsw00;
     71   scale2 = 15 - bitsw11;
     72 
     73   if (scale2>(scale1-16)) {
     74     scale2 = scale1 - 16;
     75   } else {
     76     scale1 = scale2 + 16;
     77   }
     78 
     79   w00prim = WEBRTC_SPL_LSHIFT_W32(w00, scale1);
     80   w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);
     81 
     82   /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */
     83   if (w11prim>64) {
     84     endiff = WEBRTC_SPL_LSHIFT_W32(
     85         (int32_t)WebRtcSpl_DivW32W16(w00prim, w11prim), 6);
     86     C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
     87   } else {
     88     C = 1;
     89   }
     90 
     91   /* first try enhancement without power-constraint */
     92 
     93   errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C);
     94 
     95 
     96 
     97   /* if constraint violated by first try, add constraint */
     98 
     99   if ( (6-scale+scale1) > 31) {
    100     crit=0;
    101   } else {
    102     /* crit = 0.05 * w00 (Result in Q-6) */
    103     crit = WEBRTC_SPL_SHIFT_W32(
    104         WEBRTC_SPL_MUL(ENH_A0, WEBRTC_SPL_RSHIFT_W32(w00prim, 14)),
    105         -(6-scale+scale1));
    106   }
    107 
    108   if (errs > crit) {
    109 
    110     if( w00 < 1) {
    111       w00=1;
    112     }
    113 
    114     /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */
    115 
    116     scale1 = bitsw00-15;
    117     scale2 = bitsw11-15;
    118 
    119     if (scale2>scale1) {
    120       scale = scale2;
    121     } else {
    122       scale = scale1;
    123     }
    124 
    125     w11w00 = WEBRTC_SPL_MUL_16_16(
    126         (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale),
    127         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale));
    128 
    129     w10w10 = WEBRTC_SPL_MUL_16_16(
    130         (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale),
    131         (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale));
    132 
    133     w00w00 = WEBRTC_SPL_MUL_16_16(
    134         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale),
    135         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale));
    136 
    137     /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */
    138     if (w00w00>65536) {
    139       endiff = (w11w00-w10w10);
    140       endiff = WEBRTC_SPL_MAX(0, endiff);
    141       /* denom is in Q16 */
    142       denom = WebRtcSpl_DivW32W16(endiff, (int16_t)WEBRTC_SPL_RSHIFT_W32(w00w00, 16));
    143     } else {
    144       denom = 65536;
    145     }
    146 
    147     if( denom > 7){ /* eliminates numerical problems
    148                        for if smooth */
    149 
    150       scale=WebRtcSpl_GetSizeInBits(denom)-15;
    151 
    152       if (scale>0) {
    153         /* denomW16 is in Q(16+scale) */
    154         denomW16=(int16_t)WEBRTC_SPL_RSHIFT_W32(denom, scale);
    155 
    156         /* num in Q(34-scale) */
    157         num=WEBRTC_SPL_RSHIFT_W32(ENH_A0_MINUS_A0A0DIV4, scale);
    158       } else {
    159         /* denomW16 is in Q16 */
    160         denomW16=(int16_t)denom;
    161 
    162         /* num in Q34 */
    163         num=ENH_A0_MINUS_A0A0DIV4;
    164       }
    165 
    166       /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */
    167       A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
    168 
    169       /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
    170       scale1 = 31-bitsw10;
    171       scale2 = 21-scale1;
    172       w10prim = WEBRTC_SPL_LSHIFT_W32(w10, scale1);
    173       w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
    174       scale = bitsw00-scale2-15;
    175 
    176       if (scale>0) {
    177         w10prim=WEBRTC_SPL_RSHIFT_W32(w10prim, scale);
    178         w00prim=WEBRTC_SPL_RSHIFT_W32(w00prim, scale);
    179       }
    180 
    181       if ((w00prim>0)&&(w10prim>0)) {
    182         w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
    183 
    184         if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
    185           B_W32 = 0;
    186         } else {
    187           B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
    188               WEBRTC_SPL_MUL(A, w11_div_w00);
    189         }
    190         B = (int16_t)WEBRTC_SPL_RSHIFT_W32(B_W32, 16); /* B in Q14 */
    191       } else {
    192         /* No smoothing */
    193         A = 0;
    194         B = 16384; /* 1 in Q14 */
    195       }
    196     }
    197     else{ /* essentially no difference between cycles;
    198              smoothing not needed */
    199 
    200       A = 0;
    201       B = 16384; /* 1 in Q14 */
    202     }
    203 
    204     /* create smoothed sequence */
    205 
    206     WebRtcSpl_ScaleAndAddVectors(surround, A, 9,
    207                                 current, B, 14,
    208                                 odata, ENH_BLOCKL);
    209   }
    210   return;
    211 }
    212