📄 nb_celp.c
字号:
pit_max=offset;
#ifdef EPIC_48K
if (st->lbr_48k)
{
pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
st->lpcSize, st->subframeSize, bits, stack,
exc, syn_resp, st->complexity, ol_pitch_id, st->plc_tuning);
} else {
#endif
/* Perform pitch search */
pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
st->lpcSize, st->subframeSize, bits, stack,
exc, syn_resp, st->complexity, 0, st->plc_tuning);
#ifdef EPIC_48K
}
#endif
st->pitch[sub]=pitch;
} else {
speex_error ("No pitch prediction, what's wrong");
}
/* Quantization of innovation */
{
spx_sig_t *innov;
spx_word32_t ener=0;
spx_word16_t fine_gain;
innov = st->innov+sub*st->subframeSize;
for (i=0;i<st->subframeSize;i++)
innov[i]=0;
for (i=0;i<st->subframeSize;i++)
real_exc[i] = SUB32(real_exc[i], exc[i]);
ener = SHL32(EXTEND32(compute_rms(real_exc, st->subframeSize)),SIG_SHIFT);
/*FIXME: Should use DIV32_16 and make sure result fits in 16 bits */
#ifdef FIXED_POINT
{
spx_word32_t f = DIV32(ener,PSHR32(ol_gain,SIG_SHIFT));
if (f<=32767)
fine_gain = f;
else
fine_gain = 32767;
}
#else
fine_gain = DIV32_16(ener,PSHR32(ol_gain,SIG_SHIFT));
#endif
/* Calculate gain correction for the sub-frame (if any) */
if (SUBMODE(have_subframe_gain))
{
int qe;
if (SUBMODE(have_subframe_gain)==3)
{
qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8);
speex_bits_pack(bits, qe, 3);
ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain);
} else {
qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2);
speex_bits_pack(bits, qe, 1);
ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain);
}
} else {
ener=ol_gain;
}
/*printf ("%f %f\n", ener, ol_gain);*/
/* Normalize innovation */
signal_div(target, target, ener, st->subframeSize);
/* Quantize innovation */
if (SUBMODE(innovation_quant))
{
/* Codebook search */
SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
SUBMODE(innovation_params), st->lpcSize, st->subframeSize,
innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook));
/* De-normalize innovation and update excitation */
signal_mul(innov, innov, ener, st->subframeSize);
for (i=0;i<st->subframeSize;i++)
exc[i] = ADD32(exc[i],innov[i]);
} else {
speex_error("No fixed codebook");
}
/* In some (rare) modes, we do a second search (more bits) to reduce noise even more */
if (SUBMODE(double_codebook)) {
char *tmp_stack=stack;
VARDECL(spx_sig_t *innov2);
ALLOC(innov2, st->subframeSize, spx_sig_t);
for (i=0;i<st->subframeSize;i++)
innov2[i]=0;
for (i=0;i<st->subframeSize;i++)
target[i]*=2.2;
SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
SUBMODE(innovation_params), st->lpcSize, st->subframeSize,
innov2, syn_resp, bits, stack, st->complexity, 0);
signal_mul(innov2, innov2, (spx_word32_t) (ener*(1/2.2)), st->subframeSize);
for (i=0;i<st->subframeSize;i++)
exc[i] = ADD32(exc[i],innov2[i]);
stack = tmp_stack;
}
}
/* Final signal synthesis from excitation */
iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);
/* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */
if (st->complexity!=0)
filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw);
}
/* Store the LSPs for interpolation in the next frame */
if (st->submodeID>=1)
{
for (i=0;i<st->lpcSize;i++)
st->old_lsp[i] = st->lsp[i];
for (i=0;i<st->lpcSize;i++)
st->old_qlsp[i] = st->qlsp[i];
}
if (st->submodeID==1)
{
if (st->dtx_count)
speex_bits_pack(bits, 15, 4);
else
speex_bits_pack(bits, 0, 4);
}
/* The next frame will not be the first (Duh!) */
st->first = 0;
#ifdef RESYNTH
/* Replace input by synthesized speech */
for (i=0;i<st->frameSize;i++)
{
spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
if (sig>32767)
sig = 32767;
if (sig<-32767)
sig = -32767;
in[i]=sig;
}
#endif
if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0)
st->bounded_pitch = 1;
else
st->bounded_pitch = 0;
return 1;
}
void *nb_decoder_init(const SpeexMode *m)
{
DecState *st;
const SpeexNBMode *mode;
int i;
mode=(const SpeexNBMode*)m->mode;
st = (DecState *)speex_alloc(sizeof(DecState));
if (!st)
return NULL;
#if defined(VAR_ARRAYS) || defined (USE_ALLOCA)
st->stack = NULL;
#else
st->stack = (char*)speex_alloc_scratch(NB_DEC_STACK);
#endif
st->mode=m;
st->encode_submode = 1;
#ifdef EPIC_48K
st->lbr_48k=mode->lbr48k;
#endif
st->first=1;
/* Codec parameters, should eventually have several "modes"*/
st->frameSize = mode->frameSize;
st->nbSubframes=mode->frameSize/mode->subframeSize;
st->subframeSize=mode->subframeSize;
st->lpcSize = mode->lpcSize;
st->min_pitch=mode->pitchStart;
st->max_pitch=mode->pitchEnd;
st->submodes=mode->submodes;
st->submodeID=mode->defaultSubmode;
st->lpc_enh_enabled=0;
st->inBuf = speex_alloc((st->frameSize)*sizeof(spx_sig_t));
st->frame = st->inBuf;
st->excBuf = speex_alloc((st->frameSize + st->max_pitch + 1)*sizeof(spx_sig_t));
st->exc = st->excBuf + st->max_pitch + 1;
for (i=0;i<st->frameSize;i++)
st->inBuf[i]=0;
for (i=0;i<st->frameSize + st->max_pitch + 1;i++)
st->excBuf[i]=0;
st->innov = speex_alloc((st->frameSize)*sizeof(spx_sig_t));
st->interp_qlpc = speex_alloc(st->lpcSize*sizeof(spx_coef_t));
st->qlsp = speex_alloc(st->lpcSize*sizeof(spx_lsp_t));
st->old_qlsp = speex_alloc(st->lpcSize*sizeof(spx_lsp_t));
st->interp_qlsp = speex_alloc(st->lpcSize*sizeof(spx_lsp_t));
st->mem_sp = speex_alloc((5*st->lpcSize)*sizeof(spx_mem_t));
st->comb_mem = speex_alloc(sizeof(CombFilterMem));
comb_filter_mem_init (st->comb_mem);
st->pi_gain = speex_alloc((st->nbSubframes)*sizeof(spx_word32_t));
st->last_pitch = 40;
st->count_lost=0;
st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0;
st->pitch_gain_buf_idx = 0;
st->seed = 1000;
st->sampling_rate=8000;
st->last_ol_gain = 0;
st->user_callback.func = &speex_default_user_handler;
st->user_callback.data = NULL;
for (i=0;i<16;i++)
st->speex_callbacks[i].func = NULL;
st->voc_m1=st->voc_m2=st->voc_mean=0;
st->voc_offset=0;
st->dtx_enabled=0;
#ifdef ENABLE_VALGRIND
VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
#endif
return st;
}
void nb_decoder_destroy(void *state)
{
DecState *st;
st=(DecState*)state;
#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA))
speex_free_scratch(st->stack);
#endif
speex_free (st->inBuf);
speex_free (st->excBuf);
speex_free (st->innov);
speex_free (st->interp_qlpc);
speex_free (st->qlsp);
speex_free (st->old_qlsp);
speex_free (st->interp_qlsp);
speex_free (st->mem_sp);
speex_free (st->comb_mem);
speex_free (st->pi_gain);
speex_free(state);
}
#define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a))))
#ifdef FIXED_POINT
const spx_word16_t attenuation[10] = {32767, 31483, 27923, 22861, 17278, 12055, 7764, 4616, 2533, 1283};
#else
const spx_word16_t attenuation[10] = {1., 0.961, 0.852, 0.698, 0.527, 0.368, 0.237, 0.141, 0.077, 0.039};
#endif
static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack)
{
int i, sub;
VARDECL(spx_coef_t *awk1);
VARDECL(spx_coef_t *awk2);
VARDECL(spx_coef_t *awk3);
spx_word16_t pitch_gain;
spx_word16_t fact;
spx_word16_t gain_med;
spx_word16_t innov_gain;
if (st->count_lost<10)
fact = attenuation[st->count_lost];
else
fact = 0;
gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]);
if (gain_med < st->last_pitch_gain)
st->last_pitch_gain = gain_med;
#ifdef FIXED_POINT
pitch_gain = st->last_pitch_gain;
if (pitch_gain>62)
pitch_gain = 62;
pitch_gain = SHL(pitch_gain, 9);
#else
pitch_gain = GAIN_SCALING_1*st->last_pitch_gain;
if (pitch_gain>.95)
pitch_gain=.95;
#endif
pitch_gain = MULT16_16_Q15(fact,pitch_gain) + VERY_SMALL;
/* Shift all buffers by one frame */
/*speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));*/
speex_move(st->excBuf, st->excBuf+st->frameSize, (st->max_pitch + 1)*sizeof(spx_sig_t));
ALLOC(awk1, (st->lpcSize+1), spx_coef_t);
ALLOC(awk2, (st->lpcSize+1), spx_coef_t);
ALLOC(awk3, (st->lpcSize+1), spx_coef_t);
for (sub=0;sub<st->nbSubframes;sub++)
{
int offset;
spx_sig_t *sp, *exc;
/* Offset relative to start of frame */
offset = st->subframeSize*sub;
/* Original signal */
sp=st->frame+offset;
/* Excitation */
exc=st->exc+offset;
/* Excitation after post-filter*/
/* Calculate perceptually enhanced LPC filter */
if (st->lpc_enh_enabled)
{
spx_word16_t k1,k2,k3;
if (st->submodes[st->submodeID] != NULL)
{
k1=SUBMODE(lpc_enh_k1);
k2=SUBMODE(lpc_enh_k2);
k3=SUBMODE(lpc_enh_k3);
} else {
k1=k2=.7*GAMMA_SCALING;
k3=.0;
}
bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize);
bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize);
bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize);
}
/* Make up a plausible excitation */
/* FIXME: THIS CAN BE IMPROVED */
/*if (pitch_gain>.95)
pitch_gain=.95;*/
innov_gain = compute_rms(st->innov, st->frameSize);
for (i=0;i<st->subframeSize;i++)
{
exc[i]= MULT16_32_Q15(pitch_gain, (exc[i-st->last_pitch]+VERY_SMALL)) +
MULT16_32_Q15(fact, MULT16_32_Q15(sqrt(SHL(Q15ONE,15)-SHL(pitch_gain,15)),speex_rand(innov_gain, &st->seed)));
}
for (i=0;i<st->subframeSize;i++)
sp[i]=exc[i];
/* Signal synthesis */
if (st->lpc_enh_enabled)
{
filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize,
st->mem_sp+st->lpcSize);
filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize,
st->mem_sp);
} else {
for (i=0;i<st->lpcSize;i++)
st->mem_sp[st->lpcSize+i] = 0;
iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize,
st->mem_sp);
}
}
for (i=0;i<st->frameSize;i++)
{
spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
if (sig>32767)
sig = 32767;
if (sig<-32767)
sig = -32767;
out[i]=sig;
}
st->first = 0;
st->count_lost++;
st->pitch_gain_buf[st->pitch_gain_buf_idx++] = PSHR(pitch_gain,9);
if (st->pitch_gain_buf_idx > 2) /* rollover */
st->pitch_gain_buf_idx = 0;
}
int nb_decode(void *state, SpeexBits *bits, void *vout)
{
DecState *st;
int i, sub;
int pitch;
spx_word16_t pitch_gain[3];
spx_word32_t ol_gain=0;
int ol_pitch=0;
spx_word16_t ol_pitch_coef=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -