You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
			
		
		
	
	
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
/*
 | 
						|
 *  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 maxtot, 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;
 | 
						|
  int16_t max1, max2;
 | 
						|
 | 
						|
  /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
 | 
						|
 | 
						|
  w00 = w10 = w11 = 0;
 | 
						|
 | 
						|
  max1=WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL);
 | 
						|
  max2=WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL);
 | 
						|
  maxtot=WEBRTC_SPL_MAX(max1, max2);
 | 
						|
 | 
						|
  scale=WebRtcSpl_GetSizeInBits(maxtot);
 | 
						|
  scale = (int16_t)WEBRTC_SPL_MUL_16_16(2,scale)-26;
 | 
						|
  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 = WEBRTC_SPL_LSHIFT_W32(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 = WEBRTC_SPL_LSHIFT_W32(
 | 
						|
        (int32_t)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, WEBRTC_SPL_RSHIFT_W32(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 = WEBRTC_SPL_MUL_16_16(
 | 
						|
        (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale),
 | 
						|
        (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale));
 | 
						|
 | 
						|
    w10w10 = WEBRTC_SPL_MUL_16_16(
 | 
						|
        (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale),
 | 
						|
        (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale));
 | 
						|
 | 
						|
    w00w00 = WEBRTC_SPL_MUL_16_16(
 | 
						|
        (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)WEBRTC_SPL_RSHIFT_W32(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)WEBRTC_SPL_RSHIFT_W32(denom, scale);
 | 
						|
 | 
						|
        /* num in Q(34-scale) */
 | 
						|
        num=WEBRTC_SPL_RSHIFT_W32(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 = WEBRTC_SPL_LSHIFT_W32(w10, scale1);
 | 
						|
      w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
 | 
						|
      scale = bitsw00-scale2-15;
 | 
						|
 | 
						|
      if (scale>0) {
 | 
						|
        w10prim=WEBRTC_SPL_RSHIFT_W32(w10prim, scale);
 | 
						|
        w00prim=WEBRTC_SPL_RSHIFT_W32(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)WEBRTC_SPL_RSHIFT_W32(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;
 | 
						|
}
 |