📄 dec_gain.c
字号:
}
else
{
gain_in = 32767;
}
exp = exp - i;
/*
* g0 = sqrt(gain_in/gain_out)
*/
s = (gain_out << 15) / gain_in;
s = s << (7 - exp); /* s = gain_out / gain_in */
s = D_UTIL_inverse_sqrt(s);
g0 = ((s << 9) + 0x8000) >> 16;
}
/* sig_out(n) = gain(n) sig_out(n) */
for(i = 0; i < l_trm; i++)
{
s = (sig_out[i] * g0) >> 13;
sig_out[i] = D_UTIL_saturate(s);
}
return;
}
/*
* D_GAIN_insert_lag
*
* Parameters:
* array I/O: pitch lag history
* n I: history size
* x I: lag value
*
* Function:
* Insert lag into correct location
*
* Returns:
* void
*/
static void D_GAIN_insert_lag(Word16 array[], Word32 n, Word16 x)
{
Word32 i;
for(i = n - 1; i >= 0; i--)
{
if(x < array[i])
{
array[i + 1] = array[i];
}
else
{
break;
}
}
array[i + 1] = x;
}
/*
* D_GAIN_sort_lag
*
* Parameters:
* array I/O: pitch lag history
* n I: history size
*
* Function:
* Sorting of the lag history
*
* Returns:
* void
*/
static void D_GAIN_sort_lag(Word16 array[], Word16 n)
{
Word32 i;
for(i = 0; i < n; i++)
{
D_GAIN_insert_lag(array, i, array[i]);
}
}
/*
* D_GAIN_lag_concealment_init
*
* Parameters:
* lag_hist O: pitch lag history
*
* Function:
* Initialise lag history to 64
*
* Returns:
* void
*/
void D_GAIN_lag_concealment_init(Word16 lag_hist[])
{
Word32 i;
for(i = 0; i < L_LTPHIST; i++)
{
lag_hist[i] = 64;
}
}
/*
* D_GAIN_lag_concealment
*
* Parameters:
* gain_hist I: gain history
* lag_hist I: pitch lag history
* T0 O: current lag
* old_T0 I: previous lag
* seed I/O: seed for random
* unusable_frame I: lost frame
*
* Function:
* Concealment of LTP lags during bad frames
*
* Returns:
* void
*/
void D_GAIN_lag_concealment(Word16 gain_hist[], Word16 lag_hist[],
Word32 *T0, Word16 *old_T0, Word16 *seed,
Word16 unusable_frame)
{
Word32 i, lagDif, tmp, tmp2, D2, meanLag = 0;
Word16 lag_hist2[L_LTPHIST] = {0};
Word16 maxLag, minLag, lastLag;
Word16 minGain, lastGain, secLastGain;
Word16 D;
/*
* Is lag index such that it can be aplied directly
* or does it has to be subtituted
*/
lastGain = gain_hist[4];
secLastGain = gain_hist[3];
lastLag = lag_hist[0];
/* SMALLEST history lag */
minLag = lag_hist[0];
for(i = 1; i < L_LTPHIST; i++)
{
if(lag_hist[i] < minLag)
{
minLag = lag_hist[i];
}
}
/* BIGGEST history lag */
maxLag = lag_hist[0];
for(i = 1; i < L_LTPHIST; i++)
{
if(lag_hist[i] > maxLag)
{
maxLag = lag_hist[i];
}
}
/* SMALLEST history gain */
minGain = gain_hist[0];
for(i = 1; i < L_LTPHIST; i++)
{
if(gain_hist[i] < minGain)
{
minGain = gain_hist[i];
}
}
/* Difference between MAX and MIN lag */
lagDif = maxLag - minLag;
if(unusable_frame != 0)
{
/*
* LTP-lag for RX_SPEECH_LOST
* Recognition of the LTP-history
*/
if((minGain > 8192) & (lagDif < 10))
{
*T0 = *old_T0;
}
else if((lastGain > 8192) && (secLastGain > 8192))
{
*T0 = lag_hist[0];
}
else
{
/*
* SORT
* The sorting of the lag history
*/
for(i = 0; i < L_LTPHIST; i++)
{
lag_hist2[i] = lag_hist[i];
}
D_GAIN_sort_lag(lag_hist2, 5);
/*
* Lag is weighted towards bigger lags
* and random variation is added
*/
lagDif = (lag_hist2[4] - lag_hist2[2]);
if(lagDif > 40)
{
lagDif = 40;
}
D = D_UTIL_random(seed); /* D={-1, ...,1} */
/* D2={-lagDif/2..lagDif/2} */
tmp = lagDif >> 1;
D2 = (tmp * D) >> 15;
tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
*T0 = ((tmp * ONE_PER_3) >> 15) + D2;
}
/* New lag is not allowed to be bigger or smaller than last lag values */
if(*T0 > maxLag)
{
*T0 = maxLag;
}
if(*T0 < minLag)
{
*T0 = minLag;
}
}
else
{
/*
* LTP-lag for RX_BAD_FRAME
* MEAN lag
*/
meanLag = 0;
for(i = 0; i < L_LTPHIST; i++)
{
meanLag = meanLag + lag_hist[i];
}
meanLag = (meanLag * ONE_PER_LTPHIST) >> 15;
tmp = *T0 - maxLag;
tmp2 = *T0 - lastLag;
if((lagDif < 10) & (*T0 > (minLag - 5)) & (tmp < 5))
{
*T0 = *T0;
}
else if((lastGain > 8192) & (secLastGain > 8192) & ((tmp2 > - 10)
& (tmp2 < 10)))
{
*T0 = *T0;
}
else if((minGain < 6554) & (lastGain == minGain) & ((*T0 > minLag)
& (*T0 < maxLag)))
{
*T0 = *T0;
}
else if((lagDif < 70) & (*T0 > minLag) & (*T0 < maxLag))
{
*T0 = *T0;
}
else if((*T0 > meanLag) & (*T0 < maxLag))
{
*T0 = *T0;
}
else
{
if((minGain > 8192) & (lagDif < 10))
{
*T0 = lag_hist[0];
}
else if((lastGain > 8192) & (secLastGain > 8192))
{
*T0 = lag_hist[0];
}
else
{
/*
* SORT
* The sorting of the lag history
*/
for(i = 0; i < L_LTPHIST; i++)
{
lag_hist2[i] = lag_hist[i];
}
D_GAIN_sort_lag(lag_hist2, 5);
/*
* Lag is weighted towards bigger lags
* and random variation is added
*/
lagDif = lag_hist2[4] - lag_hist2[2];
if(lagDif > 40)
{
lagDif = 40;
}
D = D_UTIL_random(seed); /* D={-1,.., 1} */
/* D2={-lagDif/2..lagDif/2} */
tmp = lagDif >> 1;
D2 = (tmp * D) >> 15;
tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
*T0 = ((tmp * ONE_PER_3) >> 15) + D2;
}
/*
* New lag is not allowed to be bigger or
* smaller than last lag values
*/
if(*T0 > maxLag)
{
*T0 = maxLag;
}
if(*T0 < minLag)
{
*T0 = minLag;
}
}
}
}
/*
* D_GAIN_adaptive_codebook_excitation
*
* Parameters:
* exc I/O: excitation buffer
* T0 I: integer pitch lag
* frac I: fraction of lag
*
* Function:
* Compute the result of Word32 term prediction with fractional
* interpolation of resolution 1/4.
*
* Returns:
* interpolated signal (adaptive codebook excitation)
*/
void D_GAIN_adaptive_codebook_excitation(Word16 exc[], Word32 T0, Word32 frac)
{
Word32 i, j, k, sum;
Word16 *x;
x = &exc[ - T0];
frac = -(frac);
if(frac < 0)
{
frac = (frac + UP_SAMP);
x--;
}
x = x - L_INTERPOL2 + 1;
for(j = 0; j < L_SUBFR + 1; j++)
{
sum = 0L;
for(i = 0, k = ((UP_SAMP - 1) - frac); i < 2 * L_INTERPOL2; i++,
k += UP_SAMP)
{
sum += x[i] * D_ROM_inter4_2[k];
}
sum = (sum + 0x2000) >> 14;
exc[j] = D_UTIL_saturate(sum);
x++;
}
return;
}
/*
* D_GAIN_pitch_sharpening
*
* Parameters:
* x I/O: impulse response (or algebraic code)
* pit_lag I: pitch lag
* sharp I: (Q15) pitch sharpening factor
*
* Function:
* Performs Pitch sharpening routine for one subframe.
*
* Returns:
* void
*/
void D_GAIN_pitch_sharpening(Word16 *x, Word32 pit_lag, Word16 sharp)
{
Word32 i;
Word32 tmp;
for(i = pit_lag; i < L_SUBFR; i++)
{
tmp = x[i] << 15;
tmp += x[i - pit_lag] * sharp;
x[i] = (Word16)((tmp + 0x4000) >> 15);
}
return;
}
/*
* D_GAIN_find_voice_factor
*
* Parameters:
* exc I: pitch excitation
* Q_exc I: exc format
* gain_pit I: (Q14) gain of pitch
* code I: (Q9) fixed codebook excitation
* gain_code I: (Q0) gain of code
* L_subfr I: subframe length
*
* Function:
* Find the voicing factor.
*
* Returns:
* (Q15) 1=voice to -1=unvoiced
*/
Word16 D_GAIN_find_voice_factor(Word16 exc[], Word16 Q_exc,
Word16 gain_pit, Word16 code[],
Word16 gain_code, Word16 L_subfr)
{
Word32 tmp, ener1, ener2, i;
Word16 exp, exp1, exp2;
ener1 = (D_UTIL_dot_product12(exc, exc, L_subfr, &exp1)) >> 16;
exp1 = (Word16)(exp1 - (Q_exc + Q_exc));
tmp = (gain_pit * gain_pit) << 1;
exp = D_UTIL_norm_l(tmp);
tmp = (tmp << exp) >> 16;
ener1 = (ener1 * tmp) >> 15;
exp1 = (Word16)((exp1 - exp) - 10); /* 10 -> gain_pit Q14 to Q9 */
ener2 = D_UTIL_dot_product12(code, code, L_subfr, &exp2) >> 16;
exp = D_UTIL_norm_s(gain_code);
tmp = gain_code << exp;
tmp = (tmp * tmp) >> 15;
ener2 = (ener2 * tmp) >> 15;
exp2 = (Word16)(exp2 - (exp << 1));
i = exp1 - exp2;
if(i >= 0)
{
ener1 = ener1 >> 1;
ener2 = ener2 >> (i + 1);
}
else if(i > (-16))
{
ener1 = ener1 >> (1 - i);
ener2 = ener2 >> 1;
}
else
{
ener1 = 0;
ener2 = ener2 >> 1;
}
tmp = ener1 - ener2;
ener1 = (ener1 + ener2) + 1;
tmp = (tmp << 15) / ener1;
return((Word16)tmp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -