📄 sb_celp.c
字号:
mode = (const SpeexSBMode*)(st->mode->mode);
{
VARDECL(spx_word16_t *low);
ALLOC(low, st->frame_size, spx_word16_t);
/* Compute the two sub-bands by filtering with h0 and h1*/
qmf_decomp(in, h0, st->x0d, st->x1d, st->full_frame_size, QMF_ORDER, st->h0_mem, stack);
for (i=0;i<st->frame_size;i++)
low[i] = SATURATE(PSHR(st->x0d[i],SIG_SHIFT),32767);
/* Encode the narrowband part*/
speex_encode_native(st->st_low, low, bits);
for (i=0;i<st->frame_size;i++)
st->x0d[i] = SHL(low[i],SIG_SHIFT);
}
/* High-band buffering / sync with low band */
for (i=0;i<st->windowSize-st->frame_size;i++)
st->high[i] = st->high[st->frame_size+i];
for (i=0;i<st->frame_size;i++)
st->high[st->windowSize-st->frame_size+i]=SATURATE(st->x1d[i],536854528);
speex_move(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(spx_sig_t));
ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t);
ALLOC(low_exc, st->frame_size, spx_sig_t);
ALLOC(low_innov, st->frame_size, spx_sig_t);
speex_encoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain);
speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc);
speex_encoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov);
speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, &dtx);
if (dtx==0)
dtx=1;
else
dtx=0;
{
VARDECL(spx_word16_t *w_sig);
ALLOC(w_sig, st->windowSize, spx_word16_t);
/* Window for analysis */
for (i=0;i<st->windowSize;i++)
w_sig[i] = SHR(MULT16_16(SHR((spx_word32_t)(st->high[i]),SIG_SHIFT),st->window[i]),SIG_SHIFT);
/* Compute auto-correlation */
_spx_autocorr(w_sig, st->autocorr, st->lpcSize+1, st->windowSize);
}
st->autocorr[0] = (spx_word16_t)(st->autocorr[0]*st->lpc_floor); /* Noise floor in auto-correlation domain */
/* Lag windowing: equivalent to filtering in the power-spectrum domain */
for (i=0;i<st->lpcSize+1;i++)
st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]);
/* Levinson-Durbin */
_spx_lpc(st->lpc, st->autocorr, st->lpcSize);
/* LPC to LSPs (x-domain) transform */
roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, LSP_DELTA1, stack);
if (roots!=st->lpcSize)
{
roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, LSP_DELTA2, stack);
if (roots!=st->lpcSize) {
/*If we can't find all LSP's, do some damage control and use a flat filter*/
for (i=0;i<st->lpcSize;i++)
{
st->lsp[i]=M_PI*((float)(i+1))/(st->lpcSize+1);
}
}
}
/* VBR code */
if ((st->vbr_enabled || st->vad_enabled) && !dtx)
{
float e_low=0, e_high=0;
float ratio;
if (st->abr_enabled)
{
float qual_change=0;
if (st->abr_drift2 * st->abr_drift > 0)
{
/* Only adapt if long-term and short-term drift are the same sign */
qual_change = -.00001*st->abr_drift/(1+st->abr_count);
if (qual_change>.1)
qual_change=.1;
if (qual_change<-.1)
qual_change=-.1;
}
st->vbr_quality += qual_change;
if (st->vbr_quality>10)
st->vbr_quality=10;
if (st->vbr_quality<0)
st->vbr_quality=0;
}
/*FIXME: Are the two signals (low, high) in sync? */
e_low = compute_rms(st->x0d, st->frame_size);
e_high = compute_rms(st->high, st->frame_size);
ratio = 2*log((1+e_high)/(1+e_low));
speex_encoder_ctl(st->st_low, SPEEX_GET_RELATIVE_QUALITY, &st->relative_quality);
if (ratio<-4)
ratio=-4;
if (ratio>2)
ratio=2;
/*if (ratio>-2)*/
if (st->vbr_enabled)
{
int modeid;
modeid = mode->nb_modes-1;
st->relative_quality+=1.0*(ratio+2);
if (st->relative_quality<-1)
st->relative_quality=-1;
while (modeid)
{
int v1;
float thresh;
v1=(int)floor(st->vbr_quality);
if (v1==10)
thresh = mode->vbr_thresh[modeid][v1];
else
thresh = (st->vbr_quality-v1) * mode->vbr_thresh[modeid][v1+1] +
(1+v1-st->vbr_quality) * mode->vbr_thresh[modeid][v1];
if (st->relative_quality >= thresh)
break;
modeid--;
}
speex_encoder_ctl(state, SPEEX_SET_HIGH_MODE, &modeid);
if (st->abr_enabled)
{
int bitrate;
speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate);
st->abr_drift+=(bitrate-st->abr_enabled);
st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled);
st->abr_count += 1.0;
}
} else {
/* VAD only */
int modeid;
if (st->relative_quality<2.0)
modeid=1;
else
modeid=st->submodeSelect;
/*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
st->submodeID=modeid;
}
/*fprintf (stderr, "%f %f\n", ratio, low_qual);*/
}
if (st->encode_submode)
{
speex_bits_pack(bits, 1, 1);
if (dtx)
speex_bits_pack(bits, 0, SB_SUBMODE_BITS);
else
speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS);
}
/* If null mode (no transmission), just set a couple things to zero*/
if (dtx || st->submodes[st->submodeID] == NULL)
{
for (i=0;i<st->frame_size;i++)
st->exc[i]=st->sw[i]=VERY_SMALL;
for (i=0;i<st->lpcSize;i++)
st->mem_sw[i]=0;
st->first=1;
/* Final signal synthesis from excitation */
iir_mem2(st->exc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp);
#ifdef RESYNTH
/* Reconstruct the original */
fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
for (i=0;i<st->full_frame_size;i++)
in[i]=SHR(st->y0[i]-st->y1[i], SIG_SHIFT-1);
#endif
if (dtx)
return 0;
else
return 1;
}
/* LSP quantization */
SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);
if (st->first)
{
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];
}
ALLOC(mem, st->lpcSize, spx_mem_t);
ALLOC(syn_resp, st->subframeSize, spx_word16_t);
ALLOC(innov, st->subframeSize, spx_sig_t);
for (sub=0;sub<st->nbSubframes;sub++)
{
spx_sig_t *exc, *sp, *res, *target, *sw;
spx_word16_t filter_ratio;
int offset;
spx_word32_t rl, rh;
spx_word16_t eh=0;
offset = st->subframeSize*sub;
sp=st->high+offset;
exc=st->exc+offset;
res=st->res+offset;
target=st->target+offset;
sw=st->sw+offset;
/* LSP interpolation (quantized and unquantized) */
lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, sub, st->nbSubframes);
lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes);
lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);
lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);
lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
/* Compute mid-band (4000 Hz for wideband) response of low-band and high-band
filters */
st->pi_gain[sub]=LPC_SCALING;
rh = LPC_SCALING;
for (i=0;i<st->lpcSize;i+=2)
{
rh += st->interp_qlpc[i+1] - st->interp_qlpc[i];
st->pi_gain[sub] += st->interp_qlpc[i] + st->interp_qlpc[i+1];
}
rl = low_pi_gain[sub];
#ifdef FIXED_POINT
filter_ratio=DIV32_16(SHL(rl+82,2),SHR(82+rh,5));
#else
filter_ratio=(rl+.01)/(rh+.01);
#endif
/* Compute "real excitation" */
fir_mem2(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2);
/* Compute energy of low-band and high-band excitation */
eh = compute_rms(exc, st->subframeSize);
if (!SUBMODE(innovation_quant)) {/* 1 for spectral folding excitation, 0 for stochastic */
float g;
spx_word16_t el;
el = compute_rms(low_innov+offset, st->subframeSize);
/* Gain to use if we want to use the low-band excitation for high-band */
g=eh/(.01+el);
#if 0
{
char *tmp_stack=stack;
float *tmp_sig;
float g2;
ALLOC(tmp_sig, st->subframeSize, spx_sig_t);
for (i=0;i<st->lpcSize;i++)
mem[i]=st->mem_sp[i];
iir_mem2(low_innov+offset, st->interp_qlpc, tmp_sig, st->subframeSize, st->lpcSize, mem);
g2 = compute_rms(sp, st->subframeSize)/(.01+compute_rms(tmp_sig, st->subframeSize));
/*fprintf (stderr, "gains: %f %f\n", g, g2);*/
g = g2;
stack = tmp_stack;
}
#endif
#ifdef FIXED_POINT
g *= filter_ratio/128.;
#else
g *= filter_ratio;
#endif
/*print_vec(&g, 1, "gain factor");*/
/* Gain quantization */
{
int quant = (int) floor(.5 + 10 + 8.0 * log((g+.0001)));
/*speex_warning_int("tata", quant);*/
if (quant<0)
quant=0;
if (quant>31)
quant=31;
speex_bits_pack(bits, quant, 5);
}
} else {
spx_word16_t gc;
spx_word32_t scale;
spx_word16_t el;
el = compute_rms(low_exc+offset, st->subframeSize);
gc = DIV32_16(MULT16_16(filter_ratio,1+eh),1+el);
/* This is a kludge that cleans up a historical bug */
if (st->subframeSize==80)
gc *= 0.70711;
/*printf ("%f %f %f %f\n", el, eh, filter_ratio, gc);*/
#ifdef FIXED_POINT
{
int qgc = scal_quant(gc, gc_quant_bound, 16);
speex_bits_pack(bits, qgc, 4);
gc = MULT16_32_Q15(28626,gc_quant_bound[qgc]);
}
#else
{
int qgc = (int)floor(.5+3.7*(log(gc)+0.15556));
if (qgc<0)
qgc=0;
if (qgc>15)
qgc=15;
speex_bits_pack(bits, qgc, 4);
gc = exp((1/3.7)*qgc-0.15556);
}
#endif
if (st->subframeSize==80)
gc *= 1.4142;
scale = SHL(MULT16_16(DIV32_16(SHL(gc,SIG_SHIFT-4),filter_ratio),(1+el)),4);
compute_impulse_response(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]=VERY_SMALL;
/* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(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]=0;
signal_div(target, target, scale, st->subframeSize);
/* Reset excitation */
for (i=0;i<st->subframeSize;i++)
innov[i]=0;
/*print_vec(target, st->subframeSize, "\ntarget");*/
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+1)>>1, SUBMODE(double_codebook));
/*print_vec(target, st->subframeSize, "after");*/
signal_mul(innov, innov, scale, st->subframeSize);
for (i=0;i<st->subframeSize;i++)
exc[i] = ADD32(exc[i], innov[i]);
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.5;
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+1)>>1, 0);
for (i=0;i<st->subframeSize;i++)
innov2[i]*=scale*(1/2.5)/SIG_SCALING;
for (i=0;i<st->subframeSize;i++)
exc[i] = ADD32(exc[i],innov2[i]);
stack = tmp_stack;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -