/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

/******************************************************************

 iLBC Speech Coder ANSI-C Source Code

 WebRtcIlbcfix_Smooth.c

******************************************************************/

#include "defines.h"
#include "constants.h"
#include "smooth_out_data.h"

/*----------------------------------------------------------------*
 * find the smoothed output data
 *---------------------------------------------------------------*/

void WebRtcIlbcfix_Smooth(
    int16_t *odata,   /* (o) smoothed output */
    int16_t *current,  /* (i) the un enhanced residual for
                                this block */
    int16_t *surround  /* (i) The approximation from the
                                surrounding sequences */
                          ) {
  int16_t scale, scale1, scale2;
  int16_t A, B, C, denomW16;
  int32_t B_W32, denom, num;
  int32_t errs;
  int32_t w00,w10,w11, endiff, crit;
  int32_t w00prim, w10prim, w11_div_w00;
  int16_t w11prim;
  int16_t bitsw00, bitsw10, bitsw11;
  int32_t w11w00, w10w10, w00w00;
  uint32_t max1, max2, max12;

  /* compute some inner products (ensure no overflow by first calculating proper scale factor) */

  w00 = w10 = w11 = 0;

  // Calculate a right shift that will let us sum ENH_BLOCKL pairwise products
  // of values from the two sequences without overflowing an int32_t. (The +1
  // in max1 and max2 are because WebRtcSpl_MaxAbsValueW16 will return 2**15 -
  // 1 if the input array contains -2**15.)
  max1 = WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL) + 1;
  max2 = WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL) + 1;
  max12 = WEBRTC_SPL_MAX(max1, max2);
  scale = (64 - 31) -
          WebRtcSpl_CountLeadingZeros64((max12 * max12) * (uint64_t)ENH_BLOCKL);
  scale=WEBRTC_SPL_MAX(0, scale);

  w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale);
  w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale);
  w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale);

  if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX;
  if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX;

  /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim
     is in Q16 */

  bitsw00 = WebRtcSpl_GetSizeInBits(w00);
  bitsw11 = WebRtcSpl_GetSizeInBits(w11);
  bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10));
  scale1 = 31 - bitsw00;
  scale2 = 15 - bitsw11;

  if (scale2>(scale1-16)) {
    scale2 = scale1 - 16;
  } else {
    scale1 = scale2 + 16;
  }

  w00prim = w00 << scale1;
  w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);

  /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */
  if (w11prim>64) {
    endiff = WebRtcSpl_DivW32W16(w00prim, w11prim) << 6;
    C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
  } else {
    C = 1;
  }

  /* first try enhancement without power-constraint */

  errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C);



  /* if constraint violated by first try, add constraint */

  if ( (6-scale+scale1) > 31) {
    crit=0;
  } else {
    /* crit = 0.05 * w00 (Result in Q-6) */
    crit = WEBRTC_SPL_SHIFT_W32(
        WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
        -(6-scale+scale1));
  }

  if (errs > crit) {

    if( w00 < 1) {
      w00=1;
    }

    /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */

    scale1 = bitsw00-15;
    scale2 = bitsw11-15;

    if (scale2>scale1) {
      scale = scale2;
    } else {
      scale = scale1;
    }

    w11w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale) *
        (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);

    w10w10 = (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale) *
        (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale);

    w00w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale) *
        (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);

    /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */
    if (w00w00>65536) {
      endiff = (w11w00-w10w10);
      endiff = WEBRTC_SPL_MAX(0, endiff);
      /* denom is in Q16 */
      denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
    } else {
      denom = 65536;
    }

    if( denom > 7){ /* eliminates numerical problems
                       for if smooth */

      scale=WebRtcSpl_GetSizeInBits(denom)-15;

      if (scale>0) {
        /* denomW16 is in Q(16+scale) */
        denomW16 = (int16_t)(denom >> scale);

        /* num in Q(34-scale) */
        num = ENH_A0_MINUS_A0A0DIV4 >> scale;
      } else {
        /* denomW16 is in Q16 */
        denomW16=(int16_t)denom;

        /* num in Q34 */
        num=ENH_A0_MINUS_A0A0DIV4;
      }

      /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */
      A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));

      /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
      scale1 = 31-bitsw10;
      scale2 = 21-scale1;
      w10prim = w10 * (1 << scale1);
      w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
      scale = bitsw00-scale2-15;

      if (scale>0) {
        w10prim >>= scale;
        w00prim >>= scale;
      }

      if ((w00prim>0)&&(w10prim>0)) {
        w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);

        if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
          B_W32 = 0;
        } else {
          B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
              WEBRTC_SPL_MUL(A, w11_div_w00);
        }
        B = (int16_t)(B_W32 >> 16);  /* B in Q14. */
      } else {
        /* No smoothing */
        A = 0;
        B = 16384; /* 1 in Q14 */
      }
    }
    else{ /* essentially no difference between cycles;
             smoothing not needed */

      A = 0;
      B = 16384; /* 1 in Q14 */
    }

    /* create smoothed sequence */

    WebRtcSpl_ScaleAndAddVectors(surround, A, 9,
                                current, B, 14,
                                odata, ENH_BLOCKL);
  }
  return;
}
