precomp-cpp/contrib/packmp3/huffmp3.cpp

348 lines
8.2 KiB
C++

#include <stdlib.h>
#include <string.h>
#include "../packjpg/bitops.h"
#include "huffmp3.h"
// bit buffer size - careful changing this!
// should not be smaller than 8 or HWIDTH_MAX
#define BIT_BUFFER_SIZE 16
/* -----------------------------------------------
small values quadruple conversion table (abs)
----------------------------------------------- */
static const unsigned char sv_qconv_abs[ 16 ][ 4 ] = {
{ 0, 0, 0, 0 }, // 0000 -> 0/0/0/0
{ 0, 0, 0, 1 }, // 0001 -> 0/0/0/1
{ 0, 0, 1, 0 }, // 0010 -> 0/0/1/0
{ 0, 0, 1, 1 }, // 0011 -> 0/0/1/1
{ 0, 1, 0, 0 }, // 0100 -> 0/1/0/0
{ 0, 1, 0, 1 }, // 0101 -> 0/1/0/1
{ 0, 1, 1, 0 }, // 0110 -> 0/1/1/0
{ 0, 1, 1, 1 }, // 0111 -> 0/1/1/1
{ 1, 0, 0, 0 }, // 1000 -> 1/0/0/0
{ 1, 0, 0, 1 }, // 1001 -> 1/0/0/1
{ 1, 0, 1, 0 }, // 1010 -> 1/0/1/0
{ 1, 0, 1, 1 }, // 1011 -> 1/0/1/1
{ 1, 1, 0, 0 }, // 1100 -> 1/1/0/0
{ 1, 1, 0, 1 }, // 1101 -> 1/1/0/1
{ 1, 1, 1, 0 }, // 1110 -> 1/1/1/0
{ 1, 1, 1, 1 }, // 1111 -> 1/1/1/1
};
/* -----------------------------------------------
constructor for huffman reader class
----------------------------------------------- */
huffman_reader::huffman_reader( unsigned char* data, int size )
{
// WARNING: NO error checks in this class!
// init bitreader
bit_reader = new abitreader( data, size );
// fill the bit buffer for the first time
bit_buffer = bit_reader->read( BIT_BUFFER_SIZE );
// set count zero
count = 0;
}
/* -----------------------------------------------
destructor for huffman reader class
----------------------------------------------- */
huffman_reader::~huffman_reader( void )
{
// close bitreader
delete( bit_reader );
}
/* -----------------------------------------------
decode one big value pair
----------------------------------------------- */
void huffman_reader::decode_pair( huffman_conv_set* table, unsigned char* vals )
{
huffman_conv* conv;
int ext;
for ( ext = 0; ext != -1; ext = conv->ext ) {
conv = (table+ext)->h + ( bit_buffer >> ( BIT_BUFFER_SIZE - (table+ext)->hwidth ) );
advance_bitstream( conv->len );
}
vals[ 0 ] = conv->v0;
vals[ 1 ] = conv->v1;
}
/* -----------------------------------------------
decode one small value quadruple
----------------------------------------------- */
void huffman_reader::decode_quadruple( huffman_conv_set* table, unsigned char* vals )
{
huffman_conv* conv;
conv = table->h + ( bit_buffer >> ( BIT_BUFFER_SIZE - table->hwidth ) );
advance_bitstream( conv->len );
memcpy( vals, sv_qconv_abs[ conv->v0 ], sizeof( char ) * 4 );
}
/* -----------------------------------------------
bit reader function for n bit
----------------------------------------------- */
unsigned int huffman_reader::read_bits( int n )
{
unsigned int bits;
// read bits
bits = ( n <= BIT_BUFFER_SIZE ) ?
bit_buffer >> (BIT_BUFFER_SIZE-n) :
( bit_buffer << (n-BIT_BUFFER_SIZE) ) | bit_reader->read( (n-BIT_BUFFER_SIZE) );
// refill the buffer
advance_bitstream( n );
return bits;
}
/* -----------------------------------------------
bit reader function for one bit
----------------------------------------------- */
unsigned char huffman_reader::read_bit( void )
{
unsigned char bit;
// read one bit
bit = bit_buffer >> (BIT_BUFFER_SIZE-1);
// refill the buffer
advance_bitstream_1();
return bit;
}
/* -----------------------------------------------
reset the internal bit counter
----------------------------------------------- */
void huffman_reader::reset_counter( void )
{
count = 0;
}
/* -----------------------------------------------
get the internal bit count
----------------------------------------------- */
int huffman_reader::get_count( void )
{
return count;
}
/* -----------------------------------------------
rewind n bits
----------------------------------------------- */
void huffman_reader::rewind_bits( int n )
{
// rewind n bits
bit_reader->rewind_bits( n + BIT_BUFFER_SIZE );
// fill the bit buffer
bit_buffer = bit_reader->read( BIT_BUFFER_SIZE );
// set back the counter
count = ( count > n ) ? count - n : 0;
}
/* -----------------------------------------------
set position in stream
----------------------------------------------- */
void huffman_reader::setpos( int pbyte, int pbit )
{
// reposition the bit reader
bit_reader->setpos( pbyte, pbit );
// fill the bit buffer
bit_buffer = bit_reader->read( BIT_BUFFER_SIZE );
}
/* -----------------------------------------------
return current byte position
----------------------------------------------- */
int huffman_reader::getpos( void )
{
// ugly, but it works!
return bit_reader->getpos() - ( BIT_BUFFER_SIZE + ( 8 - bit_reader->getbitp() ) ) / 8;
}
/* -----------------------------------------------
refill bit buffer utility function
----------------------------------------------- */
inline void huffman_reader::advance_bitstream( int n )
{
// refill the buffer
bit_buffer = ( n >= BIT_BUFFER_SIZE ) ?
bit_reader->read( BIT_BUFFER_SIZE ) :
( ( bit_buffer << n ) | bit_reader->read( n ) ) & ( ( 1 << BIT_BUFFER_SIZE ) - 1 );
// record # of bits read
count += n;
}
/* -----------------------------------------------
refill bit buffer utility function (1 bit)
----------------------------------------------- */
inline void huffman_reader::advance_bitstream_1( void )
{
// refill the buffer
bit_buffer = ( ( bit_buffer << 1 ) | bit_reader->read_bit() ) &
( ( 1 << BIT_BUFFER_SIZE ) - 1 );
// increment counter
count++;
}
/* -----------------------------------------------
constructor for huffman writer class
----------------------------------------------- */
huffman_writer::huffman_writer( int adds )
{
// WARNING: NO error checks in this class!
// init bitwriter - recommended value: 5MB
if ( adds == 0 ) adds = 5 * 1024 * 1024;
bit_writer = new abitwriter( adds );
// set count zero
count = 0;
}
/* -----------------------------------------------
destructor for huffman writer class
----------------------------------------------- */
huffman_writer::~huffman_writer( void )
{
// close bitwriter
delete( bit_writer );
}
/* -----------------------------------------------
encode one big value pair
----------------------------------------------- */
void huffman_writer::encode_pair( huffman_code** hcodes, unsigned char* vals )
{
huffman_code* hcode;
// find correct code, encode absvals and signs
hcode = &hcodes[vals[0]][vals[1]];
write_bits( hcode->code, hcode->len );
}
/* -----------------------------------------------
encode one small value quadruple
----------------------------------------------- */
void huffman_writer::encode_quadruple( huffman_code* hcode, unsigned char* vals )
{
int bits = 0;
int i;
// build bits unit
for ( i = 0; i < 4; i++ ) {
bits = bits << 1;
if ( vals[i] ) bits |= 1;
}
// encode vals
hcode += bits;
write_bits( hcode->code, hcode->len );
}
/* -----------------------------------------------
bit writer function for n bit
----------------------------------------------- */
void huffman_writer::write_bits( unsigned int bits, int n )
{
// write bits
bit_writer->write( bits, n );
// take count
count += n;
}
/* -----------------------------------------------
bit writer function for 1 bit
----------------------------------------------- */
void huffman_writer::write_bit( unsigned char bit )
{
// write bit
bit_writer->write_bit( bit );
// increment counter
count++;
}
/* -----------------------------------------------
reset the internal bit counter
----------------------------------------------- */
void huffman_writer::reset_counter( void )
{
count = 0;
}
/* -----------------------------------------------
get the internal bit count
----------------------------------------------- */
int huffman_writer::get_count( void )
{
return count;
}
/* -----------------------------------------------
return data pointer (when finished)
----------------------------------------------- */
unsigned char* huffman_writer::getptr( void )
{
return bit_writer->getptr();
}
/* -----------------------------------------------
return current byte position
----------------------------------------------- */
int huffman_writer::getpos( void )
{
return bit_writer->getpos();
}