維特比譯碼算法 轉帖

//實現(4,1,6)卷積碼的維特比譯碼源程序,採用了最大似然算法
//介紹了軟判決維特比譯碼算法過程的三個步驟:初始化,度量更新和回溯譯碼
#include< stdio.h>
#define data_length 4000000
#define traceback_length 48 //譯碼回溯深度,一般爲m的5-10倍,m爲寄存器個數
#define tb_data_out 16 //回溯輸出譯碼長度,即每次回溯輸出16bits譯碼信息


unsigned long trans_table[2traceback_length]={0} //一個單元32位,每兩個存儲單元存儲一個時刻的64狀態倖存信息
unsigned long tran //存儲每個時刻的分支選擇路徑信息值,32位
int bef[64]={0} //前64狀態
int aft[64]={0} //後64狀態

void bfly_a(int dp int dm int p1 int p2 int p3 int select) //用於計算路徑度量
void tran_exchange() //用於調整tran中第2,3位的次序
void trace_back(int pout) //回溯
int max_state(int pbef) //用於找到具有最大值所對應的狀態點
int min(int pbef) //求出64個狀態的最小值

void viterbi()
{
//採用軟判決,16電平量化,量化範圍:-8到7,理想情況下1爲-8,0爲7

int t0 t1 t2 t3 //分支度量因子
int n i j
int st mini

int input[4]={0} //keep input data
int output[tb_data_out]={0} //keep output data
int pb pa1 pa2 //pb指向前狀態,pa1 pa2指向後狀態
int p4 //存儲路徑信息

file fp
file fq

if((fp=fopen(" quantizer_bpsk0db.bin" " r" ))==null)
{
printf(" cannot not open file!/n" ) //file that provides input data
exit(1)
}

if((fq=fopen(" viterbi_data_out.bin" " wb" ))==null) //file that keep output data
{
printf(" cannot not open file viterbi_data_out!/n" )
exit(1)
}

bef[0]=1000 //從0狀態開始,任意賦一個初值

for(n=0 n< data_length/tb_data_out n++) //回溯次數,由處理數據長度定
{
if(n==0)
p4=trans_table
else if(n> =3)
p4=trans_table+2(traceback_length-tb_data_out)

for(j=0 j< tb_data_out j++) //每次循環對應一個時刻
{
pb=bef
pa1=aft
pa2=aft+2

fread(input sizeof(int) 4 fp) //read input data

//4個不同的分支度量因子,對應前4個蝶形
//他們對應的因子爲:0000,0110,0010,0100
t0=input[0] + input[1] + input[2] + input[3]
t1=input[0] - input[1] - input[2] + input[3]
t0=input[0] + input[1] - input[2] + input[3]
t0=input[0] - input[1] + input[2] + input[3]
// printf(" t0=d t1=d t2=d t3=d/n" t0 t1 t2 t3)

//每時刻64個狀態,32個蝶形,兩個蝶形爲一組,共循環16次
tran=0
for(i=0 i< 16 i++)
{
//16個蝶形的執行順序是state:0-1-1-0--2-3-3-2--4-5-5-4--6-7-7-6
if(i==0||i==3)
st=0
else if(i==1||i==2)
st=1
else if(i==4||i==7)
st=2
else if(i==5||i==6)
st=3
else if(i==8||i==11)
st=4
else if(i==9||i==10)
st=5
else if(i==12||i==15)
st=6
else
st=7

switch(st)
{
case 0:
bfly_a(t0 t1 pb pa1 pa2 0)
pa1++
pa2++
bfly_a(t0 t1 pb pa1 pa2 1)
//以下調整tran中第2,3位的次序
tran_exchange()
break
case 1:
bfly_a(-t2 -t3 pb pa1 pa2 0)
pa1++
pa2++
bfly_a(-t2 -t3 pb pa1 pa2 1)
//以下調整tran中第2,3位的次序
tran_exchange()
break
case 2:
bfly_a(-t2 -t3 pb pa1 pa2 1)
pa1++
pa2++
bfly_a(-t2 -t3 pb pa1 pa2 0)
//以下調整tran中第2,3位的次序
tran_exchange()
break
case 3:
bfly_a(t0 t1 pb pa1 pa2 1)
pa1++
pa2++
bfly_a(t0 t1 pb pa1 pa2 0)
//以下調整tran中第2,3位的次序
tran_exchange()
break
case 4:
if(i==8)
{
(p4++)=tran //前32位存儲一次
tran=0
}
bfly_a(t1 t0 pb pa1 pa2 1)
pa1++
pa2++
bfly_a(t1 t0 pb pa1 pa2 0)
tran_exchange()
break
case 5:
bfly_a(-t3 -t2 pb pa1 pa2 1)
pa1++
pa2++
bfly_a(-t3 -t2 pb pa1 pa2 0)
tran_exchange()
break
case 6:
bfly_a(-t3 -t2 pb pa1 pa2 0)
pa1++
pa2++
bfly_a(-t3 -t2 pb pa1 pa2 1)
tran_exchange()
break
case 7:
bfly_a(t1 t0 pb pa1 pa2 0)
pa1++
pa2++
bfly_a(t1 t0 pb pa1 pa2 1)
tran_exchange()
break
default:
printf(" state error!/n" )
break
}
pa1=pa1+3 //進入下一組蝶形運算
pa2=pa2+3
pb=pb+2
}//end of i
(p4++)=tran //存儲分支路徑,後32位存儲一次

for(i=0 i< 64 i++)
bef[i]=aft[i]

}//end of j

//48時刻後,每16時刻回溯一次,輸出16bits譯碼信息
if(n> =2)
{
trace_back(output)

//將輸出寫到文件中
fwrite(output sizeof(int) tb_data_out fq)

//爲了防止溢出,每個狀態減去最小值
mini=min(bef)
for(i=0 i< 64 i++)
{
bef[i]=bef[i]-mini
}

//trans_table信息移位
for(i=0 i< 2(traceback_length-tb_data_out) i++)
{
trans_table[i]=trans_table[i+32]
}
}

//清零輸出
for(j=0 j< tb_data_out j++)
{output[j]=0 }
}//end of n
fclose(fq)
fclose(fp)
}

