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

📄 imppm.c

📁 语音图像压缩dpcm编码源程序
💻 C
字号:

//#define NO_PPM
//#define DEBUG

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <crbinc/inc.h>
#include <crbinc/bbitio.h>
#include <crbinc/arithc.h>
#include <crbinc/memutil.h>
#include <crbinc/mempool.h>

extern int tune_param;

#ifdef DEBUG
#define dprintf3(a,b,c,d) printf(a,b,c,d)
#else
#define dprintf3(a,b,c,d)
#endif

/**** primary config ****/

#define HASH_BITS			14
#define PPMQ_CNTX_BITS		5
#define PPMQ_SMTH_BITS		2	// helps a miniscule amount (0.002 bpb)
#define PPMQ_SMTH_DIV		0

/**** secondary config ****/

#define HASH_SIZE (1<<HASH_BITS)
#define HASH(cntx)	((cntx ^ (cntx>>11)) & (HASH_SIZE - 1))

#define PPMQ_SIZE 			(1<<(PPMQ_CNTX_BITS + PPMQ_SMTH_BITS))
#define PPMQ_CNTX_MAX					((1<<PPMQ_CNTX_BITS)-1)
#define PPMQ_CNTX_HASH(cntx)	(((cntx>>3)^cntx)&PPMQ_CNTX_MAX)
#define PPMQ_SMTH_MAX					((1<<PPMQ_SMTH_BITS)-1)
#define PPMQ_HASH(cntx,smth)	((PPMQ_CNTX_HASH(cntx) << PPMQ_SMTH_BITS) + min((smth>>PPMQ_SMTH_DIV),PPMQ_SMTH_MAX))

#define BAD_PRED 			0xFFFF
#define TOT_SCALEDOWN		8000

typedef struct _imcontext {
  struct _imcontext *next;
  ulong cntx1,cntx2;
  uword pred;
} imcontext;

typedef struct Image_PPM_Info {
	struct FAI * arith;
	MemPool * contextPool;
	imcontext * contexts[HASH_SIZE];	// easy to add more orders, if you like
	uword ppmq_tot[PPMQ_SIZE],ppmq_esc[PPMQ_SIZE];
} imppmi;

/**********************/

imppmi * iOpen(struct FAI * FAI);

int iDecode(imppmi *ipi,ulong cntx1,ulong cntx2,uword smoothness);	// -1 for none
void iDecodeGot(imppmi *ipi,ulong cntx1,ulong cntx2,uword value);
bool iEncode(imppmi *ipi,ulong cntx1,ulong cntx2,uword value,uword smoothness); // coded/not

int  imppmDecode(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],uword smoothness);
bool imppmEncode(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],uword value,uword smoothness);
void imppmAddC(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],uword value);

imcontext * imppmFind(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[]);

/*********************/

imppmi * iOpen(struct FAI * FAI)
{
imppmi * ipi;
int i;

if ( (ipi = new(imppmi) ) == NULL )
	return(NULL);

ipi->arith = FAI;

if ( (ipi->contextPool = AllocPool(sizeof(imcontext),1024,1024)) == NULL )
	{ iFree(ipi); return(NULL); }

for(i=0;i<PPMQ_SIZE;i++) {
	ipi->ppmq_esc[i] = 1;
	ipi->ppmq_tot[i] = 2;
}

return(ipi);
}

extern void iFree(imppmi *ipi)
{
if ( ipi->contextPool ) FreePool(ipi->contextPool);
free(ipi);
}

imcontext * imppmFind(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[])
{
imcontext *c;
ulong hash;

	hash = HASH(cntx1);
	c = contexts[hash];
	while( c ) {
		if ( c->cntx1 == cntx1 )
			if ( c->cntx2 == cntx2 )
				return(c);

		c = c->next;
	}

return NULL;
}

bool iEncode(imppmi *ipi,ulong cntx1,ulong cntx2,uword value,uword smoothness)
{

#ifdef NO_PPM
return false;
#endif

	dprintf3("%08X %08X : %d\n",cntx1,cntx2,value);

	if ( ! imppmEncode(ipi,cntx1,cntx2,ipi->contexts,value,smoothness) )
		return false;

	return true;
}

