📄 nb_celp.c
字号:
/* First, transmit a zero for narrowband */
speex_bits_pack(bits, 0, 1);
/* Transmit the sub-mode we use for this frame */
speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS);
/* If null mode (no transmission), just set a couple things to zero*/
if (st->submodes[st->submodeID] == NULL)
{
for (i=0;i<st->frameSize;i++)
st->exc[i]=st->exc2[i]=st->sw[i]=0;
for (i=0;i<st->lpcSize;i++)
st->mem_sw[i]=0;
st->first=1;
st->bounded_pitch = 1;
/* Final signal synthesis from excitation */
iir_mem2(st->exc, st->interp_qlpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp);
in[0] = st->frame[0] + st->preemph*st->pre_mem2;
for (i=1;i<st->frameSize;i++)
in[i]=st->frame[i] + st->preemph*in[i-1];
st->pre_mem2=in[st->frameSize-1];
return 0;
}
/* LSP Quantization */
if (st->first)
{
for (i=0;i<st->lpcSize;i++)
st->old_lsp[i] = st->lsp[i];
}
/*Quantize LSPs*/
#if 1 /*0 for unquantized*/
SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);
#else
for (i=0;i<st->lpcSize;i++)
st->qlsp[i]=st->lsp[i];
#endif
/*If we use low bit-rate pitch mode, transmit open-loop pitch*/
if (SUBMODE(lbr_pitch)!=-1)
{
speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
}
if (SUBMODE(forced_pitch_gain))
{
int quant;
quant = (int)floor(.5+15*ol_pitch_coef);
if (quant>15)
quant=0;
if (quant<0)
quant=0;
speex_bits_pack(bits, quant, 4);
ol_pitch_coef=0.066667*quant;
}
/*Quantize and transmit open-loop excitation gain*/
{
int qe = (int)(floor(3.5*log(ol_gain)));
if (qe<0)
qe=0;
if (qe>31)
qe=31;
ol_gain = exp(qe/3.5);
speex_bits_pack(bits, qe, 5);
}
/* Special case for first frame */
if (st->first)
{
for (i=0;i<st->lpcSize;i++)
st->old_qlsp[i] = st->qlsp[i];
}
/* Filter response */
res = PUSH(stack, st->subframeSize, float);
/* Target signal */
target = PUSH(stack, st->subframeSize, float);
syn_resp = PUSH(stack, st->subframeSize, float);
mem = PUSH(stack, st->lpcSize, float);
orig = PUSH(stack, st->frameSize, float);
for (i=0;i<st->frameSize;i++)
orig[i]=st->frame[i];
/* Loop on sub-frames */
for (sub=0;sub<st->nbSubframes;sub++)
{
float tmp;
int offset;
float *sp, *sw, *exc, *exc2;
int pitch;
/* Offset relative to start of frame */
offset = st->subframeSize*sub;
/* Original signal */
sp=st->frame+offset;
/* Excitation */
exc=st->exc+offset;
/* Weighted signal */
sw=st->sw+offset;
exc2=st->exc2+offset;
/* LSP interpolation (quantized and unquantized) */
tmp = (1.0 + sub)/st->nbSubframes;
for (i=0;i<st->lpcSize;i++)
st->interp_lsp[i] = (1-tmp)*st->old_lsp[i] + tmp*st->lsp[i];
for (i=0;i<st->lpcSize;i++)
st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i];
/* Make sure the filters are stable */
lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002);
lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002);
/* Compute interpolated LPCs (quantized and unquantized) */
for (i=0;i<st->lpcSize;i++)
st->interp_lsp[i] = cos(st->interp_lsp[i]);
lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
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 analysis filter gain at w=pi (for use in SB-CELP) */
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;
}
/* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */
bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
if (st->gamma2>=0)
bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
else
{
st->bw_lpc2[0]=1;
st->bw_lpc2[1]=-st->preemph;
for (i=2;i<=st->lpcSize;i++)
st->bw_lpc2[i]=0;
}
/* Compute impulse response of A(z/g1) / ( A(z)*A(z/g2) )*/
for (i=0;i<st->subframeSize;i++)
exc[i]=0;
exc[0]=1;
syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack);
/* Reset excitation */
for (i=0;i<st->subframeSize;i++)
exc[i]=0;
for (i=0;i<st->subframeSize;i++)
exc2[i]=0;
/* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */
for (i=0;i<st->lpcSize;i++)
mem[i]=st->mem_sp[i];
iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem);
for (i=0;i<st->lpcSize;i++)
mem[i]=st->mem_sw[i];
filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem);
/* Compute weighted signal */
for (i=0;i<st->lpcSize;i++)
mem[i]=st->mem_sw[i];
filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem);
/* Compute target signal */
for (i=0;i<st->subframeSize;i++)
target[i]=sw[i]-res[i];
for (i=0;i<st->subframeSize;i++)
exc[i]=exc2[i]=0;
/* If we have a long-term predictor (otherwise, something's wrong) */
if (SUBMODE(ltp_quant))
{
int pit_min, pit_max;
/* Long-term prediction */
if (SUBMODE(lbr_pitch) != -1)
{
/* Low bit-rate pitch handling */
int margin;
margin = SUBMODE(lbr_pitch);
if (margin)
{
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;
} else {
pit_min=pit_max=ol_pitch;
}
} else {
pit_min = st->min_pitch;
pit_max = st->max_pitch;
}
/* Force pitch to use only the current frame if needed */
if (st->bounded_pitch && pit_max>offset)
pit_max=offset;
/* 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,
exc2, syn_resp, st->complexity);
st->pitch[sub]=pitch;
} else {
speex_error ("No pitch prediction, what's wrong");
}
/* Update target for adaptive codebook contribution */
syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, stack);
for (i=0;i<st->subframeSize;i++)
target[i]-=res[i];
/* Quantization of innovation */
{
float *innov;
float ener=0, ener_1;
innov = st->innov+sub*st->subframeSize;
for (i=0;i<st->subframeSize;i++)
innov[i]=0;
residue_percep_zero(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, st->buf2, st->subframeSize, st->lpcSize, stack);
for (i=0;i<st->subframeSize;i++)
ener+=st->buf2[i]*st->buf2[i];
ener=sqrt(.1+ener/st->subframeSize);
/*for (i=0;i<st->subframeSize;i++)
printf ("%f\n", st->buf2[i]/ener);
*/
ener /= ol_gain;
/* Calculate gain correction for the sub-frame (if any) */
if (SUBMODE(have_subframe_gain))
{
int qe;
ener=log(ener);
if (SUBMODE(have_subframe_gain)==3)
{
qe = vq_index(&ener, exc_gain_quant_scal3, 1, 8);
speex_bits_pack(bits, qe, 3);
ener=exc_gain_quant_scal3[qe];
} else {
qe = vq_index(&ener, exc_gain_quant_scal1, 1, 2);
speex_bits_pack(bits, qe, 1);
ener=exc_gain_quant_scal1[qe];
}
ener=exp(ener);
} else {
ener=1;
}
ener*=ol_gain;
/*printf ("%f %f\n", ener, ol_gain);*/
ener_1 = 1/ener;
/* Normalize innovation */
for (i=0;i<st->subframeSize;i++)
target[i]*=ener_1;
/* 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);
/* De-normalize innovation and update excitation */
for (i=0;i<st->subframeSize;i++)
innov[i]*=ener;
for (i=0;i<st->subframeSize;i++)
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;
float *innov2 = PUSH(tmp_stack, st->subframeSize, float);
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, tmp_stack, st->complexity);
for (i=0;i<st->subframeSize;i++)
innov2[i]*=ener*(1/2.2);
for (i=0;i<st->subframeSize;i++)
exc[i] += innov2[i];
}
for (i=0;i<st->subframeSize;i++)
target[i]*=ener;
}
/*Keep the previous memory*/
for (i=0;i<st->lpcSize;i++)
mem[i]=st->mem_sp[i];
/* 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) */
filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw);
for (i=0;i<st->subframeSize;i++)
exc2[i]=exc[i];
}
/* 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;
{
float ener=0, err=0;
float snr;
for (i=0;i<st->frameSize;i++)
{
ener+=st->frame[i]*st->frame[i];
err += (st->frame[i]-orig[i])*(st->frame[i]-orig[i]);
}
snr = 10*log10((ener+1)/(err+1));
/*printf ("%f %f %f\n", snr, ener, err);*/
}
/* Replace input by synthesized speech */
in[0] = st->frame[0] + st->preemph*st->pre_mem2;
for (i=1;i<st->frameSize;i++)
in[i]=st->frame[i] + st->preemph*in[i-1];
st->pre_mem2=in[st->frameSize-1];
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(SpeexMode *m)
{
DecState *st;
SpeexNBMode *mode;
int i;
mode=(SpeexNBMode*)m->mode;
st = (DecState *)speex_alloc(sizeof(DecState)+4000*sizeof(float));
st->mode=m;
st->stack = ((char*)st) + sizeof(DecState);
st->first=1;
/* Codec parameters, should eventually have several "modes"*/
st->frameSize = mode->frameSize;
st->windowSize = st->frameSize*3/2;
st->nbSubframes=mode->frameSize/mode->subframeSize;
st->subframeSize=mode->subframeSize;
st->lpcSize = mode->lpcSize;
st->bufSize = mode->bufSize;
st->gamma1=mode->gamma1;
st->gamma2=mode->gamma2;
st->min_pitch=mode->pitchStart;
st->max_pitch=mode->pitchEnd;
st->preemph = mode->preemph;
st->submodes=mode->submodes;
st->submodeID=mode->defaultSubmode;
st->pre_mem=0;
st->lpc_enh_enabled=0;
st->inBuf = PUSH(st->stack, st->bufSize, float);
st->frame = st->inBuf + st->bufSize - st->windowSize;
st->excBuf = PUSH(st->stack, st->bufSize, float);
st->exc = st->excBuf + st->bufSize - st->windowSize;
for (i=0;i<st->bufSize;i++)
st->inBuf[i]=0;
for (i=0;i<st->bufSize;i++)
st->excBuf[i]=0;
st->innov = PUSH(st->stack, st->frameSize, float);
st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, float);
st->qlsp = PUSH(st->stack, st->lpcSize, float);
st->old_qlsp = PUSH(st->stack, st->lpcSize, float);
st->interp_qlsp = PUSH(st->stack, st->lpcSize, float);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -