211 lines
6.3 KiB
C
211 lines
6.3 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 "modules/audio_coding/codecs/ilbc/defines.h"
|
||
|
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||
|
#include "modules/audio_coding/codecs/ilbc/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 == 0 ? 0 : 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;
|
||
|
}
|