int iDecode(imppmi *ipi,ulong cntx1,ulong cntx2,uword smoothness)
{
int value;

#ifdef NO_PPM
return -1;
#endif

	if ( (value = imppmDecode(ipi,cntx1,cntx2,ipi->contexts,smoothness)) == -1 ) {
		return -1;
	}

	dprintf3("%08X %08X : %d\n",cntx1,cntx2,value);

return value;
}

void iDecodeGot(imppmi *ipi,ulong cntx1,ulong cntx2,uword value)
{

#ifdef NO_PPM
return;
#endif

	dprintf3("%08X %08X : %d a\n",cntx1,cntx2,value);

	imppmAddC(ipi,cntx1,cntx2,ipi->contexts,value);
}

bool imppmEncode(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],
	uword value,uword smoothness) // bool : coded
{
imcontext *c;
ulong hash,esc,tot;
bool ret;

	if ( (c = imppmFind(ipi,cntx1,cntx2,contexts)) == NULL ) {
		c = (imcontext *) GetPoolHunk(ipi->contextPool,TRUE);

		hash = HASH(cntx1);
		c->next = contexts[hash];
		contexts[hash] = c;

		c->cntx1 = cntx1;	c->cntx2 = cntx2;
	
		c->pred = value;

		return false;
	}

	if ( c->pred == BAD_PRED )	// made a bad pred
		return false;

	hash = PPMQ_HASH(cntx1,smoothness);

	tot = ipi->ppmq_tot[hash];
	esc = ipi->ppmq_esc[hash];

	if ( value == c->pred ) {
		arithEncode(ipi->arith,esc,tot,tot);
		ret = true;
	} else {
		arithEncode(ipi->arith,0,esc,tot);
		c->pred = BAD_PRED;	// never use this context again
		ret = false;
		ipi->ppmq_esc[hash]++;
	}

	if ( ++(ipi->ppmq_tot[hash]) > TOT_SCALEDOWN ) {
		ipi->ppmq_tot[hash] >>= 1; ipi->ppmq_esc[hash] >>= 1;
		ipi->ppmq_tot[hash] ++;
		if ( ipi->ppmq_esc[hash] > 1 ) ipi->ppmq_esc[hash] = 1;
	}

	return ret;
}

int imppmDecode(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],
	uword smoothness)	// -1 is an escape
{
imcontext *c;
ulong hash,got,esc,tot;
int ret;

	if ( (c = imppmFind(ipi,cntx1,cntx2,contexts)) == NULL ) {
		return -1;
	}

	if ( c->pred == BAD_PRED )	// made a bad pred
		return -1;

	hash = PPMQ_HASH(cntx1,smoothness);
	tot = ipi->ppmq_tot[hash];
	esc = ipi->ppmq_esc[hash];

	got = arithGet(ipi->arith,tot);

	if ( got < esc ) { //escape
		arithDecode(ipi->arith,0,esc,tot);
		c->pred = BAD_PRED;
		ret = -1;
		ipi->ppmq_esc[hash] ++;
	} else {
		arithDecode(ipi->arith,esc,tot,tot);
		ret = c->pred;
	}

	if ( ++(ipi->ppmq_tot[hash]) > TOT_SCALEDOWN ) {
		ipi->ppmq_tot[hash] >>= 1; ipi->ppmq_esc[hash] >>= 1;
		ipi->ppmq_tot[hash] ++;
		if ( ipi->ppmq_esc[hash] > 1 ) ipi->ppmq_esc[hash] = 1;
	}

	return ret;
}

void imppmAddC(imppmi *ipi,ulong cntx1,ulong cntx2,imcontext *contexts[],uword value)
{
imcontext *c;

	if ( (c = imppmFind(ipi,cntx1,cntx2,contexts)) == NULL ) {
		ulong hash;

		c = (imcontext *) GetPoolHunk(ipi->contextPool,TRUE);

		hash = HASH(cntx1);
		c->next = contexts[hash];
		contexts[hash] = c;

		c->cntx1 = cntx1;	c->cntx2 = cntx2;

		c->pred = value;
	} else {
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -