decode.c
来自「高通的cmda语音压缩算法is96a源代码. 针对自己的dsp将最耗时的c改成汇」· C语言 代码 · 共 293 行
C
293 行
/**********************************************************************/
/* QCELP Variable Rate Speech Codec - Simulation of TIA IS96-A, service */
/* option one for TIA IS95, North American Wideband CDMA Digital */
/* Cellular Telephony. */
/* */
/* (C) Copyright 1993, QUALCOMM Incorporated */
/* QUALCOMM Incorporated */
/* 10555 Sorrento Valley Road */
/* San Diego, CA 92121 */
/* */
/* Note: Reproduction and use of this software for the design and */
/* development of North American Wideband CDMA Digital */
/* Cellular Telephony Standards is authorized by */
/* QUALCOMM Incorporated. QUALCOMM Incorporated does not */
/* authorize the use of this software for any other purpose. */
/* */
/* The availability of this software does not provide any license */
/* by implication, estoppel, or otherwise under any patent rights */
/* of QUALCOMM Incorporated or others covering any use of the */
/* contents herein. */
/* */
/* Any copies of this software or derivative works must include */
/* this and all other proprietary notices. */
/**********************************************************************/
/* decode.c - main QCELP decoder */
#include"math.h"
#include"struct.h"
decoder(out_speech, packet, control, d_mem)
float *out_speech;
struct PACKET *packet;
struct CONTROL *control;
struct DECODER_MEM *d_mem;
{
INTTYPE i,j;
INTTYPE rate;
INTTYPE cbsf_number;
float qlsp[LPCORDER];
float lpc[MAX_PITCH_SF][2][LPCORDER];
float bright[MAX_PITCH_SF];
float out_nopf[FSIZE];
float last_G;
struct PITCHPARAMS pitch_params;
struct CBPARAMS cb_params;
unpack_frame(packet, &(d_mem->err_cnt), d_mem->last_b, d_mem->last_lag);
rate=packet->rate;
if (rate==BLANK) {
cb_params.G=0;
cb_params.i=0; /* arbitrary */
pitch_params.b =d_mem->last_b;
if (pitch_params.b>1.0) {
pitch_params.b=1.0;
}
pitch_params.lag=d_mem->last_lag;
bright[0]=0;
for (i=0; i<LPCORDER; i++) {
qlsp[i]=d_mem->last_qlsp[i];
bright[0]+=qlsp[i];
}
bright[0]/=(float)(LPCORDER);
if (bright[0]<0.24) {
bright[0]= 0.25;
}
else if (bright[0]>0.26) {
bright[0]= -0.25;
}
else {
bright[0]= -25.0*(bright[0]-0.25);
}
lsp2lpc(qlsp, lpc[0][NOT_WGHTED], LPCORDER);
run_decoder(rate, d_mem, lpc[0], &pitch_params, &cb_params,
out_nopf, out_speech, bright[0], FSIZE, control);
}
else if (rate==ERASURE) {
cb_params.qcode_G= 0.7*d_mem->G_pred[0];
d_mem->G_pred[1]=d_mem->G_pred[0];
d_mem->G_pred[0]=cb_params.qcode_G;
cb_params.G=GA[cb_params.qcode_G +6];
d_mem->seed=((521*(d_mem->seed)+259)&0xffff);
cb_params.i=((d_mem->seed)&0x007f);
pitch_params.b =d_mem->last_b;
if (pitch_params.b>ERASE_B_SAT[d_mem->err_cnt]) {
pitch_params.b=ERASE_B_SAT[d_mem->err_cnt];
}
pitch_params.lag=d_mem->last_lag;
for (i=0; i<LPCORDER; i++) {
d_mem->lsp_pred[i]*= .90625;
qlsp[i]= d_mem->lsp_pred[i]+0.5*(float)(i+1)/(float)(LPCORDER+1);
}
check_lsp_stab(qlsp);
bright[0]=0;
for (i=0; i<LPCORDER; i++) {
qlsp[i]=.875*d_mem->last_qlsp[i]+.125*qlsp[i];
bright[0]+=qlsp[i];
}
bright[0]/=(float)(LPCORDER);
if (bright[0]<0.24) {
bright[0]= 0.25;
}
else if (bright[0]>0.26) {
bright[0]= -0.25;
}
else {
bright[0]= -25.0*(bright[0]-0.25);
}
lsp2lpc(qlsp, lpc[0][NOT_WGHTED], LPCORDER);
run_decoder(rate, d_mem, lpc[0], &pitch_params, &cb_params,
out_nopf, out_speech, bright[0], FSIZE, control);
}
else if (rate==EIGHTH) {
unquantize_lsp(rate, qlsp, d_mem->lsp_pred, packet->lsp);
interp_lpcs(rate, d_mem->last_qlsp, qlsp, lpc, &(d_mem->low_rate_cnt),
bright);
unpack_cb(rate, packet, &cb_params, 0);
unquantize_G(rate, &(cb_params.G), &(cb_params.qcode_G),
&(cb_params.qcode_Gsign), d_mem->G_pred);
update_Gpred(rate, cb_params.qcode_G, d_mem->G_pred);
last_G = 0.5*(cb_params.G+d_mem->last_G);
cb_params.seed=packet->data[1];
pitch_params.b=0.0;
pitch_params.lag=0;
for (j=0; j<8; j++) {
cb_params.G= d_mem->last_G*(7-j)/8.0 +last_G*(j+1)/8.0;
run_decoder(rate, d_mem, lpc[0], &pitch_params, &cb_params,
&out_nopf[j*FSIZE/8], &out_speech[j*FSIZE/8],
bright[0], FSIZE/8, control);
}
}
else { /* Full, Half, or Quarter rates here */
unquantize_lsp(rate, qlsp, d_mem->lsp_pred, packet->lsp);
interp_lpcs(rate, d_mem->last_qlsp, qlsp, lpc, &(d_mem->low_rate_cnt),
bright);
for (i=0; i<PITCHSF[rate]; i++) {
unquantize_b_and_lag(rate, &(pitch_params.lag), &(packet->lag[i]),
&(pitch_params.b), &(packet->b[i]));
for (j=0; j<CBSF[rate]/PITCHSF[rate]; j++) {
cbsf_number=i*CBSF[rate]/PITCHSF[rate]+j;
unpack_cb(rate, packet, &cb_params, cbsf_number);
unquantize_G(rate, &(cb_params.G), &(cb_params.qcode_G),
&(cb_params.qcode_Gsign), d_mem->G_pred);
update_Gpred(rate, cb_params.qcode_G, d_mem->G_pred);
unquantize_i(rate, &(cb_params.i), &(cb_params.qcode_i));
run_decoder(rate, d_mem, lpc[i], &pitch_params, &cb_params,
&out_nopf[cbsf_number*FSIZE/CBSF[rate]],
&out_speech[cbsf_number*FSIZE/CBSF[rate]],
bright[i], FSIZE/CBSF[rate], control);
}
}
}
for (i=0; i<4; i++) {
agc(&out_nopf[i*FSIZE/4], &out_speech[i*FSIZE/4],
&out_speech[i*FSIZE/4], FSIZE/4, &(d_mem->agc_factor));
}
/* Update parameters for next frame */
for (i=0; i<LPCORDER; i++) {
d_mem->last_qlsp[i]=qlsp[i];
}
d_mem->last_b =pitch_params.b;
d_mem->last_lag=pitch_params.lag;
d_mem->last_G= (float)fabs((double)(cb_params.G));
}
run_decoder(rate, d_mem, lpc, pitch_params, cb_params, buffer, out_buffer,
bright, length, control)
INTTYPE rate;
struct DECODER_MEM *d_mem;
float lpc[2][LPCORDER];
struct PITCHPARAMS *pitch_params;
struct CBPARAMS *cb_params;
float *buffer;
float *out_buffer;
float bright;
INTTYPE length;
struct CONTROL *control;
{
INTTYPE j;
float zero_wght_factor, pole_wght_factor;
float cb_out[FSIZE], pitch_out[FSIZE], pf_out[FSIZE], null_out[FSIZE];
if (rate==EIGHTH) {
for (j=0; j<length; j++) {
cb_params->seed=(521*cb_params->seed+259)&(0xffff);
cb_out[j]=(((cb_params->seed+0x7fff)&(0xffff))-0x7fff);
cb_out[j]*=1.3736895*cb_params->G/32768.0;
}
d_mem->seed=cb_params->seed;
}
else {
for (j=0; j<length; j++) {
cb_out[j]=CODEBOOK[(CBLENGTH-cb_params->i +j)%CBLENGTH]
*cb_params->G;
}
}
d_mem->pitch_filt.coeff=pitch_params->b;
d_mem->pitch_filt.delay=pitch_params->lag;
do_pole_filter_1_tap(cb_out, pitch_out, length, &(d_mem->pitch_filt),
UPDATE);
if (d_mem->type==ENCODER) {
for (j=0; j<LPCORDER; j++) {
d_mem->lpc_filt.pole_coeff[j]=lpc[NOT_WGHTED][j];
d_mem->wghting_filt.zero_coeff[j]=-lpc[NOT_WGHTED][j];
d_mem->wghting_filt.pole_coeff[j]=lpc[WGHTED][j];
}
do_pole_filter(pitch_out, out_buffer, length,
&(d_mem->lpc_filt), UPDATE);
for (j=0; j<length; j++) {
/* buffer holds input speech in encoder case */
null_out[j]=buffer[j]-out_buffer[j];
}
do_pole_zero_filter(null_out, null_out, length,
&(d_mem->wghting_filt), UPDATE);
}
else {
for (j=0; j<LPCORDER; j++) {
d_mem->lpc_filt.pole_coeff[j]=lpc[NOT_WGHTED][j];
}
/* buffer holds no_pf output in decoder case */
do_pole_filter(pitch_out, buffer, length, &(d_mem->lpc_filt),
UPDATE);
if (control->pf_flag==PF_ON) {
zero_wght_factor=1;
pole_wght_factor=1;
for (j=0; j<LPCORDER; j++) {
zero_wght_factor*=PF_ZERO_WGHT_FACTOR;
d_mem->post_filt_z.zero_coeff[j]=
-lpc[NOT_WGHTED][j]*zero_wght_factor;
pole_wght_factor*=PF_POLE_WGHT_FACTOR;
d_mem->post_filt_p.pole_coeff[j]=
lpc[NOT_WGHTED][j]*pole_wght_factor;
}
do_zero_filter(buffer, pf_out, length,
&(d_mem->post_filt_z), UPDATE);
do_pole_filter(pf_out, pf_out, length,
&(d_mem->post_filt_p), UPDATE);
d_mem->bright_filt.pole_coeff[0]= -bright;
d_mem->bright_filt.zero_coeff[0]= -bright;
do_pole_zero_filter(pf_out, out_buffer, length,
&(d_mem->bright_filt), UPDATE);
}
else {
for (j=0; j<length; j++) {
out_buffer[j]=buffer[j];
}
}
}
}
agc(input, output, return_vals, length, factor)
float *input, *output, *return_vals;
INTTYPE length;
float *factor;
{
INTTYPE i;
float input_energy, output_energy;
float norm;
input_energy=0;
output_energy=0;
for (i=0; i<length; i++) {
input_energy+=input[i]*input[i];
output_energy+=output[i]*output[i];
}
if (output_energy>.1) {
norm=sqrt((double)(input_energy/output_energy));
}
else {
norm= *factor;
}
*factor=AGC_FACTOR*(*factor)+(1-AGC_FACTOR)*norm;
for (i=0; i<length; i++) {
return_vals[i]=output[i]*(*factor);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?