📄 lpc.cpp
字号:
bp7 = st->bp[7];
bp8 = st->bp[8];
bp9 = st->bp[9];
bp10 = st->bp[10];
per = (float)(in[0]);
//per = (float)(per / 2);
G = (float)in[1] / 256.f;
//k[0] = 0.0;
for (i = 0; i < LPC_FILTORDER; i++)
k[i] = (float) ((signed char)in[i + 2]) * 0.0078125f;//还原k
G /= (float)sqrt(BUFLEN / ((per < FLT_EPSILON && per > -FLT_EPSILON)? 3.0f : per));
Newper = st->Oldper;
NewG = st->OldG;
for (i = 0; i < LPC_FILTORDER; i++)
Newk[i] = st->Oldk[i];
if (st->Oldper != 0 && per != 0)//两桢都为元音,两桢采取周期递增,平滑性好
{
perinc = (per - st->Oldper) * (1.0f/LPC_SAMPLES_PER_FRAME);
Ginc = (G - st->OldG) * (1.0f/LPC_SAMPLES_PER_FRAME);
}
else//若有一桢不为元音,则不进行递增
{
perinc = 0.0f;
Ginc = 0.0f;
}
if (Newper == 0.f)//上一桢为辅音
{
st->pitchctr = 0;
st->tri=0;
st->tri_1=0;
st->tri_2=0;
}
//int tri;//三角波参数
//int tri_1;
//int tri_2;
for (i = 0; i < LPC_SAMPLES_PER_FRAME; i++)
{
if (Newper == 0.f) //假如上一桢是辅音,必有perinc = 0.0f;Ginc = 0.0f;处理上一桢
{
u = (((PNrandom() - 32768) / 32768.0f)) * 1.5874f * NewG;//随机产生激励预案,噪声
}
else //上一桢是元音
{
/* if (st->pitchctr == 0) //激励源只是一单位脉冲
{
u = NewG;
st->pitchctr = (int) Newper;
}
else
{
u = 0.0f;
st->pitchctr--;
}*/
if(st->pitchctr==0)//激励源三角波
{
st->pitchctr=(int) Newper;
st->tri=0;
st->tri_1=(int)(3*Newper)/7;
st->tri_2=(int)(6*Newper)/7;
}
if(st->tri<st->tri_1)
{
u=float(1-cos(M_PI*st->tri/st->tri_1)/2)*NewG;
st->pitchctr--;
st->tri++;
}
else
{
if(st->tri<st->tri_2)
{
u=float(cos(M_PI*(st->tri-st->tri_1)/(2*st->tri_2)))*NewG;
st->pitchctr--;
st->tri++;
}
else
{
u=0;
st->pitchctr--;
st->tri++;
}
}
//三角波部分结束
}
//下面是解压过程,极点模型s(n)=G*u+(预测部分);begin
f = u;
b = bp9;
kj = Newk[9];
f -= kj * bp9;
bp10 = bp9 + kj * f;
kj = Newk[8];
f -= kj * bp8;
bp9 = bp8 + kj * f;
kj = Newk[7];
f -= kj * bp7;
bp8 = bp7 + kj * f;
kj = Newk[6];
f -= kj * bp6;
bp7 = bp6 + kj * f;
kj = Newk[5];
f -= kj * bp5;
bp6 = bp5 + kj * f;
kj = Newk[4];
f -= kj * bp4;
bp5 = bp4 + kj * f;
kj = Newk[3];
f -= kj * bp3;
bp4 = bp3 + kj * f;
kj = Newk[2];
f -= kj * bp2;
bp3 = bp2 + kj * f;
kj = Newk[1];
f -= kj * bp1;
bp2 = bp1 + kj * f;
kj = Newk[0];
f -= kj * bp0;
bp1 = bp0 + kj * f;
bp0 = f;
u = f;
if (u < -0.9999f)
{
u = -0.9999f;
}
else if (u > 0.9999f)
{
u = 0.9999f;
}
*out++ = (short)(u * 32767.0f);
//解压过程结束 end
Newper += perinc;
NewG += Ginc;
}
st->bp[0] = bp0;
st->bp[1] = bp1;
st->bp[2] = bp2;
st->bp[3] = bp3;
st->bp[4] = bp4;
st->bp[5] = bp5;
st->bp[6] = bp6;
st->bp[7] = bp7;
st->bp[8] = bp8;
st->bp[9] = bp9;
st->bp[10] = bp10;
st->Oldper = per;
st->OldG = G;
for (i = 0; i < LPC_FILTORDER; i++)
st->Oldk[i] = k[i];
return LPC_SAMPLES_PER_FRAME;
}
void destroy_lpc_decoder_state(lpc_decoder_state *st)
{
if(st != NULL)
{
free(st);
st = NULL;
}
}
int main()
{
lpc_encoder_state *state1;
state1 = (lpc_encoder_state *)malloc(sizeof(lpc_encoder_state));
init_lpc_encoder_state(state1);
FILE *fp1_1=fopen("f:\\Test\\bianma_char.txt","w");//打开文本文件,写入压缩后的数据,文本形式
if(fp1_1==NULL)
{
cout<<"can not open the bianma_char.txt!";
exit(0);
}
FILE *fp1_2=fopen("f:\\Test\\bianma_bit.txt","wb");//打开文本文件,写入压缩后的数据.二进制形式
if(fp1_2==NULL)
{
cout<<"can not open the bianma_bit.txt!";
exit(0);
}
FILE *fp2=fopen("f:\\Test\\orignal_voice.pcm","rb"); //打开原始语音文件 ,二进制方式
if(fp2==NULL)
{
cout<<"can not open the orignalvoice.pcm!";
exit(0);
}
else
{
cout<<"//////////////////////////下面是编码......//////////////////////////////////"<<endl;
long LEN;//文件长度
long length=0;
fseek(fp2,0L,SEEK_END);
LEN=ftell(fp2);
fseek(fp2,0L,SEEK_SET);
short *in=new short[BUFLEN];
unsigned char *out=new unsigned char[12];
unsigned char temp1;
unsigned char temp2;
short temp;
for(int i=0;i<BUFLEN;i++)
{
temp=0x0000;
temp1=fgetc(fp2);//低位
temp2=fgetc(fp2);//高位
temp|=temp2;
temp=(temp<<8);
temp|=temp1;
length+=2;
in[i]=temp;
//printf("%d",in[i]);
//cout<<endl;
}
lpc_encode(in,out,state1);
for(int i=0;i<12;i++)
{
fprintf(fp1_1,"%u",out[i]);//写入文本文件
fprintf(fp1_1," ");
fwrite(&out[i],1,1,fp1_2);//写入二进制文件
}
fprintf(fp1_1,"\n");
while(1) //while
{
//cout<<"test"<<endl;
for(int i=0;i<BUFLEN/3;i++)
in[i]=in[i+LPC_SAMPLES_PER_FRAME];
for(int i=BUFLEN/3;i<BUFLEN;i++)//for
{
if(length<LEN)
{
temp1=fgetc(fp2);
length++;
}
else
break;
if(length<LEN)
{
temp2=fgetc(fp2);
length++;
}
else
break;
temp=0x0000;
temp|=temp2;
temp=(temp<<8);
temp|=temp1;
in[i]=temp;
}//for
lpc_encode(in,out,state1);
for(int i=0;i<12;i++)
{
fprintf(fp1_1,"%u",out[i]);
fprintf(fp1_1," ");
fwrite(&out[i],1,1,fp1_2);
}
fprintf(fp1_1,"\n");
if(length>=LEN)
break;
}//while
}//else
fclose(fp2);
fclose(fp1_1);
fclose(fp1_2);
FILE *fp3_1=fopen("f:\\Test\\bianma_char.txt","r");//打开编码文件,按文本读入
if(fp3_1==NULL)
{
cout<<"can not open the bianma_char.txt!";
exit(0);
}
FILE *fp3_2=fopen("f:\\Test\\bianma_bit.txt","rb");//打开编码文件,按二进制读入
if(fp3_2==NULL)
{
cout<<"can not open the bianma_bit.txt!";
exit(0);
}
lpc_decoder_state *state2;
state2 = (lpc_decoder_state *)malloc(sizeof(lpc_decoder_state));
init_lpc_decoder_state(state2);
FILE *fp4 = fopen("F:\\Test\\result_voice.pcm","wb");//输出解压后的语音
if(fp4==NULL)
{
cout<<"Can't open the result_voice file!"<<endl;
exit(0);
}
else
{
cout<<"//////////////////////////下面是解码......//////////////////////////////////"<<endl;
unsigned char *in=new unsigned char[12];
short *out=new short[LPC_SAMPLES_PER_FRAME];
unsigned char temp;
char *ch=new char[4];
unsigned char ss;
while(1)//while
{
//for(int i=0;i<12;i++)//这些是从文本里面读入压缩后的数据
//{
// int j=0;
// temp=fgetc(fp3_1);
// while((!feof(fp3_1))&&(temp!=' '))
// {
// ch[j++]=temp;
// temp=fgetc(fp3_1);
// }
// ch[j]='\0';
// //cout<<atoi(ch)<<endl;
// in[i]=(unsigned char)(atoi(ch));
//}
//while((!feof(fp3_1))&&(temp!='\n'))
// temp=fgetc(fp3_1);
//if(feof(fp3_1))
// break;
for(int i=0;i<12;i++)//按二进制读入压缩后的数据
{
fread(&in[i],1,1,fp3_2);
}
if(feof(fp3_2))
break;
lpc_decode(in,out,state2);
for(int i=0;i<LPC_SAMPLES_PER_FRAME;i++)
{
ss=((unsigned char)((unsigned short)out[i]&0x00ff));
fwrite(&ss,1,1,fp2);
ss=((unsigned char)((unsigned short)(out[i])>>8));
fwrite(&ss,1,1,fp2);
}
}//while
}//else
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -