📄 dtx.c
字号:
/**************************************************************************
*
*
* Function : dtx_dec_reset
*
*
**************************************************************************/
Word16 dtx_dec_reset(dtx_decState * st, Word16 isf_init[])
{
Word16 i;
test();
if (st == (dtx_decState *) NULL)
{
fprintf(stderr, "dtx_dec_reset: invalid parameter\n");
return -1;
}
st->since_last_sid = 0; move16();
st->true_sid_period_inv = (1 << 13); move16(); /* 0.25 in Q15 */
st->log_en = 3500; move16();
st->old_log_en = 3500; move16();
/* low level noise for better performance in DTX handover cases */
st->cng_seed = RANDOM_INITSEED; move16();
st->hist_ptr = 0; move16();
/* Init isf_hist[] and decoder log frame energy */
Copy(isf_init, st->isf, M);
Copy(isf_init, st->isf_old, M);
for (i = 0; i < DTX_HIST_SIZE; i++)
{
Copy(isf_init, &st->isf_hist[i * M], M);
st->log_en_hist[i] = st->log_en; move16();
}
st->dtxHangoverCount = DTX_HANG_CONST; move16();
st->decAnaElapsedCount = 32767; move16();
st->sid_frame = 0; move16();
st->valid_data = 0; move16();
st->dtxHangoverAdded = 0; move16();
st->dtxGlobalState = SPEECH; move16();
st->data_updated = 0; move16();
st->dither_seed = RANDOM_INITSEED; move16();
st->CN_dith = 0;
return 0;
}
/**************************************************************************
*
*
* Function : dtx_dec_exit
*
*
**************************************************************************/
void dtx_dec_exit(dtx_decState ** st)
{
test();
if (st == NULL || *st == NULL)
return;
/* deallocate memory */
free(*st);
*st = NULL;
return;
}
/*
Table of new SPD synthesis states
| previous SPD_synthesis_state
Incoming |
frame_type | SPEECH | DTX | DTX_MUTE
---------------------------------------------------------------
RX_SPEECH_GOOD , | | |
RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
----------------------------------------------------------------
RX_SPEECH_BAD, | SPEECH | DTX | DTX_MUTE
----------------------------------------------------------------
RX_SID_FIRST, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
----------------------------------------------------------------
RX_SID_UPDATE, | DTX | DTX | DTX
----------------------------------------------------------------
RX_SID_BAD, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
----------------------------------------------------------------
RX_NO_DATA, | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
RX_SPARE |(class2 garb.)| |
----------------------------------------------------------------
*/
/**************************************************************************
*
*
* Function : dtx_dec
*
*
**************************************************************************/
Word16 dtx_dec(
dtx_decState * st, /* i/o : State struct */
Word16 * exc2, /* o : CN excitation */
Word16 new_state, /* i : New DTX state */
Word16 isf[], /* o : CN ISF vector */
Word16 ** prms
)
{
Word16 log_en_index;
Word16 ind[7];
Word16 i, j;
Word16 int_fac;
Word16 gain;
Word32 L_isf[M], L_log_en_int, level32, ener32;
Word16 ptr;
Word16 tmp_int_length;
Word16 tmp, exp, exp0, log_en_int_e, log_en_int_m, level;
/* This function is called if synthesis state is not SPEECH the globally passed inputs to this function
* are st->sid_frame st->valid_data st->dtxHangoverAdded new_state (SPEECH, DTX, DTX_MUTE) */
test();test();
if ((st->dtxHangoverAdded != 0) &&
(st->sid_frame != 0))
{
/* sid_first after dtx hangover period */
/* or sid_upd after dtxhangover */
/* consider twice the last frame */
ptr = add(st->hist_ptr, 1);
test();
if (sub(ptr, DTX_HIST_SIZE) == 0)
ptr = 0; move16();
Copy(&st->isf_hist[st->hist_ptr * M], &st->isf_hist[ptr * M], M);
st->log_en_hist[ptr] = st->log_en_hist[st->hist_ptr]; move16();
/* compute mean log energy and isf from decoded signal (SID_FIRST) */
st->log_en = 0; move16();
for (i = 0; i < M; i++)
{
L_isf[i] = 0; move32();
}
/* average energy and isf */
for (i = 0; i < DTX_HIST_SIZE; i++)
{
/* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer log_en is in Q10 */
st->log_en = add(st->log_en, st->log_en_hist[i]); move16();
for (j = 0; j < M; j++)
{
L_isf[j] = L_add(L_isf[j], L_deposit_l(st->isf_hist[i * M + j])); move32();
}
}
/* st->log_en in Q9 */
st->log_en = shr(st->log_en, 1); move16();
/* Add 2 in Q9, in order to have only positive values for Pow2 */
/* this value is subtracted back after Pow2 function */
st->log_en = add(st->log_en, 1024);move16();
test();
if (st->log_en < 0)
st->log_en = 0; move16();
for (j = 0; j < M; j++)
{
st->isf[j] = extract_l(L_shr(L_isf[j], 3)); move32(); /* divide by 8 */
}
}
test();
if (st->sid_frame != 0)
{
/* Set old SID parameters, always shift */
/* even if there is no new valid_data */
Copy(st->isf, st->isf_old, M);
st->old_log_en = st->log_en; move16();
test();
if (st->valid_data != 0) /* new data available (no CRC) */
{
/* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
/* Compute interpolation factor, since the division only works * for values of since_last_sid <
* 32 we have to limit the * interpolation to 32 frames */
tmp_int_length = st->since_last_sid; move16();
test();
if (sub(tmp_int_length, 32) > 0)
{
tmp_int_length = 32; move16();
}
test();
if (sub(tmp_int_length, 2) >= 0)
{
move16();
st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
} else
{
st->true_sid_period_inv = 1 << 14; /* 0.5 it Q15 */move16();
}
ind[0] = Serial_parm(6, prms); move16();
ind[1] = Serial_parm(6, prms); move16();
ind[2] = Serial_parm(6, prms); move16();
ind[3] = Serial_parm(5, prms); move16();
ind[4] = Serial_parm(5, prms); move16();
Disf_ns(ind, st->isf);
log_en_index = Serial_parm(6, prms);
/* read background noise stationarity information */
st->CN_dith = Serial_parm(1, prms); move16();
/* st->log_en = (float)log_en_index / 2.625 - 2.0; */
/* log2(E) in Q9 (log2(E) lies in between -2:22) */
st->log_en = shl(log_en_index, 15 - 6); move16();
/* Divide by 2.625 */
st->log_en = mult(st->log_en, 12483); move16();
/* Subtract 2 in Q9 is done later, after Pow2 function */
/* no interpolation at startup after coder reset */
/* or when SID_UPD has been received right after SPEECH */
test();test();
if ((st->data_updated == 0) ||
(sub(st->dtxGlobalState, SPEECH) == 0))
{
Copy(st->isf, st->isf_old, M);
st->old_log_en = st->log_en; move16();
}
} /* endif valid_data */
} /* endif sid_frame */
test();
test();
if ((st->sid_frame != 0) && (st->valid_data != 0))
{
st->since_last_sid = 0; move16();
}
/* Interpolate SID info */
int_fac = shl(st->since_last_sid, 10); /* Q10 */move16();
int_fac = mult(int_fac, st->true_sid_period_inv); /* Q10 * Q15 -> Q10 */
/* Maximize to 1.0 in Q10 */
test();
if (sub(int_fac, 1024) > 0)
{
int_fac = 1024; move16();
}
int_fac = shl(int_fac, 4); /* Q10 -> Q14 */
L_log_en_int = L_mult(int_fac, st->log_en); /* Q14 * Q9 -> Q24 */
for (i = 0; i < M; i++)
{
isf[i] = mult(int_fac, st->isf[i]);/* Q14 * Q15 -> Q14 */move16();
}
int_fac = sub(16384, int_fac); /* 1-k in Q14 */move16();
/* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */
L_log_en_int = L_mac(L_log_en_int, int_fac, st->old_log_en);
for (i = 0; i < M; i++)
{
/* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
isf[i] = add(isf[i], mult(int_fac, st->isf_old[i])); move16();
isf[i] = shl(isf[i], 1); /* Q14 -> Q15 */move16();
}
/* If background noise is non-stationary, insert comfort noise dithering */
if (st->CN_dith != 0)
{
CN_dithering(isf, &L_log_en_int, &st->dither_seed);
}
/* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
/* Q25 -> Q16 */
L_log_en_int = L_shr(L_log_en_int, 9);
/* Find integer part */
log_en_int_e = extract_h(L_log_en_int);
/* Find fractional part */
log_en_int_m = extract_l(L_shr(L_sub(L_log_en_int, L_deposit_h(log_en_int_e)), 1));
/* Subtract 2 from L_log_en_int in Q9, i.e divide the gain by 2 (energy by 4) */
/* Add 16 in order to have the result of pow2 in Q16 */
log_en_int_e = add(log_en_int_e, 16 - 1);
/* level = (float)( pow( 2.0f, log_en ) ); */
level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
exp0 = norm_l(level32);
level32 = L_shl(level32, exp0); /* level in Q31 */
exp0 = sub(15, exp0);
level = extract_h(level32); /* level in Q15 */
/* generate white noise vector */
for (i = 0; i < L_FRAME; i++)
{
exc2[i] = shr(Random(&(st->cng_seed)), 4); move16();
}
/* gain = level / sqrt(ener) * sqrt(L_FRAME) */
/* energy of generated excitation */
ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
Isqrt_n(&ener32, &exp);
gain = extract_h(ener32);
gain = mult(level, gain); /* gain in Q15 */
exp = add(exp0, exp);
/* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
exp = add(exp, 4);
for (i = 0; i < L_FRAME; i++)
{
tmp = mult(exc2[i], gain); /* Q0 * Q15 */
exc2[i] = shl(tmp, exp); move16();
}
test();
if (sub(new_state, DTX_MUTE) == 0)
{
/* mute comfort noise as it has been quite a long time since last SID update was performed */
tmp_int_length = st->since_last_sid; move16();
test();
if (sub(tmp_int_length, 32) > 0)
{
tmp_int_length = 32; move16();
}
move16();
st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
st->since_last_sid = 0; move16();
st->old_log_en = st->log_en; move16();
/* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
st->log_en = sub(st->log_en, 64); move16();
}
/* reset interpolation length timer if data has been updated. */
test();test();test();test();
if ((st->sid_frame != 0) &&
((st->valid_data != 0) ||
((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
{
st->since_last_sid = 0; move16();
st->data_updated = 1; move16();
}
return 0;
}
void dtx_dec_activity_update(
dtx_decState * st,
Word16 isf[],
Word16 exc[])
{
Word16 i;
Word32 L_frame_en;
Word16 log_en_e, log_en_m, log_en;
st->hist_ptr = add(st->hist_ptr, 1); move16();
test();
if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
{
st->hist_ptr = 0; move16();
}
Copy(isf, &st->isf_hist[st->hist_ptr * M], M);
/* compute log energy based on excitation frame energy in Q0 */
L_frame_en = 0; move32();
for (i = 0; i < L_FRAME; i++)
{
L_frame_en = L_mac(L_frame_en, exc[i], exc[i]);
}
L_frame_en = L_shr(L_frame_en, 1);
/* log_en = (float)log10(L_frame_en/(float)L_FRAME)/(float)log10(2.0f); */
Log2(L_frame_en, &log_en_e, &log_en_m);
/* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
log_en = shl(log_en_e, 7); /* Q7 */
log_en = add(log_en, shr(log_en_m, 15 - 7));
/* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
log_en = sub(log_en, 1024);
/* insert into log energy buffer */
st->log_en_hist[st->hist_ptr] = log_en;move16();
return;
}
/*
Table of new SPD synthesis states
| previous SPD_synthesis_state
Incoming |
frame_type | SPEECH | DTX | DTX_MUTE
---------------------------------------------------------------
RX_SPEECH_GOOD , | | |
RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
----------------------------------------------------------------
RX_SPEECH_BAD, | SPEECH | DTX | DTX_MUTE
----------------------------------------------------------------
RX_SID_FIRST, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
----------------------------------------------------------------
RX_SID_UPDATE, | DTX | DTX | DTX
----------------------------------------------------------------
RX_SID_BAD, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
----------------------------------------------------------------
RX_NO_DATA, | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -