📄 arithdec.c
字号:
/*****************************************************************************
// 程序: ebcot 编码
// 版本: V0.0
// 作者: 胡运平
// 最后修改时间 : 30, 6, 2005
// 功能描述:
Context variables made global, rather than access via pointers.
Manually inlined the CodeMPS and CodeLPS functions.
Implements mq 解码,实现MQ解码所需要的参数
****************************************************************************/
#include <stdio.h>
#include"mq_code.h"
// Set this to inline to make all internal functions inline.
#define inline
typedef struct
//上下文状态的相关信息
{
unsigned char I; //values in the range 0..46
unsigned char MPS; //MPS(either 0 or 1
} ArithDecContext;
//算术编码器所需要的状态信息
static long int C; //下限寄存器
static long int A; //间隔长度寄存器
static long int CT; //向下计数器
static unsigned char B; // The byte that is currently being assembled
static int firstByte;
//1 if the current byte is the first output byte, otherwise 0
//static int L;//代表到当前为止所产生的编码字节数
//static uint8 T;//临时字节缓冲器
//用 static来声明一个变量的作用有两个,一是对局部变量用static声明,则为该变量分配
//的空间在整个程序执行期间始终存在。二是全局变量用static声明,则该变量的作用域只限于
//本文件模块。
// The array of allowable context states
#define MAXCONTEXT 18
static ArithDecContext contexts[MAXCONTEXT+1];//19个(I,MPS)
// Special context labels
#define RUNLENGTH_CX 17
#define UNIFORM_CX 18
/*****************************************************************************
Define these inputs to have different data types
******************************************************************************/
static long int Qe[47] =
{//Qe值的十六进制表示
0x5601UL, 0x3401UL, 0x1801UL, 0x0ac1UL, 0x0521UL, 0x0221UL, 0x5601UL,
0x5401UL, 0x4801UL, 0x3801UL, 0x3001UL, 0x2401UL, 0x1c01UL, 0x1601UL,
0x5601UL, 0x5401UL, 0x5101UL, 0x4801UL, 0x3801UL, 0x3401UL, 0x3001UL,
0x2801UL, 0x2401UL, 0x2201UL, 0x1c01UL, 0x1801UL, 0x1601UL, 0x1401UL,
0x1201UL, 0x1101UL, 0x0ac1UL, 0x09c1UL, 0x08a1UL, 0x0521UL, 0x0441UL,
0x02a1UL, 0x0221UL, 0x0141UL, 0x0111UL, 0x0085UL, 0x0049UL, 0x0025UL,
0x0015UL, 0x0009UL, 0x0005UL, 0x0001UL, 0x5601UL
};
static unsigned char SWITCH[47] =
{
1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0
};
static unsigned char NMPS[47] =
{
1 , 2 , 3 , 4 , 5 , 38 ,
7 , 8 , 9 , 10 , 11 , 12 , 13 , 29 ,
15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 ,
23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 ,
31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 ,
39 , 40 , 41 , 42 , 43 , 44 , 45 , 45 ,
46
};
static unsigned char NLPS[47] =
{
1 , 6 , 9 , 12 , 29 , 33 ,
6 , 14 , 14 , 14 , 17 , 18 , 20 , 21 ,
14 , 14 , 15 , 16 , 17 , 18 , 19 , 19 ,
20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 ,
28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 ,
36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 ,
46
};
/*****************************************************************************
//输入字节Write in bytes, allowing for 0xFF stuffing.
*****************************************************************************/
static inline void byte_in(unsigned char b1)
{
/* This test sequence might speed up process */
if (B == 0xFF)//
{
// b1 = ReceiveByte(FILE *context);
if (b1 > 0x8F)
{
C += 0xFF00;
CT = 8;
}
else
{
C += (B<<=9);//B是C寄存器中的8个b
CT = 7;
}
}
else//B != 0XFF;
{
// B = ReceiveByte(FILE *context);
C += (B<<=8);//B是C寄存器中的8个b
CT = 8;
}
}
/******************************************************************************
//初始化算术解码器
******************************************************************************/
void ArithDecInit()
{
C = 0;
// B = ReceiveByte(FILE *context);
C += B << 16;
byte_in(B);
C <<= 7;
CT -= 7;
A = 0x8000;
}
/*****************************************************************************
编码中的重新归一化直到概率区间A的大小超过0.75
*****************************************************************************/
static inline void Renorme(void)
{
do
{//Check that there will be no overflow with these shifts
if (CT == 0)
byte_in(B);
A <<= 1;
C <<= 1;
CT -= 1;
}while (A <= 0x8000);//while((A && 0x8000)==0)
}
/*****************************************************************************
//Encode a bit using the given context.Output bits will be written to the file
given to ArithEncInit().
param: D - The bit to encode, either 0 or 1.
param: CX - The number of the context to use.
*****************************************************************************/
unsigned char ArithDecode(unsigned char CD,unsigned char CX)
{
ArithDecContext *pCX;//指向ArithDecContext的指针
unsigned char I;
unsigned char D;
long int QeI;
unsigned char MPS;
pCX = &(contexts[CX]);
//Put the current context into globals, and write them back later
I = pCX->I;//索引号0--46
MPS = pCX->MPS;//二进制数据。0 1
QeI = Qe[I];//概率估计值
if (pCX->MPS == CD)
{/* CodeMPS */
A -= QeI;
if ((C>>16)<QeI)//
{
if(A < QeI)
{
A = QeI;
D = MPS;
I = NMPS[I];
}
else
{
A = QeI;
D = 1- MPS;
if(SWITCH[I] == 1)
{
MPS = 1 - MPS;
}
I = NLPS[I];
}
Renorme();
}
else
{
C -= QeI<<16;
if (A >= 0x8000u)
D = MPS;
else
{
if(A < QeI)
{
D = 1- MPS;
if(SWITCH[I] == 1)
{
MPS = 1 - MPS;
}
I = NLPS[I];
}
else
{
D = MPS;
I = NMPS[I];
}
Renorme();
}
}
}
else
{/* CodeLPS */
A -= QeI;
if ((C>>16)<QeI)//
{
if(A < QeI)
{
A = QeI;
D = MPS;
I = NMPS[I];
}
else
{
A = QeI;
D = 1- MPS;
if(SWITCH[I] == 1)
{
MPS = 1 - MPS;
}
I = NLPS[I];
}
Renorme();
}
else
{
C -= QeI<<16;
if (A >= 0x8000u)
D = MPS;
else
{
if(A < QeI)
{
D = 1- MPS;
if(SWITCH[I] == 1)
{
MPS = 1 - MPS;
}
I = NLPS[I];
}
else
{
D = MPS;
I = NMPS[I];
}
Renorme();
}
}
}
pCX->I = I;
pCX->MPS = MPS;
return D;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -