📄 nb_celp.c
字号:
st->mem_sp = PUSH(st->stack, 5*st->lpcSize, float);
st->comb_mem = PUSHS(st->stack, CombFilterMem);
comp_filter_mem_init (st->comb_mem);
st->pi_gain = PUSH(st->stack, st->nbSubframes, float);
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->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;
return st;
}
void nb_decoder_destroy(void *state)
{
DecState *st;
st=(DecState*)state;
speex_free(state);
}
#define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a))))
static void nb_decode_lost(DecState *st, float *out, char *stack)
{
int i, sub;
float *awk1, *awk2, *awk3;
float pitch_gain, fact, gain_med;
fact = exp(-.04*st->count_lost*st->count_lost);
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;
pitch_gain = st->last_pitch_gain;
if (pitch_gain>.95)
pitch_gain=.95;
pitch_gain *= fact;
/* Shift all buffers by one frame */
speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
awk1=PUSH(stack, (st->lpcSize+1), float);
awk2=PUSH(stack, (st->lpcSize+1), float);
awk3=PUSH(stack, (st->lpcSize+1), float);
for (sub=0;sub<st->nbSubframes;sub++)
{
int offset;
float *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)
{
float r=.9;
float k1,k2,k3;
if (st->submodes[st->submodeID] != NULL)
{
k1=SUBMODE(lpc_enh_k1);
k2=SUBMODE(lpc_enh_k2);
} else {
k1=k2=.7;
}
k3=(1-(1-r*k1)/(1-r*k2))/r;
if (!st->lpc_enh_enabled)
{
k1=k2;
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 */
/* THIS CAN BE IMPROVED */
/*if (pitch_gain>.95)
pitch_gain=.95;*/
{
float innov_gain=0;
for (i=0;i<st->frameSize;i++)
innov_gain += st->innov[i]*st->innov[i];
innov_gain=sqrt(innov_gain/st->frameSize);
for (i=0;i<st->subframeSize;i++)
{
#if 0
exc[i] = pitch_gain * exc[i - st->last_pitch] + fact*sqrt(1-pitch_gain)*st->innov[i+offset];
/*Just so it give the same lost packets as with if 0*/
/*rand();*/
#else
/*exc[i]=pitch_gain*exc[i-st->last_pitch] + fact*st->innov[i+offset];*/
exc[i]=pitch_gain*exc[i-st->last_pitch] +
fact*sqrt(1-pitch_gain)*speex_rand(innov_gain);
#endif
}
}
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);
}
}
out[0] = st->frame[0] + st->preemph*st->pre_mem;
for (i=1;i<st->frameSize;i++)
out[i]=st->frame[i] + st->preemph*out[i-1];
st->pre_mem=out[st->frameSize-1];
st->first = 0;
st->count_lost++;
st->pitch_gain_buf[st->pitch_gain_buf_idx++] = pitch_gain;
if (st->pitch_gain_buf_idx > 2) /* rollover */
st->pitch_gain_buf_idx = 0;
}
int nb_decode(void *state, SpeexBits *bits, float *out)
{
DecState *st;
int i, sub;
int pitch;
float pitch_gain[3];
float ol_gain=0;
int ol_pitch=0;
float ol_pitch_coef=0;
int best_pitch=40;
float best_pitch_gain=0;
int wideband;
int m;
char *stack;
float *awk1, *awk2, *awk3;
float pitch_average=0;
st=(DecState*)state;
stack=st->stack;
/* Check if we're in DTX mode*/
if (!bits && st->dtx_enabled)
{
st->submodeID=0;
} else
{
/* If bits is NULL, consider the packet to be lost (what could we do anyway) */
if (!bits)
{
nb_decode_lost(st, out, stack);
return 0;
}
/* Search for next narrowband block (handle requests, skip wideband blocks) */
do {
wideband = speex_bits_unpack_unsigned(bits, 1);
if (wideband) /* Skip wideband block (for compatibility) */
{
int submode;
int advance;
advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
if (advance < 0)
{
speex_warning ("Invalid wideband mode encountered. Corrupted stream?");
return -2;
}
advance -= (SB_SUBMODE_BITS+1);
speex_bits_advance(bits, advance);
wideband = speex_bits_unpack_unsigned(bits, 1);
if (wideband)
{
advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
if (advance < 0)
{
speex_warning ("Invalid wideband mode encountered: corrupted stream?");
return -2;
}
advance -= (SB_SUBMODE_BITS+1);
speex_bits_advance(bits, advance);
wideband = speex_bits_unpack_unsigned(bits, 1);
if (wideband)
{
speex_warning ("More than to wideband layers found: corrupted stream?");
return -2;
}
}
}
/* FIXME: Check for overflow */
m = speex_bits_unpack_unsigned(bits, 4);
if (m==15) /* We found a terminator */
{
return -1;
} else if (m==14) /* Speex in-band request */
{
int ret = speex_inband_handler(bits, st->speex_callbacks, state);
if (ret)
return ret;
} else if (m==13) /* User in-band request */
{
int ret = st->user_callback.func(bits, state, st->user_callback.data);
if (ret)
return ret;
} else if (m>8) /* Invalid mode */
{
speex_warning("Invalid mode encountered: corrupted stream?");
return -2;
}
} while (m>8);
/* Get the sub-mode that was used */
st->submodeID = m;
}
/* Shift all buffers by one frame */
speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
/* If null mode (no transmission), just set a couple things to zero*/
if (st->submodes[st->submodeID] == NULL)
{
float *lpc;
lpc = PUSH(stack,11, float);
bw_lpc(.93, st->interp_qlpc, lpc, 10);
/*for (i=0;i<st->frameSize;i++)
st->exc[i]=0;*/
{
float innov_gain=0;
float pgain=st->last_pitch_gain;
if (pgain>.6)
pgain=.6;
for (i=0;i<st->frameSize;i++)
innov_gain += st->innov[i]*st->innov[i];
innov_gain=sqrt(innov_gain/st->frameSize);
for (i=0;i<st->frameSize;i++)
st->exc[i]=0;
speex_rand_vec(innov_gain, st->exc, st->frameSize);
}
st->first=1;
/* Final signal synthesis from excitation */
iir_mem2(st->exc, lpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp);
out[0] = st->frame[0] + st->preemph*st->pre_mem;
for (i=1;i<st->frameSize;i++)
out[i]=st->frame[i] + st->preemph*out[i-1];
st->pre_mem=out[st->frameSize-1];
st->count_lost=0;
return 0;
}
/* Unquantize LSPs */
SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits);
/*Damp memory if a frame was lost and the LSP changed too much*/
if (st->count_lost)
{
float lsp_dist=0, fact;
for (i=0;i<st->lpcSize;i++)
lsp_dist += fabs(st->old_qlsp[i] - st->qlsp[i]);
fact = .6*exp(-.2*lsp_dist);
for (i=0;i<2*st->lpcSize;i++)
st->mem_sp[i] *= fact;
}
/* Handle first frame and lost-packet case */
if (st->first || st->count_lost)
{
for (i=0;i<st->lpcSize;i++)
st->old_qlsp[i] = st->qlsp[i];
}
/* Get open-loop pitch estimation for low bit-rate pitch coding */
if (SUBMODE(lbr_pitch)!=-1)
{
ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
}
if (SUBMODE(forced_pitch_gain))
{
int quant;
quant = speex_bits_unpack_unsigned(bits, 4);
ol_pitch_coef=0.066667*quant;
}
/* Get global excitation gain */
{
int qe;
qe = speex_bits_unpack_unsigned(bits, 5);
ol_gain = exp(qe/3.5);
}
awk1=PUSH(stack, st->lpcSize+1, float);
awk2=PUSH(stack, st->lpcSize+1, float);
awk3=PUSH(stack, st->lpcSize+1, float);
if (st->submodeID==1)
{
int extra;
extra = speex_bits_unpack_unsigned(bits, 4);
if (extra==15)
st->dtx_enabled=1;
else
st->dtx_enabled=0;
}
if (st->submodeID>1)
st->dtx_enabled=0;
/*Loop on subframes */
for (sub=0;sub<st->nbSubframes;sub++)
{
int offset;
float *sp, *exc, tmp;
/* 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*/
/* LSP interpolation (quantized and unquantized) */
tmp = (1.0 + sub)/st->nbSubframes;
for (i=0;i<st->lpcSize;i++)
st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i];
/* Make sure the LSP's are stable */
lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002);
/* Compute interpolated LPCs (unquantized) */
for (i=0;i<st->lpcSize;i++)
st->interp_qlsp[i] = cos(st->interp_qlsp[i]);
lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
/* Compute enhanced synthesis filter */
if (st->lpc_enh_enabled)
{
float r=.9;
float k1,k2,k3;
k1=SUBMODE(lpc_enh_k1);
k2=SUBMODE(lpc_enh_k2);
k3=(1-(1-r*k1)/(1-r*k2))/r;
if (!st->lpc_enh_enabled)
{
k1=k2;
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);
}
/* Compute analysis filter at w=pi */
tmp=1;
st->pi_gain[sub]=0;
for (i=0;i<=st->lpcSize;i++)
{
st->pi_gain[sub] += tmp*st->interp_qlpc[i];
tmp = -tmp;
}
/* Reset excitation */
for (i=0;i<st->subframeSize;i++)
exc[i]=0;
/*Adaptive codebook contribution*/
if (SUBMODE(ltp_unquant))
{
int pit_min, pit_max;
/* Handle pitch constraints if any */
if (SUBMODE(lbr_pitch) != -1)
{
int margin;
margin = SUBMODE(lbr_pitch);
if (margin)
{
/* GT - need optimization?
if (ol_pitch < st->min_pitch+margin-1)
ol_pitch=st->min_pitch+margin-1;
if (ol_pitch > st->max_pitch-margin)
ol_pitch=st->max_pitch-margin;
pit_min = ol_pitch-margin+1;
pit_max = ol_pitch+margin;
*/
pit_min = ol_pitch-margin+1;
if (pit_min < st->min_pitch)
pit_min = st->min_pitch;
pit_max = ol_pitch+margin;
if (pit_max > st->max_pitch)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -