00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00059 #ifdef __GNUG__
00060 #pragma implementation
00061 #endif
00062
00063 #include "arithcodec.h"
00064
00065
00073 #define OUTPUT_BIT(b) \
00074 { \
00075 outBuffer <<= 1; \
00076 if (b) \
00077 outBuffer |= 1; \
00078 outBitsToGo--; \
00079 if (outBitsToGo == 0) \
00080 { \
00081 outputDevice->putChar(outBuffer); \
00082 numberOfBytes++; \
00083 outBitsToGo = BYTE_SIZE; \
00084 outBuffer = 0; \
00085 } \
00086 }
00087
00088
00089
00097 #define UNGET_BIT(b) \
00098 { \
00099 inBitPtr <<= 1; \
00100 \
00101 if (inBitPtr == 0) \
00102 inBitPtr = 1; \
00103 \
00104 \
00105 inBuffer = inBuffer & (inBitPtr - 1); \
00106 if (b) \
00107 \
00108 inBuffer |= inBitPtr; \
00109 }
00110
00111
00112
00121 #define ADD_NEXT_INPUT_BIT(v, garbageBits) \
00122 { \
00123 if (inBitPtr == 0) \
00124 { \
00125 if (inputDevice->getChar(&inBuffer) == EndOfFile) \
00126 { \
00127 inGarbage++; \
00128 if ((FreqValue)((inGarbage-1)*8) >= garbageBits) \
00129 FATAL("Bad input file - attempted read past end of file."); \
00130 } \
00131 inBitPtr = (1<<(BYTE_SIZE-1)); \
00132 } \
00133 v <<= 1; \
00134 \
00135 if (inBuffer & inBitPtr) \
00136 v++; \
00137 \
00138 inBitPtr >>= 1; \
00139 }
00140
00141
00142
00148 #define ORIG_BIT_PLUS_FOLLOW(b) \
00149 { \
00150 OUTPUT_BIT(b); \
00151 \
00152 while (outBitsOutstanding > 0) \
00153 { \
00154 OUTPUT_BIT(!b); \
00155 outBitsOutstanding--; \
00156 } \
00157 }
00158
00159
00160 #ifdef FRUGAL_BITS
00161
00166 # define BIT_PLUS_FOLLOW(x) \
00167 { \
00168 if (ignoreFirstBit) \
00169 ignoreFirstBit = 0; \
00170 else \
00171 ORIG_BIT_PLUS_FOLLOW(x); \
00172 }
00173
00174 #else
00175
00181 # define BIT_PLUS_FOLLOW(x) ORIG_BIT_PLUS_FOLLOW(x)
00182
00183 #endif
00184
00188 #define ENCODE_RENORMALISE \
00189 { \
00190 while (out_R <= Quarter) \
00191 { \
00192 if (out_L >= Half) \
00193 { \
00194 BIT_PLUS_FOLLOW(1); \
00195 out_L -= Half; \
00196 } \
00197 else \
00198 if (out_L+out_R <= Half) \
00199 { \
00200 BIT_PLUS_FOLLOW(0); \
00201 } \
00202 else \
00203 { \
00204 outBitsOutstanding++; \
00205 out_L -= Quarter; \
00206 } \
00207 out_L <<= 1; \
00208 out_R <<= 1; \
00209 } \
00210 }
00211
00212
00213 #ifdef FRUGAL_BITS
00214
00218 # define DECODE_RENORMALISE \
00219 { \
00220 while (in_R <= Quarter) \
00221 { \
00222 in_R <<= 1; \
00223 in_V <<= 1; \
00224 ADD_NEXT_INPUT_BIT(in_D,B_BITS); \
00225 if (in_D & 1) \
00226 in_V++; \
00227 } \
00228 }
00229
00230 #else
00231
00235 # define DECODE_RENORMALISE \
00236 { \
00237 while (in_R <= Quarter) \
00238 { \
00239 in_R <<= 1; \
00240 ADD_NEXT_INPUT_BIT(in_D,0); \
00241 } \
00242 }
00243
00244 #endif
00245
00246
00247
00251 ArithCodec::ArithCodec(void)
00252 : ArithCodecBase()
00253 {
00254 outputDevice = 0;
00255
00256
00257 #ifdef FRUGAL_BITS
00258 ignoreFirstBit = 1;
00259 firstMessage = 1;
00260 #endif
00261
00262 numberOfBytes = 0;
00263
00264 inBuffer = 0;
00265 inBitPtr = 0;
00266 inGarbage = 0;
00267
00268 outBuffer = 0;
00269 outBitsToGo = 0;
00270 }
00271
00272
00273
00274
00278 void ArithCodec::startOutputtingBits(void)
00279 {
00280 outBuffer = 0;
00281 outBitsToGo = BYTE_SIZE;
00282 }
00283
00287 void ArithCodec::startInputtingBits(void)
00288 {
00289 inGarbage = 0;
00290 inBitPtr = 0;
00291 }
00292
00293
00294
00298 void ArithCodec::doneOutputtingBits(void)
00299 {
00300 if (outBitsToGo != BYTE_SIZE)
00301 {
00302 outputDevice->putChar(outBuffer << outBitsToGo);
00303 numberOfBytes++;
00304 }
00305 outBitsToGo = BYTE_SIZE;
00306 }
00307
00311 void ArithCodec::doneInputtingBits(void)
00312 {
00313 inBitPtr = 0;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00377 void ArithCodec::arithmeticEncode(FreqValue low, FreqValue high, FreqValue total)
00378 {
00379 CodeValue temp;
00380
00381 #ifdef MULT_DIV
00382 {
00383 DivValue out_r;
00384 out_r = out_R/total;
00385 temp = out_r*low;
00386 out_L += temp;
00387 if (high < total)
00388 out_R = out_r*(high-low);
00389 else
00390 out_R -= temp;
00391
00392
00393 }
00394 #else
00395 {
00396 CodeValue A, M;
00397 CodeValue temp2;
00398
00399
00400
00401
00402
00403 A = out_R;
00404 temp = 0;
00405 temp2 = 0;
00406
00407 M = total << (B_BITS - F_BITS - 1);
00408 if (A >= M) { A -= M; temp += low; temp2 += high; }
00409
00410 #define UNROLL_NUM B_BITS - F_BITS - 1
00411 #define UNROLL_CODE \
00412 A <<= 1; temp <<= 1; temp2 <<= 1; \
00413 if (A >= M) \
00414 { \
00415 A -= M; temp += low; temp2 += high; \
00416 }
00417
00418 #include "unroll.h"
00419
00420 out_L += temp;
00421 if (high < total)
00422 out_R = temp2 - temp;
00423 else
00424 out_R -= temp;
00425 }
00426 #endif
00427
00428 ENCODE_RENORMALISE;
00429
00430 if (outBitsOutstanding > MAX_BITS_OUTSTANDING)
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 FATAL("Bits_outstanding limit reached - File too large!");
00442 }
00443
00444
00445
00471 FreqValue ArithCodec::arithmeticDecodeTarget(FreqValue total)
00472 {
00473 FreqValue target;
00474
00475 #ifdef MULT_DIV
00476 in_r = in_R/total;
00477 target = (in_D)/in_r;
00478 #else
00479 {
00480 CodeValue A, M;
00481
00482
00483 A = in_R;
00484 in_r = 0;
00485
00486 M = total << ( B_BITS - F_BITS - 1 );
00487 if (A >= M) { A -= M; in_r++; }
00488
00489 #define UNROLL_NUM B_BITS - F_BITS - 1
00490 #define UNROLL_CODE \
00491 A <<= 1; in_r <<= 1; \
00492 if (A >= M) \
00493 { \
00494 A -= M; in_r++; \
00495 }
00496
00497 #include "unroll.h"
00498
00499 A = in_D;
00500 target = 0;
00501 if (in_r < (1 << (B_BITS - F_BITS - 1)))
00502 { M = in_r << F_BITS;
00503 if (A >= M) { A -= M; target++; }
00504 A <<= 1; target <<= 1;
00505 }
00506 else
00507 {
00508 M = in_r << (F_BITS - 1);
00509 }
00510
00511 if (A >= M) { A -= M; target++; }
00512
00513
00514 #define UNROLL_NUM F_BITS - 1
00515 #define UNROLL_CODE \
00516 A <<= 1; target <<= 1; \
00517 if (A >= M) \
00518 { \
00519 A -= M; target++; \
00520 }
00521
00522 #include "unroll.h"
00523
00524 }
00525 #endif //shifts vs multiply
00526
00527 return (target >= total ? total-1 : target);
00528 }
00529
00530
00531
00551 void ArithCodec::arithmeticDecode(FreqValue low, FreqValue high, FreqValue total)
00552 {
00553 CodeValue temp;
00554
00555 #ifdef MULT_DIV
00556
00557 temp = in_r*low;
00558 in_D -= temp;
00559 if (high < total)
00560 in_R = in_r*(high-low);
00561 else
00562 in_R -= temp;
00563 #else
00564 {
00565 CodeValue temp2, M;
00566
00567
00568 temp = 0;
00569 temp2 = 0;
00570
00571 M = in_r << F_BITS;
00572
00573 if (M & Half) { temp += low; temp2 += high; }
00574
00575 #define UNROLL_NUM B_BITS - F_BITS - 1
00576 #define UNROLL_CODE \
00577 M <<= 1; temp <<= 1; temp2 <<= 1; \
00578 if (M & Half) \
00579 { \
00580 temp += low; temp2 += high; \
00581 }
00582
00583 #include "unroll.h"
00584
00585
00586 in_D -= temp;
00587 if (high < total)
00588 in_R = temp2 - temp;
00589 else
00590 in_R -= temp;
00591 }
00592 #endif //shifts vs multiply
00593
00594 DECODE_RENORMALISE;
00595 }
00596
00597
00598
00602 void ArithCodec::startEncode(void)
00603 {
00604 out_L = 0;
00605 out_R = Half;
00606 outBitsOutstanding = 0;
00607 #ifdef FRUGAL_BITS
00608 ignoreFirstBit = 1;
00609 #endif
00610 }
00611
00612
00613
00614 #ifdef FRUGAL_BITS
00615
00620 void ArithCodec::finishEncode(void)
00621 {
00622 unsigned int nbits, i;
00623 CodeValue roundup, bits, value;
00624
00625 bits = 0;
00626 nbits = 0;
00627
00628 for (nbits = 1; nbits <= B_BITS; nbits++)
00629 {
00630 roundup = (1 << (B_BITS - nbits)) - 1;
00631 bits = (out_L + roundup) >> (B_BITS - nbits);
00632 value = bits << (B_BITS - nbits);
00633 if (out_L <= value && value + roundup <= (out_L + (out_R - 1)) )
00634 break;
00635 }
00636 for (i = 1; i <= nbits; i++)
00637
00638 BIT_PLUS_FOLLOW(((bits >> (nbits-i)) & 1));
00639 }
00640 #else
00641
00642
00647 void ArithCodec::finishEncode(void)
00648 {
00649 int nbits, i;
00650 CodeValue bits;
00651
00652 nbits = B_BITS;
00653 bits = out_L;
00654 for (i = 1; i <= nbits; i++)
00655
00656 BIT_PLUS_FOLLOW(((bits >> (nbits-i)) & 1));
00657 }
00658 #endif
00659
00660
00668 void ArithCodec::startDecode(void)
00669 {
00670 unsigned int i;
00671
00672 in_D = 0;
00673 in_R = Half;
00674
00675 #ifdef FRUGAL_BITS
00676 {
00677
00678 if (firstMessage)
00679 {
00680 for (i = 0; i < B_BITS-1; i++)
00681 ADD_NEXT_INPUT_BIT(in_D, B_BITS);
00682 }
00683 else
00684 {
00685 in_D = retrieveExcessInputBits();
00686 UNGET_BIT(in_D & 1);
00687 in_D >>=1;
00688 }
00689
00690 firstMessage = 0;
00691 in_V = in_D;
00692 }
00693 #else
00694 for (i = 0; i<B_BITS; i++)
00695 ADD_NEXT_INPUT_BIT(in_D, 0);
00696 #endif
00697
00698 if (in_D >= Half)
00699 FATAL("Corrupt input file.");
00700 }
00701
00702 #ifdef FRUGAL_BITS
00703
00708 void ArithCodec::finishDecode(void)
00709 {
00710 unsigned int nbits, i;
00711 CodeValue roundup, bits, value;
00712 CodeValue in_L;
00713
00714
00715
00716 in_L = (in_V & (Half-1))+ Half - in_D;
00717
00718 for (nbits = 1; nbits <= B_BITS; nbits++)
00719 {
00720 roundup = (1 << (B_BITS - nbits)) - 1;
00721 bits = (in_L + roundup) >> (B_BITS - nbits);
00722 value = bits << (B_BITS - nbits);
00723 if (in_L <= value && value + roundup <= (in_L + (in_R - 1)) )
00724 break;
00725 }
00726
00727
00728 if (nbits > B_BITS)
00729 return;
00730 else
00731 for (i = 1; i <= nbits; i++)
00732 {
00733 ADD_NEXT_INPUT_BIT(in_V, B_BITS);
00734 }
00735 }
00736
00742 CodeValue ArithCodec::retrieveExcessInputBits(void)
00743 {
00744 return (in_V & (Half + (Half-1)) );
00745 }
00746
00747 #else
00748
00752 void ArithCodec::finishDecode(void)
00753 {
00754
00755 }
00756 #endif
00757
00758 size_t ArithCodec::numberOfOutputBytes(void)
00759 {
00760 return numberOfBytes;
00761 }