00001 #include "CSource.h" 00002 /**************************************************************************** 00003 * This file is part of PPMd project * 00004 * Contents: 'Carryless rangecoder' by Dmitry Subbotin * 00005 * Comments: this implementation is claimed to be a public domain * 00006 ****************************************************************************/ 00007 /********************** Original text ************************************* 00009 00010 typedef unsigned int uint; 00011 typedef unsigned char uc; 00012 00013 #define DO(n) for (int _=0; _<n; _++) 00014 #define TOP (1<<24) 00015 #define BOT (1<<16) 00016 00017 00018 class RangeCoder 00019 { 00020 uint low, code, range, passed; 00021 FILE *f; 00022 00023 void OutByte (uc c) { passed++; fputc(c,f); } 00024 uc InByte () { passed++; return fgetc(f); } 00025 00026 public: 00027 00028 uint GetPassed () { return passed; } 00029 void StartEncode (FILE *F) { f=F; passed=low=0; range= (uint) -1; } 00030 void FinishEncode () { DO(4) OutByte(low>>24), low<<=8; } 00031 void StartDecode (FILE *F) { passed=low=code=0; range= (uint) -1; 00032 f=F; DO(4) code= code<<8 | InByte(); 00033 } 00034 00035 void Encode (uint cumFreq, uint freq, uint totFreq) { 00036 assert(cumFreq+freq<totFreq && freq && totFreq<=BOT); 00037 low += cumFreq * (range/= totFreq); 00038 range*= freq; 00039 while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1)) 00040 OutByte(low>>24), range<<=8, low<<=8; 00041 } 00042 00043 uint GetFreq (uint totFreq) { 00044 uint tmp= (code-low) / (range/= totFreq); 00045 if (tmp >= totFreq) throw ("Input data corrupt"); // or force it to return 00046 return tmp; // a valid value :) 00047 } 00048 00049 void Decode (uint cumFreq, uint freq, uint totFreq) { 00050 assert(cumFreq+freq<totFreq && freq && totFreq<=BOT); 00051 low += cumFreq*range; 00052 range*= freq; 00053 while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1)) 00054 code= code<<8 | InByte(), range<<=8, low<<=8; 00055 } 00056 }; 00057 *****************************************************************************/ 00058 00059 static struct SUBRANGE { 00060 DWORD LowCount, HighCount, scale; 00061 } SubRange; 00062 enum { TOP=1 << 24, BOT=1 << 15 }; 00063 static DWORD low, code, range; 00064 00065 inline void ariInitEncoder() 00066 { 00067 low=0; range=DWORD(-1); 00068 } 00069 #define ARI_ENC_NORMALIZE(stream) { \ 00070 while ((low ^ (low+range)) < TOP || range < BOT && \ 00071 ((range= -low & (BOT-1)),1)) { \ 00072 _PPMD_E_PUTC(low >> 24,stream); \ 00073 range <<= 8; low <<= 8; \ 00074 } \ 00075 } 00076 inline void ariEncodeSymbol() 00077 { 00078 low += SubRange.LowCount*(range /= SubRange.scale); 00079 range *= SubRange.HighCount-SubRange.LowCount; 00080 } 00081 inline void ariShiftEncodeSymbol(UINT SHIFT) 00082 { 00083 low += SubRange.LowCount*(range >>= SHIFT); 00084 range *= SubRange.HighCount-SubRange.LowCount; 00085 } 00086 #define ARI_FLUSH_ENCODER(stream) { \ 00087 for (UINT i=0;i < 4;i++) { \ 00088 _PPMD_E_PUTC(low >> 24,stream); low <<= 8; \ 00089 } \ 00090 } 00091 #define ARI_INIT_DECODER(stream) { \ 00092 low=code=0; range=DWORD(-1); \ 00093 for (UINT i=0;i < 4;i++) \ 00094 code=(code << 8) | _PPMD_D_GETC(stream); \ 00095 } 00096 #define ARI_DEC_NORMALIZE(stream) { \ 00097 while ((low ^ (low+range)) < TOP || range < BOT && \ 00098 ((range= -low & (BOT-1)),1)) { \ 00099 code=(code << 8) | _PPMD_D_GETC(stream); \ 00100 range <<= 8; low <<= 8; \ 00101 } \ 00102 } 00103 inline UINT ariGetCurrentCount() { 00104 return (code-low)/(range /= SubRange.scale); 00105 } 00106 inline UINT ariGetCurrentShiftCount(UINT SHIFT) { 00107 return (code-low)/(range >>= SHIFT); 00108 } 00109 inline void ariRemoveSubrange() 00110 { 00111 low += range*SubRange.LowCount; 00112 range *= SubRange.HighCount-SubRange.LowCount; 00113 }
1.4.2