void bfly_a(int dp int dm int p1 int p2 int p3 int select)
{
int a b c d

if(select==0)
{
a=p1+dp
b=(p1+1)+dm
c=(p1+32)-dp
d=(p1+33)-dm
}
else if(select==1)
{
a=p1-dp
b=(p1+1)-dm
c=(p1+32)+dp
d=(p1+33)+dm
}
else
{
printf(" parameter input errror!/n" )
exit(1)
}

tran=tran< < 1

p2=a
p3=b
if(c> a) //c路徑標記爲1,a路徑標記爲0
{
tran=tran|0x01
p2=c
}

tran=tran< < 1

if(d> b) //d路徑標記爲1,b路徑標記爲0
{
tran=tran|0x01
p3=d
}
}

void trace_back(int pout)
{
int p4 pt
int state //標識狀態
int i num
int tb_data[traceback_length]={0} //回溯數據,其最高16位爲回溯譯碼輸出

p4=trans_table+2traceback_length //移到數組最後
pt=tb_data+traceback_length //移到數組最後,從後往前填充輸出數據
state=max_state(bef) //找到此時刻包含最大值的狀態

for(i=0 i< traceback_length i++)
{
p4=p4-2 //兩個單元爲一個整體,前一個單元處理前32狀態
pt-- //輸出數據

//下面分兩部分操作,前一部分處理前32狀態,後一部分處理後32狀態
if(state> =0& & state< 32)
{
if(state& 0x01) //只有state爲奇數時,輸入纔可能爲1
pt=1
else
pt=0

num=31-state
state=state> > 1 //回到前一時刻
if((p4> > num)& 0x01)
state=state+32
}
else if(state> =32& & state< 64)
{
p4++
if(state& 0x01) //只有state爲奇數時,輸入纔可能爲1
pt=1
else
pt=0

num=63-state
state=state> > 1 //回到前一時刻
if((p4> > num)& 0x01)
state=state+32
p4--
}
}//end of i

//輸出最高位16bits譯碼信息
pt=tb_data
for(i=0 i< tb_data_out i++)
{
(pout++)=(pt++)
}
}

void tran_exchange()
{
int x y
x=((tran& 0x04)?1:0) //取出tran的第3位
y=((tran& 0x02)?1:0) //取出tran的第2位
if(x!=y) //如果不等則交換
{
if(x> y)
tran=tran-2 //tran的第2,3位互換
else
tran=tran+2 //tran的第2,3位互換
}
}

int max_state(int pbef) //包含最大值的狀態
{
int i
int a max max_state

max=pbef
max_state=0
for(i=1 i< 64 i++)
{
a=(++pbef)
if(a> max)
{
max=a
max_state=i
}
}
return max_state
}

int min(int pbef)
{
int i
int a
int mini

mini=pbef
for(i=1 i< 64 i++)
{
a=(++pbef)
if(a< mini)
mini=a
}
return mini
}

void main()
{
vitervi()
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章