git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
830
modules/audio_coding/codecs/iSAC/fix/source/decode_plc.c
Normal file
830
modules/audio_coding/codecs/iSAC/fix/source/decode_plc.c
Normal file
@@ -0,0 +1,830 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* decode_plc.c
|
||||
*
|
||||
* Packet Loss Concealment.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "entropy_coding.h"
|
||||
#include "pitch_estimator.h"
|
||||
#include "bandwidth_estimator.h"
|
||||
#include "structs.h"
|
||||
#include "codec.h"
|
||||
|
||||
|
||||
#define NO_OF_PRIMES 8
|
||||
#define NOISE_FILTER_LEN 30
|
||||
|
||||
/*
|
||||
* function to decode the bitstream
|
||||
* returns the total number of bytes in the stream
|
||||
*/
|
||||
|
||||
WebRtc_Word16 plc_filterma_Fast(
|
||||
WebRtc_Word16 *In, /* (i) Vector to be filtered. InOut[-orderCoef+1]
|
||||
to InOut[-1] contains state */
|
||||
WebRtc_Word16 *Out, /* (o) Filtered vector */
|
||||
WebRtc_Word16 *B, /* (i) The filter coefficients (in Q0) */
|
||||
WebRtc_Word16 Blen, /* (i) Number of B coefficients */
|
||||
WebRtc_Word16 len, /* (i) Number of samples to be filtered */
|
||||
WebRtc_Word16 reduceDecay,
|
||||
WebRtc_Word16 decay,
|
||||
WebRtc_Word16 rshift )
|
||||
{
|
||||
int i, j;
|
||||
WebRtc_Word32 o;
|
||||
WebRtc_Word32 lim;
|
||||
|
||||
lim = WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 15 + rshift )-1;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
G_CONST WebRtc_Word16 *b_ptr = &B[0];
|
||||
G_CONST WebRtc_Word16 *x_ptr = &In[i];
|
||||
|
||||
o = (WebRtc_Word32)0;
|
||||
|
||||
for (j = 0;j < Blen; j++)
|
||||
{
|
||||
o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_MUL_16_16( *b_ptr, *x_ptr) );
|
||||
b_ptr++;
|
||||
x_ptr--;
|
||||
}
|
||||
|
||||
/* to round off correctly */
|
||||
o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_LSHIFT_W32( 1, (rshift-1) ) );
|
||||
|
||||
/* saturate according to the domain of the filter coefficients */
|
||||
o = WEBRTC_SPL_SAT((WebRtc_Word32)lim, o, (WebRtc_Word32)-lim);
|
||||
|
||||
/* o should be in the range of WebRtc_Word16 */
|
||||
o = WEBRTC_SPL_RSHIFT_W32( o, rshift );
|
||||
|
||||
/* decay the output signal; this is specific to plc */
|
||||
*Out++ = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16)o, decay, 15); // ((o + (WebRtc_Word32)2048) >> 12);
|
||||
|
||||
/* change the decay */
|
||||
decay -= reduceDecay;
|
||||
if( decay < 0 )
|
||||
decay = 0;
|
||||
}
|
||||
return( decay );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static __inline WebRtc_Word32 log2_Q8_T( WebRtc_UWord32 x ) {
|
||||
|
||||
WebRtc_Word32 zeros, lg2;
|
||||
WebRtc_Word16 frac;
|
||||
|
||||
zeros=WebRtcSpl_NormU32(x);
|
||||
frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
|
||||
/* log2(magn(i)) */
|
||||
|
||||
lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
|
||||
return lg2;
|
||||
|
||||
}
|
||||
|
||||
static __inline WebRtc_Word16 exp2_Q10_T(WebRtc_Word16 x) { // Both in and out in Q10
|
||||
|
||||
WebRtc_Word16 tmp16_1, tmp16_2;
|
||||
|
||||
tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
|
||||
tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
|
||||
if(tmp16_1>0)
|
||||
return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
|
||||
else
|
||||
return (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
|
||||
hard-coded. The values 700 and 5000 were experimentally obtained.
|
||||
|
||||
The function implements membership values for two sets. The mebership functions are
|
||||
of second orders corresponding to half-bell-shapped pulses.
|
||||
*/
|
||||
static void MemshipValQ15( WebRtc_Word16 in, WebRtc_Word16 *A, WebRtc_Word16 *B )
|
||||
{
|
||||
WebRtc_Word16 x;
|
||||
|
||||
in -= 700; /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
|
||||
|
||||
if( in <= 2150 )
|
||||
{
|
||||
if( in > 0 )
|
||||
{
|
||||
/* b = in^2 / (2 * M^2), a = 1 - b in Q0.
|
||||
We have to compute in Q15 */
|
||||
|
||||
/* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
|
||||
x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999 */
|
||||
|
||||
/* we are sure that x is in the range of WebRtc_Word16 */
|
||||
x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
|
||||
WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
|
||||
/* b = x^2 / 2 {in Q15} so a shift of 16 is required to
|
||||
be in correct domain and one more for the division by 2 */
|
||||
*B = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
|
||||
*A = WEBRTC_SPL_WORD16_MAX - *B;
|
||||
}
|
||||
else
|
||||
{
|
||||
*B = 0;
|
||||
*A = WEBRTC_SPL_WORD16_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( in < 4300 )
|
||||
{
|
||||
/* This is a mirror case of the above */
|
||||
in = 4300 - in;
|
||||
x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
|
||||
WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
|
||||
/* b = x^2 / 2 {in Q15} so a shift of 16 is required to
|
||||
be in correct domain and one more for the division by 2 */
|
||||
*A = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
|
||||
*B = WEBRTC_SPL_WORD16_MAX - *A;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*A = 0;
|
||||
*B = WEBRTC_SPL_WORD16_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void LinearResampler( WebRtc_Word16 *in, WebRtc_Word16 *out, WebRtc_Word16 lenIn, WebRtc_Word16 lenOut )
|
||||
{
|
||||
WebRtc_Word32 n;
|
||||
WebRtc_Word16 resOut, i, j, relativePos, diff; /* */
|
||||
WebRtc_UWord16 udiff;
|
||||
|
||||
if( lenIn == lenOut )
|
||||
{
|
||||
WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
|
||||
return;
|
||||
}
|
||||
|
||||
n = WEBRTC_SPL_MUL_16_16( (WebRtc_Word16)(lenIn-1), RESAMP_RES );
|
||||
resOut = WebRtcSpl_DivW32W16ResW16( n, (WebRtc_Word16)(lenOut-1) );
|
||||
|
||||
out[0] = in[0];
|
||||
for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
|
||||
{
|
||||
|
||||
relativePos += resOut;
|
||||
while( relativePos > RESAMP_RES )
|
||||
{
|
||||
j++;
|
||||
relativePos -= RESAMP_RES;
|
||||
}
|
||||
|
||||
|
||||
/* an overflow may happen and the differce in sample values may
|
||||
* require more than 16 bits. We like to avoid 32 bit arithmatic
|
||||
* as much as possible */
|
||||
|
||||
if( (in[ j ] > 0) && (in[j + 1] < 0) )
|
||||
{
|
||||
udiff = (WebRtc_UWord16)(in[ j ] - in[j + 1]);
|
||||
out[ i ] = in[ j ] - (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (in[j] < 0) && (in[j+1] > 0) )
|
||||
{
|
||||
udiff = (WebRtc_UWord16)( in[j + 1] - in[ j ] );
|
||||
out[ i ] = in[ j ] + (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
diff = in[ j + 1 ] - in[ j ];
|
||||
out[ i ] = in[ j ] + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( diff, relativePos, RESAMP_RES_BIT );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
WebRtc_Word16 WebRtcIsacfix_DecodePlcImpl(WebRtc_Word16 *signal_out16,
|
||||
ISACFIX_DecInst_t *ISACdec_obj,
|
||||
WebRtc_Word16 *current_framesamples )
|
||||
{
|
||||
int subframecnt;
|
||||
WebRtc_Word16 len = 0;
|
||||
|
||||
WebRtc_Word16* Vector_Word16_1;
|
||||
WebRtc_Word16 Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
|
||||
WebRtc_Word16* Vector_Word16_2;
|
||||
WebRtc_Word16 Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
|
||||
|
||||
WebRtc_Word32 Vector_Word32_1[FRAMESAMPLES_HALF];
|
||||
WebRtc_Word32 Vector_Word32_2[FRAMESAMPLES_HALF];
|
||||
|
||||
WebRtc_Word16 lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
|
||||
WebRtc_Word16 hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
|
||||
|
||||
WebRtc_Word16 pitchLags_Q7[PITCH_SUBFRAMES];
|
||||
WebRtc_Word16 pitchGains_Q12[PITCH_SUBFRAMES];
|
||||
|
||||
WebRtc_Word16 tmp_1, tmp_2;
|
||||
WebRtc_Word32 tmp32a, tmp32b;
|
||||
WebRtc_Word16 gainQ13;
|
||||
|
||||
WebRtc_Word16 myDecayRate;
|
||||
|
||||
/* ---------- PLC variables ------------ */
|
||||
WebRtc_Word16 lag0, i, k, noiseIndex;
|
||||
WebRtc_Word16 stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
|
||||
|
||||
WebRtc_Word32 gain_lo_hiQ17[2*SUBFRAMES];
|
||||
|
||||
WebRtc_Word16 nLP, pLP, wNoisyLP, wPriodicLP, tmp16, minIdx;
|
||||
WebRtc_Word32 nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
|
||||
WebRtc_Word16 noise1, rshift;
|
||||
|
||||
|
||||
WebRtc_Word16 ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
|
||||
WebRtc_Word32 varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
|
||||
int rightShiftIn, rightShiftOut;
|
||||
|
||||
|
||||
/* ------------------------------------- */
|
||||
|
||||
|
||||
myDecayRate = (DECAY_RATE);
|
||||
Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
|
||||
Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
|
||||
|
||||
|
||||
/* ----- Simply Copy Previous LPC parameters ------ */
|
||||
for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
|
||||
{
|
||||
/* lower Band */
|
||||
WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
|
||||
(ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
|
||||
gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
|
||||
|
||||
/* Upper Band */
|
||||
WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
|
||||
(ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
|
||||
gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lag0 = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLag_Q7 + 64, 7 ) + 1;
|
||||
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).pitchCycles = 0;
|
||||
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLP =
|
||||
&((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
|
||||
minCorr = WEBRTC_SPL_WORD32_MAX;
|
||||
|
||||
if ( (FRAMESAMPLES_HALF - 2*lag0 - 10) > 0 )
|
||||
{
|
||||
minIdx = 11;
|
||||
for( i = 0; i < 21; i++ )
|
||||
{
|
||||
corr = 0;
|
||||
for( k = 0; k < lag0; k++ )
|
||||
{
|
||||
corr = WEBRTC_SPL_ADD_SAT_W32( corr, WEBRTC_SPL_ABS_W32(
|
||||
WEBRTC_SPL_SUB_SAT_W16(
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLP[k],
|
||||
(ISACdec_obj->plcstr_obj).prevPitchInvIn[
|
||||
FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
|
||||
}
|
||||
if( corr < minCorr )
|
||||
{
|
||||
minCorr = corr;
|
||||
minIdx = i;
|
||||
}
|
||||
}
|
||||
(ISACdec_obj->plcstr_obj).prevPitchLP =
|
||||
&( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
|
||||
FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
|
||||
}
|
||||
else
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).prevPitchLP =
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLP;
|
||||
}
|
||||
pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
|
||||
|
||||
WebRtcSpl_AutoCorrelation(
|
||||
&(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
|
||||
lag0, 0, &varIn, &rightShiftIn);
|
||||
WebRtcSpl_AutoCorrelation(
|
||||
&(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
|
||||
lag0, 0, &varOut, &rightShiftOut);
|
||||
|
||||
maxAbs = 0;
|
||||
for( i = 0; i< lag0; i++)
|
||||
{
|
||||
myAbs = WEBRTC_SPL_ABS_W16(
|
||||
(ISACdec_obj->plcstr_obj).prevPitchInvOut[
|
||||
PITCH_MAX_LAG + 10 - lag0 + i] );
|
||||
maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
|
||||
}
|
||||
logVarIn = log2_Q8_T( (WebRtc_UWord32)( varIn ) ) +
|
||||
(WebRtc_Word32)(rightShiftIn << 8);
|
||||
logVarOut = log2_Q8_T( (WebRtc_UWord32)( varOut ) ) +
|
||||
(WebRtc_Word32)(rightShiftOut << 8);
|
||||
logMaxAbs = log2_Q8_T( (WebRtc_UWord32)( maxAbs ) );
|
||||
|
||||
ltpGain = (WebRtc_Word16)(logVarOut - logVarIn);
|
||||
Q = 2 * logMaxAbs - ( logVarOut - 1512 );
|
||||
|
||||
/*
|
||||
* ---
|
||||
* We are computing sqrt( (VarIn/lag0) / var( noise ) )
|
||||
* var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
|
||||
* so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) ) ).
|
||||
* Note that put log function is in Q8 but the exponential function is in Q10.
|
||||
* --
|
||||
*/
|
||||
|
||||
logVarIn -= log2_Q8_T( (WebRtc_UWord32)( lag0 ) );
|
||||
tmp16 = (WebRtc_Word16)((logVarIn<<1) - (4<<10) );
|
||||
rightShiftIn = 0;
|
||||
if( tmp16 > 4096 )
|
||||
{
|
||||
tmp16 -= 4096;
|
||||
tmp16 = exp2_Q10_T( tmp16 );
|
||||
tmp16 >>= 6;
|
||||
}
|
||||
else
|
||||
tmp16 = exp2_Q10_T( tmp16 )>>10;
|
||||
|
||||
(ISACdec_obj->plcstr_obj).std = tmp16 - 4;
|
||||
|
||||
if( (ltpGain < 110) || (ltpGain > 230) )
|
||||
{
|
||||
if( ltpGain < 100 && (pitchGain < 1800) )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
|
||||
)? WEBRTC_SPL_WORD16_MAX:0;
|
||||
}
|
||||
(ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
|
||||
(ISACdec_obj->plcstr_obj).A;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (pitchGain < 450) || (pitchGain > 1600) )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
|
||||
)? WEBRTC_SPL_WORD16_MAX:0;
|
||||
(ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
|
||||
(ISACdec_obj->plcstr_obj).A;
|
||||
}
|
||||
else
|
||||
{
|
||||
myVoiceIndicator = ltpGain * 2 + pitchGain;
|
||||
MemshipValQ15( myVoiceIndicator,
|
||||
&(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
|
||||
MemshipValQ15( myVoiceIndicator,
|
||||
&(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
|
||||
|
||||
|
||||
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = lag0;
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
myDecayRate = (DECAY_RATE<<2);
|
||||
}
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).B < 1000 )
|
||||
{
|
||||
myDecayRate += (DECAY_RATE<<3);
|
||||
}
|
||||
|
||||
/* ------------ reconstructing the residual signal ------------------ */
|
||||
|
||||
LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
|
||||
stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
|
||||
/* inverse pitch filter */
|
||||
|
||||
pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
|
||||
((ISACdec_obj->plcstr_obj).stretchLag<<7);
|
||||
pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
|
||||
pitchGains_Q12[2] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
pitchGains_Q12[3], 1010, 10 );
|
||||
pitchGains_Q12[1] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
pitchGains_Q12[2], 1010, 10 );
|
||||
pitchGains_Q12[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
pitchGains_Q12[1], 1010, 10 );
|
||||
|
||||
|
||||
/* most of the time either B or A are zero so seperating */
|
||||
if( (ISACdec_obj->plcstr_obj).B == 0 )
|
||||
{
|
||||
for( i = 0; i < FRAMESAMPLES_HALF; i++ )
|
||||
{
|
||||
/* --- Low Pass */
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
Vector_Word16_1[i] = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
|
||||
|
||||
/* --- Highpass */
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
Vector_Word16_2[i] = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
|
||||
|
||||
}
|
||||
for( i = 1; i < NOISE_FILTER_LEN; i++ )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
Vector_Word16_Extended_1[ i ] = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
|
||||
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
Vector_Word16_Extended_2[ i ] = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
|
||||
}
|
||||
plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
|
||||
&(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
|
||||
NOISE_FILTER_LEN], (WebRtc_Word16) NOISE_FILTER_LEN,
|
||||
(WebRtc_Word16) FRAMESAMPLES_HALF, (WebRtc_Word16)(5),
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise, (WebRtc_Word16)(6));
|
||||
|
||||
maxCoeff = WebRtcSpl_MaxAbsValueW32(
|
||||
&(ISACdec_obj->plcstr_obj).prevHP[
|
||||
PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
|
||||
|
||||
rshift = 0;
|
||||
while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
|
||||
{
|
||||
maxCoeff = WEBRTC_SPL_RSHIFT_W32(maxCoeff, 1);
|
||||
rshift++;
|
||||
}
|
||||
for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
|
||||
Vector_Word16_1[ FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =
|
||||
(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||
(ISACdec_obj->plcstr_obj).prevHP[
|
||||
PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN + i], rshift);
|
||||
}
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
|
||||
Vector_Word16_2,
|
||||
Vector_Word16_Extended_2,
|
||||
&Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
|
||||
(WebRtc_Word16) NOISE_FILTER_LEN,
|
||||
(WebRtc_Word16) FRAMESAMPLES_HALF,
|
||||
(WebRtc_Word16) (5),
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise,
|
||||
(WebRtc_Word16) (7) );
|
||||
|
||||
for( i = 0; i < FRAMESAMPLES_HALF; i++ )
|
||||
Vector_Word32_2[i] = WEBRTC_SPL_LSHIFT_W32(
|
||||
(WebRtc_Word32)Vector_Word16_Extended_2[i], rshift );
|
||||
|
||||
Vector_Word16_1 = Vector_Word16_Extended_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (ISACdec_obj->plcstr_obj).A == 0 )
|
||||
{
|
||||
/* ------ Periodic Vector --- */
|
||||
for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
|
||||
{
|
||||
/* --- Lowpass */
|
||||
pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
|
||||
|
||||
/* --- Highpass */
|
||||
pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic,
|
||||
(ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
|
||||
(ISACdec_obj->plcstr_obj).stretchLag +
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex] );
|
||||
|
||||
/* --- lower the muliplier (more decay at next sample) --- */
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
|
||||
if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
|
||||
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex++;
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).pitchIndex ==
|
||||
(ISACdec_obj->plcstr_obj).stretchLag )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex = 0;
|
||||
(ISACdec_obj->plcstr_obj).pitchCycles++;
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = lag0;
|
||||
}
|
||||
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = (
|
||||
(ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
|
||||
)? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
|
||||
|
||||
LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
|
||||
stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
|
||||
|
||||
LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
|
||||
stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
|
||||
|
||||
switch( (ISACdec_obj->plcstr_obj).pitchCycles )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)((
|
||||
(WebRtc_Word32)stretchPitchLP[k]* 3 +
|
||||
(WebRtc_Word32)stretchPitchLP1[k])>>2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)((
|
||||
(WebRtc_Word32)stretchPitchLP[k] +
|
||||
(WebRtc_Word32)stretchPitchLP1[k] )>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)((stretchPitchLP[k] +
|
||||
(WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
|
||||
{
|
||||
myDecayRate += 35; //(myDecayRate>>1);
|
||||
(ISACdec_obj->plcstr_obj).pitchCycles = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------ Sum the noisy and periodic signals ------ */
|
||||
Vector_Word16_1[i] = pLP;
|
||||
Vector_Word32_2[i] = pHP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
|
||||
{
|
||||
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
|
||||
noise1 = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
|
||||
|
||||
nLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
(WebRtc_Word16)((noise1)*(ISACdec_obj->plcstr_obj).std),
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise, 15 );
|
||||
|
||||
/* --- Highpass */
|
||||
(ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
|
||||
(ISACdec_obj->plcstr_obj).seed );
|
||||
noise1 = WEBRTC_SPL_RSHIFT_W16(
|
||||
(ISACdec_obj->plcstr_obj).seed, 11 ) - 8;
|
||||
|
||||
nHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise,
|
||||
(WebRtc_Word32)(noise1*(ISACdec_obj->plcstr_obj).std) );
|
||||
|
||||
/* --- lower the muliplier (more decay at next sample) --- */
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
|
||||
if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
|
||||
|
||||
/* ------ Periodic Vector --- */
|
||||
/* --- Lowpass */
|
||||
pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
|
||||
|
||||
/* --- Highpass */
|
||||
pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic,
|
||||
(ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
|
||||
(ISACdec_obj->plcstr_obj).stretchLag +
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex] );
|
||||
|
||||
/* --- lower the muliplier (more decay at next sample) --- */
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
|
||||
if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
|
||||
}
|
||||
|
||||
/* ------ Weighting the noisy and periodic vectors ------- */
|
||||
wNoisyLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
(ISACdec_obj->plcstr_obj).A, nLP, 15 ) );
|
||||
wNoisyHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
|
||||
(ISACdec_obj->plcstr_obj).A, (nHP) ) );
|
||||
|
||||
wPriodicLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
|
||||
(ISACdec_obj->plcstr_obj).B, pLP, 15));
|
||||
wPriodicHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
|
||||
(ISACdec_obj->plcstr_obj).B, pHP));
|
||||
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex++;
|
||||
|
||||
if((ISACdec_obj->plcstr_obj).pitchIndex ==
|
||||
(ISACdec_obj->plcstr_obj).stretchLag)
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).pitchIndex = 0;
|
||||
(ISACdec_obj->plcstr_obj).pitchCycles++;
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
|
||||
else
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = lag0;
|
||||
|
||||
(ISACdec_obj->plcstr_obj).stretchLag = (
|
||||
(ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
|
||||
)? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
|
||||
LinearResampler(
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLP,
|
||||
stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
|
||||
|
||||
LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
|
||||
stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
|
||||
|
||||
switch((ISACdec_obj->plcstr_obj).pitchCycles)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)((
|
||||
(WebRtc_Word32)stretchPitchLP[k]* 3 +
|
||||
(WebRtc_Word32)stretchPitchLP1[k] )>>2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)((
|
||||
(WebRtc_Word32)stretchPitchLP[k] +
|
||||
(WebRtc_Word32)stretchPitchLP1[k])>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
|
||||
{
|
||||
stretchPitchLP[k] = (WebRtc_Word16)(
|
||||
(stretchPitchLP[k] +
|
||||
(WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
|
||||
{
|
||||
myDecayRate += 55; //(myDecayRate>>1);
|
||||
(ISACdec_obj->plcstr_obj).pitchCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------ Sum the noisy and periodic signals ------ */
|
||||
Vector_Word16_1[i] = (WebRtc_Word16)WEBRTC_SPL_ADD_SAT_W16(
|
||||
wNoisyLP, wPriodicLP );
|
||||
Vector_Word32_2[i] = (WebRtc_Word32)WEBRTC_SPL_ADD_SAT_W32(
|
||||
wNoisyHP, wPriodicHP );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------- residual signal is reconstructed ------------------ */
|
||||
|
||||
k = (ISACdec_obj->plcstr_obj).pitchIndex;
|
||||
/* --- Write one pitch cycle for recovery block --- */
|
||||
|
||||
for( i = 0; i < RECOVERY_OVERLAP; i++ )
|
||||
{
|
||||
(ISACdec_obj->plcstr_obj).overlapLP[i] = (WebRtc_Word16)(
|
||||
WEBRTC_SPL_MUL_16_16_RSFT(stretchPitchLP[k],
|
||||
(ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15) );
|
||||
k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
|
||||
}
|
||||
|
||||
(ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = (ISACdec_obj->plcstr_obj).stretchLag << 7;
|
||||
|
||||
|
||||
/* --- Inverse Pitch Filter --- */
|
||||
WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
|
||||
&ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
|
||||
|
||||
/* reduce gain to compensate for pitch enhancer */
|
||||
/* gain = 1.0f - 0.45f * AvgPitchGain; */
|
||||
tmp32a = WEBRTC_SPL_MUL_16_16_RSFT((ISACdec_obj->plcstr_obj).AvgPitchGain_Q12,
|
||||
29, 0); // Q18
|
||||
tmp32b = 262144 - tmp32a; // Q18
|
||||
gainQ13 = (WebRtc_Word16) (tmp32b >> 5); // Q13
|
||||
|
||||
/* perceptual post-filtering (using normalized lattice filter) */
|
||||
for (k = 0; k < FRAMESAMPLES_HALF; k++)
|
||||
Vector_Word32_1[k] = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16(
|
||||
Vector_Word16_2[k], gainQ13) << 3; // Q25
|
||||
|
||||
|
||||
WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
|
||||
(ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
|
||||
Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
|
||||
|
||||
WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
|
||||
(ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
|
||||
Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
|
||||
|
||||
/* recombine the 2 bands */
|
||||
|
||||
/* Form the polyphase signals, and compensate for DC offset */
|
||||
for (k=0;k<FRAMESAMPLES_HALF;k++)
|
||||
{
|
||||
/* Construct a new upper channel signal*/
|
||||
tmp_1 = (WebRtc_Word16) WEBRTC_SPL_SAT(32767,
|
||||
(((WebRtc_Word32)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)), -32768);
|
||||
/* Construct a new lower channel signal*/
|
||||
tmp_2 = (WebRtc_Word16) WEBRTC_SPL_SAT(32767,
|
||||
(((WebRtc_Word32)Vector_Word16_1[k]-Vector_Word16_2[k])), -32768);
|
||||
Vector_Word16_1[k] = tmp_1;
|
||||
Vector_Word16_2[k] = tmp_2;
|
||||
}
|
||||
|
||||
|
||||
WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
|
||||
Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
|
||||
|
||||
(ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
|
||||
*current_framesamples = 480;
|
||||
|
||||
return len;
|
||||
}
|
Reference in New Issue
Block a user