-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcoder.cpp
97 lines (87 loc) · 3.2 KB
/
coder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <fstream>
#include "coder.h"
unsigned int coder::splitrange( float prediction ) {
unsigned int range = (unsigned int)((high - low) * prediction) + low;
if ( high <= range ) range = high - 1;
if ( low >= range ) range = low + 1;
return range;
}
void coder::shiftup() {
low = (low & 0x7FFFFFFF) << 1;
high = ((high & 0x7FFFFFFF) << 1) | 1;
}
unsigned int coder::inputbit() {
static unsigned int bitpos = 8;
static unsigned int byte;
if ( bitpos == 8 ) {
if ( !std::cin.read( (char*)&byte, 1 ) ) return EOF;
bitpos = 0;
}
++bitpos;
byte = byte << 1;
return (byte & 0x100) >> 8;
}
void coder::outputbit( unsigned int bit ) {
static unsigned int bitpos = 0;
static unsigned int byte = 0;
++bitpos;
byte = (byte << 1) | bit;
if ( bitpos == 8 ) {
std::cout.write( (char*)&byte, 1 );
bitpos = 0;
byte = 0;
}
}
coder::coder() {
low = 0x0;
high = 0xFFFFFFFF;
}
unsigned long long coder::encode( mixer p ) {
unsigned long long bitsread = 0;
unsigned long long bitswritten = 0;
for ( int bit = inputbit(); bit != EOF; bit = inputbit() ) {
unsigned int cur = splitrange( p.get_prediction() );
bit ? low = cur + 1 : high = cur;
p.model( bit );
while ( ((~high) ^ low) & 0x80000000 ) {
outputbit( (high & 0x80000000) >> 31 );
shiftup();
++bitswritten;
}
if ( bitsread % 101020 == 0 ) std::cerr << "\r" << bitsread/8 << " bytes read and " << bitswritten/8 << " bytes written ratio = " << ((float)(bitswritten+1))/((float)(bitsread+1));
++bitsread;
}
for ( int i=0; i<32; ++i ) {
outputbit( (high & 0x80000000) >> 31 );
shiftup();
}
std::cerr << "\r" << bitsread/8 << " bytes read and " << bitswritten/8 << " bytes written ratio = " << ((float)(bitswritten+1))/((float)(bitsread+1)) << std::endl;
return bitsread/8;
}
void coder::decode( mixer p, unsigned long long filesize ) {
unsigned int filebits = 0;
for ( int i = 0; i < 32; ++i ) {
unsigned int input = inputbit();
input != (unsigned int)EOF ? filebits = ((filebits & 0x7FFFFFFFul) << 1ul) | input : filebits = ((filebits & 0x7FFFFFFFul) << 1ul);
}
unsigned long long bitswritten = 0;
unsigned long long bitsread = 32;
while ( bitswritten/8 < filesize ) {
unsigned int cur = splitrange( p.get_prediction() );
unsigned int bit;
filebits <= cur ? bit = 0 : bit = 1;
outputbit( bit );
bit ? low = cur + 1 : high = cur;
p.model( bit );
while ( ((~high) ^ low) & 0x80000000 ) {
unsigned int input = inputbit();
input != (unsigned int)EOF ? filebits = ((filebits & 0x7FFFFFFF) << 1) | input : filebits = ((filebits & 0x7FFFFFFF) << 1);
shiftup();
++bitsread;
}
if ( bitswritten % 100113 == 0 ) std::cerr << "\r" << bitsread/8 << " bytes read and " << bitswritten/8 << " bytes written ratio = " << (float)bitswritten/(float)bitsread;
++bitswritten;
}
std::cerr << "\r" << bitsread/8 << " bytes read and " << bitswritten/8 << " bytes written" << std::endl;
}