📄 dtx.c
字号:
/*-------------------------------------------------------------------*
* DTX.C *
*-------------------------------------------------------------------*
* DTX functions *
*-------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "math_op.h"
#include "cnst.h"
#include "acelp.h" /* prototype of functions */
#include "bits.h"
#include "dtx.h"
#include "count.h"
#include "log2.h"
static void aver_isf_history(
Word16 isf_old[],
Word16 indices[],
Word32 isf_aver[]
);
static void find_frame_indices(
Word16 isf_old_tx[],
Word16 indices[],
dtx_encState * st
);
static Word16 dithering_control(
dtx_encState * st
);
static void CN_dithering(
Word16 isf[M],
Word32 * L_log_en_int,
Word16 * dither_seed
);
/* excitation energy adjustment depending on speech coder mode used, Q7 */
static Word16 en_adjust[9] =
{
230, /* mode0 = 7k : -5.4dB */
179, /* mode1 = 9k : -4.2dB */
141, /* mode2 = 12k : -3.3dB */
128, /* mode3 = 14k : -3.0dB */
122, /* mode4 = 16k : -2.85dB */
115, /* mode5 = 18k : -2.7dB */
115, /* mode6 = 20k : -2.7dB */
115, /* mode7 = 23k : -2.7dB */
115 /* mode8 = 24k : -2.7dB */
};
/**************************************************************************
*
*
* Function : dtx_enc_init
*
*
**************************************************************************/
Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[])
{
dtx_encState *s;
test();
if (st == (dtx_encState **) NULL)
{
fprintf(stderr, "dtx_enc_init: invalid parameter\n");
return -1;
}
*st = NULL;
/* allocate memory */
test();
if ((s = (dtx_encState *) malloc(sizeof(dtx_encState))) == NULL)
{
fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");
return -1;
}
dtx_enc_reset(s, isf_init);
*st = s;
return 0;
}
/**************************************************************************
*
*
* Function : dtx_enc_reset
*
*
**************************************************************************/
Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[])
{
Word16 i;
test();
if (st == (dtx_encState *) NULL)
{
fprintf(stderr, "dtx_enc_reset: invalid parameter\n");
return -1;
}
st->hist_ptr = 0; move16();
st->log_en_index = 0; move16();
/* Init isf_hist[] */
for (i = 0; i < DTX_HIST_SIZE; i++)
{
Copy(isf_init, &st->isf_hist[i * M], M);
}
st->cng_seed = RANDOM_INITSEED; move16();
/* Reset energy history */
Set_zero(st->log_en_hist, DTX_HIST_SIZE);
st->dtxHangoverCount = DTX_HANG_CONST; move16();
st->decAnaElapsedCount = 32767; move16();
for (i = 0; i < 28; i++)
{
st->D[i] = 0; move16();
}
for (i = 0; i < DTX_HIST_SIZE - 1; i++)
{
st->sumD[i] = 0; move32();
}
return 1;
}
/**************************************************************************
*
*
* Function : dtx_enc_exit
*
*
**************************************************************************/
void dtx_enc_exit(dtx_encState ** st)
{
test();
if (st == NULL || *st == NULL)
return;
/* deallocate memory */
free(*st);
*st = NULL;
return;
}
/**************************************************************************
*
*
* Function : dtx_enc
*
*
**************************************************************************/
Word16 dtx_enc(
dtx_encState * st, /* i/o : State struct */
Word16 isf[M], /* o : CN ISF vector */
Word16 * exc2, /* o : CN excitation */
Word16 ** prms
)
{
Word16 i, j;
Word16 indice[7];
Word16 log_en, gain, level, exp, exp0, tmp;
Word16 log_en_int_e, log_en_int_m;
Word32 L_isf[M], ener32, level32;
Word16 isf_order[3];
Word16 CN_dith;
/* VOX mode computation of SID parameters */
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 */
log_en = add(log_en, st->log_en_hist[i]);
}
find_frame_indices(st->isf_hist, isf_order, st);
aver_isf_history(st->isf_hist, isf_order, L_isf);
for (j = 0; j < M; j++)
{
isf[j] = extract_l(L_shr(L_isf[j], 3)); move16(); /* divide by 8 */
}
/* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E). */
/* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */
/* increase dynamics to 7 bits (Q8) */
log_en = shr(log_en, 2);
/* Add 2 in Q8 = 512 to get log2(E) between 0:24 */
log_en = add(log_en, 512);
/* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */
log_en = mult(log_en, 21504);
/* Quantize Energy */
st->log_en_index = shr(log_en, 6);
test();
if (sub(st->log_en_index, 63) > 0)
{
st->log_en_index = 63;
move16();
}
test();
if (st->log_en_index < 0)
{
st->log_en_index = 0;
move16();
}
/* Quantize ISFs */
Qisf_ns(isf, isf, indice);
Parm_serial(indice[0], 6, prms);
Parm_serial(indice[1], 6, prms);
Parm_serial(indice[2], 6, prms);
Parm_serial(indice[3], 5, prms);
Parm_serial(indice[4], 5, prms);
Parm_serial((st->log_en_index), 6, prms);
CN_dith = dithering_control(st);
Parm_serial(CN_dith, 1, prms);
/* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) ); */
/* log2(E) in Q9 (log2(E) lies in between -2:22) */
log_en = shl(st->log_en_index, 15 - 6);
/* Divide by 2.625; log_en will be between 0:24 */
log_en = mult(log_en, 12483);
/* the result corresponds to log2(gain) in Q10 */
/* Find integer part */
log_en_int_e = shr(log_en, 10);
/* Find fractional part */
log_en_int_m = (Word16) (log_en & 0x3ff); logic16();
log_en_int_m = shl(log_en_int_m, 5);
/* Subtract 2 from log_en 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);
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();
}
return 0;
}
/**************************************************************************
*
*
* Function : dtx_buffer Purpose : handles the DTX buffer
*
*
**************************************************************************/
Word16 dtx_buffer(
dtx_encState * st, /* i/o : State struct */
Word16 isf_new[], /* i : isf vector */
Word32 enr, /* i : residual energy (in L_FRAME) */
Word16 codec_mode
)
{
Word16 log_en;
Word16 log_en_e;
Word16 log_en_m;
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 lsp vector into buffer */
Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M);
/* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f); */
Log2(enr, &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));
/* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The
* constant 0.0059322 takes into account windowings and analysis length from autocorrelation
* computations; 7.39722 in Q7 = 947 */
/* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
/* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */
/* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0 (1024 in Q7) */
/* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
log_en = sub(log_en, add(1024, en_adjust[codec_mode]));
/* Insert into the buffer */
st->log_en_hist[st->hist_ptr] = log_en;move16();
return 0;
}
/**************************************************************************
*
*
* Function : tx_dtx_handler Purpose : adds extra speech hangover
* to analyze speech on
* the decoding side.
*
**************************************************************************/
void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
Word16 vad_flag, /* i : vad decision */
Word16 * usedMode /* i/o : mode changed or not */
)
{
/* this state machine is in synch with the GSMEFR txDtx machine */
st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); move16();
test();
if (vad_flag != 0)
{
st->dtxHangoverCount = DTX_HANG_CONST; move16();
} else
{ /* non-speech */
test();
if (st->dtxHangoverCount == 0)
{ /* out of decoder analysis hangover */
st->decAnaElapsedCount = 0; move16();
*usedMode = MRDTX; move16();
} else
{ /* in possible analysis hangover */
st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); move16();
/* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */
test();
if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),
DTX_ELAPSED_FRAMES_THRESH) < 0)
{
*usedMode = MRDTX; move16();
/* if short time since decoder update, do not add extra HO */
}
/* else override VAD and stay in speech mode *usedMode and add extra hangover */
}
}
return;
}
/**************************************************************************
*
*
* Function : dtx_dec_init
*
*
**************************************************************************/
Word16 dtx_dec_init(dtx_decState ** st, Word16 isf_init[])
{
dtx_decState *s;
test();
if (st == (dtx_decState **) NULL)
{
fprintf(stderr, "dtx_dec_init: invalid parameter\n");
return -1;
}
*st = NULL;
/* allocate memory */
test();
if ((s = (dtx_decState *) malloc(sizeof(dtx_decState))) == NULL)
{
fprintf(stderr, "dtx_dec_init: can not malloc state structure\n");
return -1;
}
dtx_dec_reset(s, isf_init);
*st = s;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -