当前位置:文档之家› Viterbi译码程序代码

Viterbi译码程序代码

译码主要部分#include"stdafx.h"//#define DEBUGvoid deci2bin(int d, int size, int *b);int bin2deci(int *b, int size);int nxt_stat(int current_state, int input, int *memory_contents);void init_quantizer(void);void init_adaptive_quant(float es_ovr_n0);int soft_quant(float channel_symbol);int soft_metric(int data, int guess);int quantizer_table[256];void sdvd(int g[2][K], float es_ovr_n0, long channel_length, float*channel_output_vector, int *decoder_output_matrix){int i, j, l, ll; //循环控制变量long t; //时间int memory_contents[K]; //记录输入内容int input[TWOTOTHEM][TWOTOTHEM]; //对当前状态以及下一个状态映射int output[TWOTOTHEM][2]; //卷积码编码输出矩阵int nextstate[TWOTOTHEM][2]; //下一个状态矩阵int accum_err_metric[TWOTOTHEM][2]; //误差累计矩阵int state_history[TWOTOTHEM][K * 5 + 1]; //历史状态表int state_sequence[K * 5 + 1]; //状态序列int *channel_output_matrix; //信道输出序列int binary_output[2];int branch_output[2]; //0或者1的输出分支int m, n, number_of_states, depth_of_trellis, step, branch_metric,sh_ptr, sh_col, x, xx, h, hh, next_state, last_stop;n = 2; //1/2为卷积码传输数据的码率m = K - 1;//寄存器个数number_of_states = (int)pow(2.0, m);//状态个数number of states = 2^(K - 1) = 2^mdepth_of_trellis = K * 5;for (i = 0; i < number_of_states; i++){for (j = 0; j < number_of_states; j++)input[i][j] = 0; //输入数组初始化for (j = 0; j < n; j++){nextstate[i][j] = 0;//下一个状态数组初始化output[i][j] = 0; //输出数组初始化}for (j = 0; j <= depth_of_trellis; j++){state_history[i][j] = 0;//历史状态数组初始化state_history[4][16] }accum_err_metric[i][0] = 0;//误差累计矩阵第一列初始化为0accum_err_metric[i][1] = MAXINT;//误差累计矩阵第二列初始化为一个很大的数}/*前向纠错简称FEC(Forward Error Correction),其原理是:发送方将要发送的数据附加上一定的冗余纠错码一并发送,接收方则根据纠错码对数据进行差错检测,如发现差错,由接收方进行纠正*//*产生状态转移矩阵、输出矩阵、输入矩阵*///输入矩阵表示的是FEC编码传输给下一个状态//下一个状态由输入和当前状态给出//输出矩阵for (j = 0; j < number_of_states; j++){for (l = 0; l < n; l++){next_state = nxt_stat(j, l, memory_contents);input[j][next_state] = l;/*计算给定的卷积编码器输出当前状态数和输入值*/branch_output[0] = 0;branch_output[1] = 0;for (i = 0; i < K; i++){branch_output[0] = branch_output[0] ^ memory_contents[i] & g[0][i];branch_output[1] = branch_output[1] ^ memory_contents[i] & g[1][i];}nextstate[j][l] = next_state;//下一个状态output[j][l] = bin2deci(branch_output, 2);//输出十进制}}#ifdef DEBUGprintf("\nInput:");for (j = 0; j < number_of_states; j++){printf("\n");for (l = 0; l < number_of_states; l++)printf("%2d ", input[j][l]);}printf("\nOutput:");for (j = 0; j < number_of_states; j++){printf("\n");for (l = 0; l < n; l++)printf("%2d ", output[j][l]);}printf("\nNext State:");for (j = 0; j < number_of_states; j++){printf("\n");for (l = 0; l < n; l++)printf("%2d ", nextstate[j][l]);}#endifchannel_output_matrix =(int *)malloc(channel_length * sizeof(int));if (channel_output_matrix == NULL){printf("allocation is failure!!\n");exit(1);}printf("\n");/*信道输出为n行,2列,每行对应于一个通道符号给定的位和每一列对应于一个已编码的位*/ channel_length = channel_length / n;init_adaptive_quant(es_ovr_n0);//进行优化,匹配过信噪比的量化矩阵//量化信道输出,将浮点型数据转化为整形for (t = 0; t < (channel_length * n); t = t + n){for (i = 0; i < n; i++){*(channel_output_matrix + (t / n) + (i * channel_length)) =soft_quant(*(channel_output_vector + (t + i)));//printf("%d ",*(channel_output_matrix + (t / n) + (i * channel_length)));}}/*结束设置:利用网格遍历开始译码通道,在编码完成后结束*/for (t = 0; t < channel_length - m; t++){if (t <= m)//假设从零,所以只是计算路径的所有零状态step = (int)pow(2.0, m - t * 1);//如果不写成2.0,会出现函数重载不明确的错误elsestep = 1;//利用state_history矩阵作为循环缓冲区sh_ptr = (int)((t + 1) % (depth_of_trellis + 1));//sh_ptr为state history矩阵的指针for (j = 0; j < number_of_states; j += step){//重复每个可能的卷积编码器的输出组for (l = 0; l < n; l++){branch_metric = 0;//计算每个通道符号的分支度量,以及所有的信道总和在卷积编码器的输出组信道符号binary_output[0] = (output[j][l] & 0x00000002) >> 1;binary_output[1] = output[j][l] & 0x00000001;branch_metric = branch_metric +abs(*(channel_output_matrix + (0 * channel_length + t)) - 7 *binary_output[0])+ abs(*(channel_output_matrix + (1 * channel_length + t)) - 7 * binary_output[1]);//选择累加误差最小的if (accum_err_metric[nextstate[j][l]][1] > accum_err_metric[j][0] + branch_metric){accum_err_metric[nextstate[j][l]][1] = accum_err_metric[j][0] + branch_metric;state_history[nextstate[j][l]][sh_ptr] = j;//printf("state_history[%d][%d]=%d\n", nextstate[j][l], sh_ptr,state_history[nextstate[j][l]][sh_ptr]);}} //循环l结束} //j结束,更新网格//accum_err_metric矩阵第二列移到第一列,第二列标志为一个很大的数for (j = 0; j < number_of_states; j++){accum_err_metric[j][0] = accum_err_metric[j][1];//printf("accum_err_metric[%d][0]=%d\n", j, accum_err_metric[j][0]);accum_err_metric[j][1] = MAXINT;}//如果网格填充完成,现在需要追踪{for (j = 0; j <= depth_of_trellis; j++)//初始化状态序列矩阵state_sequence[j] = 0;// 找到的最小累积state_history元素x = MAXINT;for (j = 0; j < (number_of_states / 2); j++){if(accum_err_metric[j][0] < accum_err_metric[number_of_states - 1 - j][0]){xx = accum_err_metric[j][0];hh = j;}else{xx = accum_err_metric[number_of_states - 1 - j][0];hh = number_of_states - 1 - j;}if (xx < x){x = xx;h = hh;}}state_sequence[depth_of_trellis] = h;for (j = depth_of_trellis; j > 0; j--){sh_col = j + (sh_ptr - depth_of_trellis);if (sh_col < 0)sh_col = sh_col + depth_of_trellis + 1;state_sequence[j - 1] = state_history[state_sequence[j]][sh_col];}//找出输入序列对应的状态序列在最佳路径*(decoder_output_matrix + t - depth_of_trellis + 1) =input[state_sequence[0]][state_sequence[1]];//printf("译码输出:%d\n", *(decoder_output_matrix + t - depth_of_trellis + 1));} //if状态} // 结束t循环//译码信道中的数据for (t = channel_length - m; t < channel_length; t++){sh_ptr = (int)((t + 1) % (depth_of_trellis + 1));last_stop = number_of_states / pow(2.0, t - channel_length + m);//不需要考虑输入的状态是1,所以确定最高可能的状态数是0for (j = 0; j < last_stop; j++){branch_metric = 0;deci2bin(output[j][0], n, binary_output);for (ll = 0; ll < n; ll++){branch_metric = branch_metric + soft_metric(*(channel_output_matrix + (ll * channel_length + t)), binary_output[ll]);}if ((accum_err_metric[nextstate[j][0]][1] > accum_err_metric[j][0] +branch_metric)){accum_err_metric[nextstate[j][0]][1] = accum_err_metric[j][0] +branch_metric;state_history[nextstate[j][0]][sh_ptr] = j;}}for (j = 0; j < number_of_states; j++){accum_err_metric[j][0] = accum_err_metric[j][1];accum_err_metric[j][1] = MAXINT;}//对所选路径进行选择{for (j = 0; j <= depth_of_trellis; j++)state_sequence[j] = 0;x = accum_err_metric[0][0];h = 0;for (j = 1; j < last_stop; j++){if (accum_err_metric[j][0] < x){x = accum_err_metric[j][0];h = j;}}state_sequence[depth_of_trellis] = h;for (j = depth_of_trellis; j > 0; j--){sh_col = j + (sh_ptr - depth_of_trellis);if (sh_col < 0)sh_col = sh_col + depth_of_trellis + 1;state_sequence[j - 1] = state_history[state_sequence[j]][sh_col];}*(decoder_output_matrix + t - depth_of_trellis + 1) =input[state_sequence[0]][state_sequence[1]];} //if条件状态} //结束t循环for (i = 1; i < depth_of_trellis - m; i++)*(decoder_output_matrix + channel_length - depth_of_trellis + i) =input[state_sequence[i]][state_sequence[i + 1]];free(channel_output_matrix);return;}//初始化三位软判决量化编码器//加入噪声后的量化void init_adaptive_quant(float es_ovr_n0){int i, d;float es, sn_ratio, sigma;es = 1;sn_ratio = (float)pow(10.0, (es_ovr_n0 / 10.0));sigma = (float)sqrt(es / (2.0 * sn_ratio));d = (int)(32 * 0.5 * sigma);for (i = -128; i < (-3 * d); i++)quantizer_table[i + 128] = 7;for (i = (-3 * d); i < (-2 * d); i++)quantizer_table[i + 128] = 6;for (i = (-2 * d); i < (-1 * d); i++)quantizer_table[i + 128] = 5;for (i = (-1 * d); i < 0; i++)quantizer_table[i + 128] = 4;for (i = 0; i < (1 * d); i++)quantizer_table[i + 128] = 3;for (i = (1 * d); i < (2 * d); i++)quantizer_table[i + 128] = 2;for (i = (2 * d); i < (3 * d); i++)quantizer_table[i + 128] = 1;for (i = (3 * d); i < 128; i++)quantizer_table[i + 128] = 0;}//channel_symbol信道中的值为-1或+1的加噪信号int soft_quant(float channel_symbol){int x;x = (int)(32.0 * channel_symbol); //则x的平均值为-32或+32if (x < -128) x = -128; //小于-128,输出128if (x > 127) x = 127; //大于127则输出127return(quantizer_table[x + 128]); //查找量化表}/* this metric is based on the algorithm given in Michelson and Levesque, page 323. */int soft_metric(int data, int guess){return(abs(data - (guess * 7)));//当给出当前状态以及输入时,计算下一个状态,并且计算卷积码编码内容int nxt_stat(int current_state, int input, int *memory_contents){int binary_state[K - 1]; //二进制当前状态int next_state_binary[K - 1]; //二进制下一个状态int next_state; //十进制当前状态int i;deci2bin(current_state, K - 1, binary_state);next_state_binary[0] = input;for (i = 1; i < K - 1; i++)next_state_binary[i] = binary_state[i - 1];next_state = bin2deci(next_state_binary, K - 1);memory_contents[0] = input;for (i = 1; i < K; i++)memory_contents[i] = binary_state[i - 1]; //编码内容return(next_state);//返回十进制的下一个状态}//将十进制数据转化为特殊的二进制,例如:十进制“100011”输出二进制数据100011 void deci2bin(int d, int size, int *b) {int i;for (i = 0; i < size; i++)b[i] = 0;b[size - 1] = d & 0x01;for (i = size - 2; i >= 0; i--) {d = d >> 1;b[i] = d & 0x01;}}//将2进制数据转化为特殊的十进制,例如:二进制“100011”输出十进制数据100011 int bin2deci(int *b, int size) {int i, d;d = 0;for (i = 0; i < size; i++)d += b[i] << (size - i - 1);return(d);}程序辅助模块// viterbi.cpp : 定义控制台应用程序的入口点。

相关主题