⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcpced.cpp

📁 仿真程序主体部分由c语言完成,改变运行的设定的参数
💻 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 + -