📄 rcpced.cpp
字号:
//本程序主要实现RCPC信道编码
//输入、输出均为二进制数据流,存为文件
#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
#include "rcpc.h" //RCPC头文件,包含删除图样、生成矩阵、一个字节各位的异或值函数
#include "math.h" //用到了指数
#include "time.h" //用到了随机函数
#define Size 2810 //输入文件的大小(字节)
#define Impt 1405//623 //相对重要信息的大小(字节)
#define NUM 7 //重要信息选择的删余矩阵(头文件删余表的第NUM+1个)
#define NUM2 8 //不重要信息选择的删余矩阵(头文件删余表的第NUM2+1个)
#define per1 22/32 //重要信息RCPC码码率
#define per2 24/32 //不中信息RCPC码码率
#define error 2810*8*4*0.01 //信道随机误码数,3200*8*4是编码后的比特数,后面的小数是误码率
unsigned char symbols[Size*8*4]; //存放进入信道的比特数据
//RCPC编码函数
void encoded(unsigned char *data,int nbytes) //*data指向symbols,nbytes表示总字节数
{
unsigned char encstate=0,a[4]; //enstate是移位寄存器的状态,a[4]存放当前删余矩阵
int s; //s进入编码器的比特
int i,encoded=0; //encoded存放已编码数
/* else
{ a0=A0[s]^A0[s-1];
a1=A1[s]^A1[s-1];
a2=A2[s]^A2[s-1];
}
*/ //unsigned char *dd=data;
//printf("%d*****",*dd);
int count=0;
while(nbytes--!=0) //知道全部数据流编码为止
{ count++;
if(count<=Impt) //判断是否重要信息已编码完成
s=NUM;
else
s=NUM2;
a[0]=A0[s]; //选择删余矩阵
a[1]=A1[s];
a[2]=A2[s];
a[3]=A3[s];
for(i=7;i>=0;i--) //按字节操作
{ encstate=(encstate<<1)|((*data>>i)&1); //移一位编码一位
for(int j=0;j<4;j++) //判断是否需要传送
{ if((a[j]>>i)&1) //若需要传送
{ symbols[encoded]=Partab(encstate&G[j]); //编码送入信道
//printf("**%d**",*(buffer+encoded));
encoded++;
}
}
}
data++;
}
}
int random(int number) //能按C语言中那样产生大小范围确定的随机函数
{
return (int)(number/(float)RAND_MAX * rand());
}
void main() //主函数
{
FILE *in_fp; //打开要编码的文件,二进制形式
in_fp=fopen("1.jpg","rb");
if(in_fp==NULL)
{
printf("cannot open this file\n"); exit(0);
}
unsigned char *buffer; //把文件读进buffer内存
buffer=(unsigned char * )malloc(Size);
fread(buffer,Size,1,in_fp);
// *(buffer)<<=2;
// *(buffer)+=1;
// printf("%x",*buffer);
// for(int i=0;i<2810;i++)
// printf("**%x**",*(buffer+i));
//*************************
unsigned char path_memory_i[16][Size*8]={0}; //存放每一个状态的输入状态
unsigned char path_memory_j[16]={0}; //存放当前状态的输入状态
unsigned char state_path_metric_i[16]={0},state_path_metric_j[16]={0}; //存放路径差错累加值,当前状态的路径差错值
encoded(buffer,Size); //编码函数
unsigned char enstate=0,a[4],b[4];
srand((unsigned)time(NULL)); //随机误码产生
for(int r=0;r<error;r++)
{ int rr=random(1600*8*4*per1+1600*8*4*per2);
symbols[rr]=1^symbols[rr]; //误码位取反
}
// for(int r=1;r<10;r++)
// { printf("**%d**",random(100));
// }
unsigned char newsymbols[Size*8*4],s1; //重新定义一数组,接收信道比特
int t1=0,t2=0,i,j;
int nbytes=Size;
int count=0; //解码
while(nbytes--!=0) //直到全部解码完为止
{ count++;
if(count<=Impt) //判断是否是重要信息
s1=NUM; //因为解码必须与编码端对应
else
s1=NUM2;
a[0]=A0[s1];
a[1]=A1[s1];
a[2]=A2[s1];
a[3]=A3[s1];
for( i=7;i>=0;i--) //若是被删除的比特填“0”
{ for( j=0;j<4;j++)
{ if((a[j]>>i)&1)
newsymbols[t1++]=symbols[t2++];
else
newsymbols[t1++]=0;
}
}
}
// for( j=0;j<Size*8*4;j++)
// { printf("*%d*",newsymbols[j]);
// }
//**************************************
s1=NUM;
a[0]=A0[s1];
a[1]=A1[s1];
a[2]=A2[s1];
a[3]=A3[s1];
int t;
//起始的约束长度应单独解码
for(t=0;t<4;t++) //下面主要是维特比译码的思想
{ for(j=0;j<pow(2,t+1);j++) //pow为指数函数,计算状态数
{ enstate=j/2; //enstate是j状态的前输入状态
enstate=(enstate<<1)|(j%2); //enstate存放移位寄存器当前状态
for(i=0;i<4;i++)
{ b[i]=Partab(enstate&G[i]); //卷积码编码
if(a[i]>>(7-t)) //若是被删余的比特就不用计算路径差错值
state_path_metric_j[j]+=newsymbols[4*t+i]^b[i];
}
path_memory_j[j]=j/2; //当前状态的输入状态
state_path_metric_j[j]+=state_path_metric_i[j/2]; //计算当前状态的路径差错累加值
//printf("%d",j/2);
}
for(j=0;j<pow(2,t+1);j++)
{ state_path_metric_i[j]=state_path_metric_j[j]; //存放路径差错累加值
path_memory_i[j][t]=path_memory_j[j]; //存放当前状态的输入状态
// printf("%d",state_path_metric_j[j]);
state_path_metric_j[j]=0; //准备下一状态的计算
}
//printf("\n");
}
//***************************************
int state_end=Size*8; //一个约束长度计算完后可以循环至数据流结束
unsigned char i1,i2,s;
int tt;
for(t=4;t<state_end;t++)
{ if(t<8) //按字节操作 tt移位用
tt=7-t;
else
tt=7-(t%8);
if(t/8<=Impt) //判断何时时重要信息
s1=NUM;
else
s1=NUM2;
a[0]=A0[s1];
a[1]=A1[s1];
a[2]=A2[s1];
a[3]=A3[s1];
for(j=0;j<16;j++) //重复上述维特比译码
{ if(j%2==0) //总结的规律:若当前状态j是偶数,则前一个状态为i1
{ i1=j/2; i2=i1+8; s=0; //前另一个输入状态为i2,输入为0
}
else
{ i1=(j-1)/2;i2=i1+8;s=1; //若当前状态j是奇数,则输入是1
}
state_path_metric_j[j]=0;
enstate=i1; //重复编码过程,先令移位寄存器状态为i1
enstate=(enstate<<1)|s;
for(i=0;i<4;i++)
{ b[i]=Partab(enstate&G[i]);
if(a[i]>>tt) //判断是否被删余,若是则不用计算路径差错值
state_path_metric_j[j]+=newsymbols[4*t+i]^b[i];
}
path_memory_j[j]=i1; //和前面一样
state_path_metric_j[j]+=state_path_metric_i[i1];
unsigned char branch_path_metric=0; //存放路径分支差错值
enstate=i2; //编码i2状态
enstate=(enstate<<1)|s;
for(i=0;i<4;i++)
{ b[i]=Partab(enstate&G[i]);
if(a[i]>>tt)
branch_path_metric+=newsymbols[4*t+i]^b[i]; //存放在分支中
}
branch_path_metric+=state_path_metric_i[i2];
if(state_path_metric_j[j]>branch_path_metric) //比较进入当前状态的两个状态的路径差错累加值,取小的,保留
{ state_path_metric_j[j]=branch_path_metric;
path_memory_j[j]=i2;
}
else
{ path_memory_j[j]=i1;
}
}
for(j=0;j<16;j++) //存放
{ state_path_metric_i[j]=state_path_metric_j[j];
path_memory_i[j][t]=path_memory_j[j];
//printf("%d",state_path_metric_j[j]);
//printf("%d",path_memory_i[j][t]);
}
//cout<<t<<endl;
}
int select_path; //解码完,选择路径差错累加值最小的路径
select_path=state_path_metric_i[0];
i=0;
for(j=1;j<16;j++)
{ if(select_path>state_path_metric_i[j])
{ select_path=state_path_metric_i[j];
i=j;
}
}
//cout<<select_path<<i<<endl;
unsigned char ss[Size*8]; //存放解码的数据流
for(t=state_end-1;t>=0;t--)
{ if(i%2==0) //与前面总结的规律一样,逆
ss[t]=0;
else
ss[t]=1;
i=path_memory_i[i][t]; //我们已经记录了每个状态的前一个状态,所以很容易找回原始的路径
//cout<<ss[t]<<endl;
// printf("**%d**",ss[t]);
}
// for( i=0;i<Size*8;i++)
// printf("**%d**",ss[i]);
unsigned char *buffer1; //重新开辟内存,存放解码后的数据流
buffer1=(unsigned char * )malloc(Size);
for(i=0;i<Size*8;i++) //恢复成字节
{ *(buffer1+i/8)<<=1;
*(buffer1+i/8)+=ss[i];
}
// for( i=0;i<Size;i++)
// printf("**%x**",*(buffer+i));
char filename[10]; //用于存放输入文件名
printf("please input filename: \n");
scanf("%s",filename);
//*************************
FILE *out_fp;
out_fp=fopen(filename,"wb");
if (out_fp==NULL)
exit(0);
fwrite(buffer1,Size,1,out_fp);
for(i=0;i<Size;i++) //计算误码
*(buffer1+i)=*(buffer1+i)^*(buffer+i);
// for( i=0;i<Size;i++)
// { if(*(buffer1+i))
// printf("%d**%x**",i,*(buffer1+i));
// }
int counter=0;
for( i=0;i<Impt;i++)
{ if(*(buffer1+i))
{ //printf("%d**%x**",i,*(buffer1+i));
for(j=7;j>=0;j--)
{ if((*(buffer1+i)>>j)&1)
counter++;
}
}
}
printf(" %d %f ",counter,float(counter)/(Impt*8)); //输出误码个数和误码率
counter=0;
for( i=Impt;i<Size;i++)
{ if(*(buffer1+i))
{ //printf("%d**%x**",i,*(buffer1+i));
for(j=7;j>=0;j--)
{ if((*(buffer1+i)>>j)&1)
counter++;
}
}
}
printf(" %d %f ",counter,float(counter)/((Size-Impt)*8)); //输出误码个数和误码率
fclose(in_fp); //关闭文件,释放内存
fclose(out_fp);
free(buffer);
free(buffer1);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -