mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
upgrade libchdr
This commit is contained in:
parent
e5fdc50812
commit
d41ea34d6b
@ -1,5 +1,6 @@
|
|||||||
// license:BSD-3-Clause
|
/* license:BSD-3-Clause
|
||||||
// copyright-holders:Aaron Giles
|
* copyright-holders:Aaron Giles
|
||||||
|
*/
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
bitstream.c
|
bitstream.c
|
||||||
@ -11,15 +12,17 @@
|
|||||||
#include "bitstream.h"
|
#include "bitstream.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
//**************************************************************************
|
/***************************************************************************
|
||||||
// INLINE FUNCTIONS
|
* INLINE FUNCTIONS
|
||||||
//**************************************************************************
|
***************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
int bitstream_overflow(struct bitstream* bitstream) { return ((bitstream->doffset - bitstream->bits / 8) > bitstream->dlength); }
|
int bitstream_overflow(struct bitstream* bitstream) { return ((bitstream->doffset - bitstream->bits / 8) > bitstream->dlength); }
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// create_bitstream - constructor
|
* create_bitstream - constructor
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
struct bitstream* create_bitstream(const void *src, uint32_t srclength)
|
struct bitstream* create_bitstream(const void *src, uint32_t srclength)
|
||||||
{
|
{
|
||||||
@ -33,17 +36,18 @@ struct bitstream* create_bitstream(const void *src, uint32_t srclength)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------
|
/*-----------------------------------------------------
|
||||||
// bitstream_peek - fetch the requested number of bits
|
* bitstream_peek - fetch the requested number of bits
|
||||||
// but don't advance the input pointer
|
* but don't advance the input pointer
|
||||||
//-----------------------------------------------------
|
*-----------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t bitstream_peek(struct bitstream* bitstream, int numbits)
|
uint32_t bitstream_peek(struct bitstream* bitstream, int numbits)
|
||||||
{
|
{
|
||||||
if (numbits == 0)
|
if (numbits == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// fetch data if we need more
|
/* fetch data if we need more */
|
||||||
if (numbits > bitstream->bits)
|
if (numbits > bitstream->bits)
|
||||||
{
|
{
|
||||||
while (bitstream->bits <= 24)
|
while (bitstream->bits <= 24)
|
||||||
@ -55,15 +59,16 @@ uint32_t bitstream_peek(struct bitstream* bitstream, int numbits)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the data
|
/* return the data */
|
||||||
return bitstream->buffer >> (32 - numbits);
|
return bitstream->buffer >> (32 - numbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------
|
/*-----------------------------------------------------
|
||||||
// bitstream_remove - advance the input pointer by the
|
* bitstream_remove - advance the input pointer by the
|
||||||
// specified number of bits
|
* specified number of bits
|
||||||
//-----------------------------------------------------
|
*-----------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void bitstream_remove(struct bitstream* bitstream, int numbits)
|
void bitstream_remove(struct bitstream* bitstream, int numbits)
|
||||||
{
|
{
|
||||||
@ -72,9 +77,10 @@ void bitstream_remove(struct bitstream* bitstream, int numbits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------
|
/*-----------------------------------------------------
|
||||||
// bitstream_read - fetch the requested number of bits
|
* bitstream_read - fetch the requested number of bits
|
||||||
//-----------------------------------------------------
|
*-----------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t bitstream_read(struct bitstream* bitstream, int numbits)
|
uint32_t bitstream_read(struct bitstream* bitstream, int numbits)
|
||||||
{
|
{
|
||||||
@ -84,9 +90,10 @@ uint32_t bitstream_read(struct bitstream* bitstream, int numbits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// read_offset - return the current read offset
|
* read_offset - return the current read offset
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t bitstream_read_offset(struct bitstream* bitstream)
|
uint32_t bitstream_read_offset(struct bitstream* bitstream)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// license:BSD-3-Clause
|
/* license:BSD-3-Clause
|
||||||
// copyright-holders:Aaron Giles
|
* copyright-holders:Aaron Giles
|
||||||
/***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
bitstream.h
|
bitstream.h
|
||||||
|
|
||||||
@ -15,18 +15,19 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
//**************************************************************************
|
/***************************************************************************
|
||||||
// TYPE DEFINITIONS
|
* TYPE DEFINITIONS
|
||||||
//**************************************************************************
|
***************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
// helper class for reading from a bit buffer
|
/* helper class for reading from a bit buffer */
|
||||||
struct bitstream
|
struct bitstream
|
||||||
{
|
{
|
||||||
uint32_t buffer; // current bit accumulator
|
uint32_t buffer; /* current bit accumulator */
|
||||||
int bits; // number of bits in the accumulator
|
int bits; /* number of bits in the accumulator */
|
||||||
const uint8_t * read; // read pointer
|
const uint8_t * read; /* read pointer */
|
||||||
uint32_t doffset; // byte offset within the data
|
uint32_t doffset; /* byte offset within the data */
|
||||||
uint32_t dlength; // length of the data
|
uint32_t dlength; /* length of the data */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bitstream* create_bitstream(const void *src, uint32_t srclength);
|
struct bitstream* create_bitstream(const void *src, uint32_t srclength);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
schemes will differ after track 1!
|
schemes will differ after track 1!
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#ifdef WANT_RAW_DATA_SECTOR
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -307,7 +308,7 @@ static const uint16_t qoffsets[ECC_Q_NUM_BYTES][ECC_Q_COMP] =
|
|||||||
// particular to a mode
|
// particular to a mode
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
static uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
|
static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
|
||||||
{
|
{
|
||||||
// in mode 2 always treat these as 0 bytes
|
// in mode 2 always treat these as 0 bytes
|
||||||
return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
|
return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
|
||||||
@ -329,9 +330,8 @@ static uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
|
|||||||
|
|
||||||
void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t *val1, uint8_t *val2)
|
void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t *val1, uint8_t *val2)
|
||||||
{
|
{
|
||||||
int component;
|
|
||||||
*val1 = *val2 = 0;
|
*val1 = *val2 = 0;
|
||||||
for (component = 0; component < rowlen; component++)
|
for (int component = 0; component < rowlen; component++)
|
||||||
{
|
{
|
||||||
*val1 ^= ecc_source_byte(sector, row[component]);
|
*val1 ^= ecc_source_byte(sector, row[component]);
|
||||||
*val2 ^= ecc_source_byte(sector, row[component]);
|
*val2 ^= ecc_source_byte(sector, row[component]);
|
||||||
@ -355,10 +355,8 @@ void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, u
|
|||||||
|
|
||||||
int ecc_verify(const uint8_t *sector)
|
int ecc_verify(const uint8_t *sector)
|
||||||
{
|
{
|
||||||
int byte;
|
|
||||||
|
|
||||||
// first verify P bytes
|
// first verify P bytes
|
||||||
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
|
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
|
||||||
{
|
{
|
||||||
uint8_t val1, val2;
|
uint8_t val1, val2;
|
||||||
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &val1, &val2);
|
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &val1, &val2);
|
||||||
@ -367,7 +365,7 @@ int ecc_verify(const uint8_t *sector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then verify Q bytes
|
// then verify Q bytes
|
||||||
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
|
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
|
||||||
{
|
{
|
||||||
uint8_t val1, val2;
|
uint8_t val1, val2;
|
||||||
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &val1, &val2);
|
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &val1, &val2);
|
||||||
@ -390,13 +388,12 @@ int ecc_verify(const uint8_t *sector)
|
|||||||
|
|
||||||
void ecc_generate(uint8_t *sector)
|
void ecc_generate(uint8_t *sector)
|
||||||
{
|
{
|
||||||
int byte;
|
|
||||||
// first verify P bytes
|
// first verify P bytes
|
||||||
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
|
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
|
||||||
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, §or[ECC_P_OFFSET + byte], §or[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
|
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, §or[ECC_P_OFFSET + byte], §or[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
|
||||||
|
|
||||||
// then verify Q bytes
|
// then verify Q bytes
|
||||||
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
|
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
|
||||||
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, §or[ECC_Q_OFFSET + byte], §or[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
|
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, §or[ECC_Q_OFFSET + byte], §or[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,3 +412,5 @@ void ecc_clear(uint8_t *sector)
|
|||||||
memset(§or[ECC_P_OFFSET], 0, 2 * ECC_P_NUM_BYTES);
|
memset(§or[ECC_P_OFFSET], 0, 2 * ECC_P_NUM_BYTES);
|
||||||
memset(§or[ECC_Q_OFFSET], 0, 2 * ECC_Q_NUM_BYTES);
|
memset(§or[ECC_Q_OFFSET], 0, 2 * ECC_Q_NUM_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* WANT_RAW_DATA_SECTOR */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// license:BSD-3-Clause
|
/* license:BSD-3-Clause */
|
||||||
// copyright-holders:Aaron Giles
|
/* copyright-holders:Aaron Giles */
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
cdrom.h
|
cdrom.h
|
||||||
@ -15,14 +15,13 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <retro_inline.h>
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
CONSTANTS
|
CONSTANTS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// tracks are padded to a multiple of this many frames
|
/* tracks are padded to a multiple of this many frames */
|
||||||
extern const uint32_t CD_TRACK_PADDING;
|
#define CD_TRACK_PADDING (4)
|
||||||
|
|
||||||
#define CD_MAX_TRACKS (99) /* AFAIK the theoretical limit */
|
#define CD_MAX_TRACKS (99) /* AFAIK the theoretical limit */
|
||||||
#define CD_MAX_SECTOR_DATA (2352)
|
#define CD_MAX_SECTOR_DATA (2352)
|
||||||
@ -61,48 +60,11 @@ enum
|
|||||||
FUNCTION PROTOTYPES
|
FUNCTION PROTOTYPES
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// ECC utilities
|
#ifdef WANT_RAW_DATA_SECTOR
|
||||||
|
/* ECC utilities */
|
||||||
int ecc_verify(const uint8_t *sector);
|
int ecc_verify(const uint8_t *sector);
|
||||||
void ecc_generate(uint8_t *sector);
|
void ecc_generate(uint8_t *sector);
|
||||||
void ecc_clear(uint8_t *sector);
|
void ecc_clear(uint8_t *sector);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CDROM_H__ */
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
INLINE FUNCTIONS
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static INLINE uint32_t msf_to_lba(uint32_t msf)
|
|
||||||
{
|
|
||||||
return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE uint32_t lba_to_msf(uint32_t lba)
|
|
||||||
{
|
|
||||||
uint8_t m, s, f;
|
|
||||||
|
|
||||||
m = lba / (60 * 75);
|
|
||||||
lba -= m * (60 * 75);
|
|
||||||
s = lba / 75;
|
|
||||||
f = lba % 75;
|
|
||||||
|
|
||||||
return ((m / 10) << 20) | ((m % 10) << 16) |
|
|
||||||
((s / 10) << 12) | ((s % 10) << 8) |
|
|
||||||
((f / 10) << 4) | ((f % 10) << 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// segacd needs it like this.. investigate
|
|
||||||
// Angelo also says PCE tracks often start playing at the
|
|
||||||
// wrong address.. related?
|
|
||||||
static INLINE uint32_t lba_to_msf_alt(int lba)
|
|
||||||
{
|
|
||||||
uint32_t ret = 0;
|
|
||||||
|
|
||||||
ret |= ((lba / (60 * 75))&0xff)<<16;
|
|
||||||
ret |= (((lba / 75) % 60)&0xff)<<8;
|
|
||||||
ret |= ((lba % 75)&0xff)<<0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __CDROM_H__
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -310,9 +310,9 @@ struct _chd_header
|
|||||||
UINT64 unitcount; /* TODO V5 */
|
UINT64 unitcount; /* TODO V5 */
|
||||||
UINT32 hunkcount; /* TODO V5 */
|
UINT32 hunkcount; /* TODO V5 */
|
||||||
|
|
||||||
// map information
|
/* map information */
|
||||||
UINT32 mapentrybytes; // length of each entry in a map (V5)
|
UINT32 mapentrybytes; /* length of each entry in a map (V5) */
|
||||||
UINT8* rawmap; // raw map data
|
UINT8* rawmap; /* raw map data */
|
||||||
|
|
||||||
UINT32 obsolete_cylinders; /* obsolete field -- do not use! */
|
UINT32 obsolete_cylinders; /* obsolete field -- do not use! */
|
||||||
UINT32 obsolete_sectors; /* obsolete field -- do not use! */
|
UINT32 obsolete_sectors; /* obsolete field -- do not use! */
|
||||||
@ -341,12 +341,13 @@ struct _chd_verify_result
|
|||||||
/* ----- CHD file management ----- */
|
/* ----- CHD file management ----- */
|
||||||
|
|
||||||
/* create a new CHD file fitting the given description */
|
/* create a new CHD file fitting the given description */
|
||||||
// chd_error chd_create(const char *filename, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent);
|
/* chd_error chd_create(const char *filename, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
|
||||||
|
|
||||||
/* same as chd_create(), but accepts an already-opened core_file object */
|
/* same as chd_create(), but accepts an already-opened core_file object */
|
||||||
// chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent);
|
/* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
|
||||||
|
|
||||||
/* open an existing CHD file */
|
/* open an existing CHD file */
|
||||||
|
chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
|
||||||
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
|
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,14 +7,18 @@
|
|||||||
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
|
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
typedef uint64_t UINT64;
|
typedef uint64_t UINT64;
|
||||||
|
#ifndef OSD_CPU_H
|
||||||
typedef uint32_t UINT32;
|
typedef uint32_t UINT32;
|
||||||
typedef uint16_t UINT16;
|
typedef uint16_t UINT16;
|
||||||
typedef uint8_t UINT8;
|
typedef uint8_t UINT8;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef int64_t INT64;
|
typedef int64_t INT64;
|
||||||
|
#ifndef OSD_CPU_H
|
||||||
typedef int32_t INT32;
|
typedef int32_t INT32;
|
||||||
typedef int16_t INT16;
|
typedef int16_t INT16;
|
||||||
typedef int8_t INT8;
|
typedef int8_t INT8;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define core_file FILE
|
#define core_file FILE
|
||||||
#define core_fopen(file) fopen(file, "rb")
|
#define core_fopen(file) fopen(file, "rb")
|
||||||
@ -23,14 +27,4 @@ typedef int8_t INT8;
|
|||||||
#define core_fclose fclose
|
#define core_fclose fclose
|
||||||
#define core_ftell ftell
|
#define core_ftell ftell
|
||||||
|
|
||||||
static size_t core_fsize(core_file* f)
|
|
||||||
{
|
|
||||||
size_t rv;
|
|
||||||
size_t p = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
rv = ftell(f);
|
|
||||||
fseek(f, p, SEEK_SET);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,17 +24,10 @@ static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const F
|
|||||||
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
|
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
|
||||||
static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||||
|
|
||||||
// getters (valid after reset)
|
/*-------------------------------------------------
|
||||||
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
|
* flac_decoder - constructor
|
||||||
static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
|
*-------------------------------------------------
|
||||||
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
|
*/
|
||||||
static uint32_t total_samples(flac_decoder *decoder) { return FLAC__stream_decoder_get_total_samples(decoder->decoder); }
|
|
||||||
static FLAC__StreamDecoderState state(flac_decoder *decoder) { return FLAC__stream_decoder_get_state(decoder->decoder); }
|
|
||||||
static const char *state_string(flac_decoder *decoder) { return FLAC__stream_decoder_get_resolved_state_string(decoder->decoder); }
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// flac_decoder - constructor
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void flac_decoder_init(flac_decoder *decoder)
|
void flac_decoder_init(flac_decoder *decoder)
|
||||||
{
|
{
|
||||||
@ -52,9 +45,10 @@ void flac_decoder_init(flac_decoder *decoder)
|
|||||||
decoder->uncompressed_swap = 0;
|
decoder->uncompressed_swap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// flac_decoder - destructor
|
* flac_decoder - destructor
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void flac_decoder_free(flac_decoder* decoder)
|
void flac_decoder_free(flac_decoder* decoder)
|
||||||
{
|
{
|
||||||
@ -63,10 +57,11 @@ void flac_decoder_free(flac_decoder* decoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// reset - reset state with the original
|
* reset - reset state with the original
|
||||||
// parameters
|
* parameters
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
static int flac_decoder_internal_reset(flac_decoder* decoder)
|
static int flac_decoder_internal_reset(flac_decoder* decoder)
|
||||||
{
|
{
|
||||||
@ -86,30 +81,31 @@ static int flac_decoder_internal_reset(flac_decoder* decoder)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// reset - reset state with new memory parameters
|
* reset - reset state with new memory parameters
|
||||||
// and a custom-generated header
|
* and a custom-generated header
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length)
|
int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
// modify the template header with our parameters
|
/* modify the template header with our parameters */
|
||||||
static const uint8_t s_header_template[0x2a] =
|
static const uint8_t s_header_template[0x2a] =
|
||||||
{
|
{
|
||||||
0x66, 0x4C, 0x61, 0x43, // +00: 'fLaC' stream header
|
0x66, 0x4C, 0x61, 0x43, /* +00: 'fLaC' stream header */
|
||||||
0x80, // +04: metadata block type 0 (STREAMINFO),
|
0x80, /* +04: metadata block type 0 (STREAMINFO), */
|
||||||
// flagged as last block
|
/* flagged as last block */
|
||||||
0x00, 0x00, 0x22, // +05: metadata block length = 0x22
|
0x00, 0x00, 0x22, /* +05: metadata block length = 0x22 */
|
||||||
0x00, 0x00, // +08: minimum block size
|
0x00, 0x00, /* +08: minimum block size */
|
||||||
0x00, 0x00, // +0A: maximum block size
|
0x00, 0x00, /* +0A: maximum block size */
|
||||||
0x00, 0x00, 0x00, // +0C: minimum frame size (0 == unknown)
|
0x00, 0x00, 0x00, /* +0C: minimum frame size (0 == unknown) */
|
||||||
0x00, 0x00, 0x00, // +0F: maximum frame size (0 == unknown)
|
0x00, 0x00, 0x00, /* +0F: maximum frame size (0 == unknown) */
|
||||||
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, // +12: sample rate (0x0ac44 == 44100),
|
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
|
||||||
// numchannels (2), sample bits (16),
|
/* numchannels (2), sample bits (16), */
|
||||||
// samples in stream (0 == unknown)
|
/* samples in stream (0 == unknown) */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // +1A: MD5 signature (0 == none)
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* */
|
||||||
// +2A: start of stream data
|
/* +2A: start of stream data */
|
||||||
};
|
};
|
||||||
memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
|
memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
|
||||||
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
|
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
|
||||||
@ -118,7 +114,7 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_
|
|||||||
decoder->custom_header[0x13] = sample_rate >> 4;
|
decoder->custom_header[0x13] = sample_rate >> 4;
|
||||||
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
|
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
|
||||||
|
|
||||||
// configure the header ahead of the provided buffer
|
/* configure the header ahead of the provided buffer */
|
||||||
decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
|
decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
|
||||||
decoder->compressed_length = sizeof(decoder->custom_header);
|
decoder->compressed_length = sizeof(decoder->custom_header);
|
||||||
decoder->compressed2_start = (const FLAC__byte *)(buffer);
|
decoder->compressed2_start = (const FLAC__byte *)(buffer);
|
||||||
@ -127,21 +123,22 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// decode_interleaved - decode to an interleaved
|
* decode_interleaved - decode to an interleaved
|
||||||
// sound stream
|
* sound stream
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
|
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
|
||||||
{
|
{
|
||||||
// configure the uncompressed buffer
|
/* configure the uncompressed buffer */
|
||||||
memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
|
memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
|
||||||
decoder->uncompressed_start[0] = samples;
|
decoder->uncompressed_start[0] = samples;
|
||||||
decoder->uncompressed_offset = 0;
|
decoder->uncompressed_offset = 0;
|
||||||
decoder->uncompressed_length = num_samples;
|
decoder->uncompressed_length = num_samples;
|
||||||
decoder->uncompressed_swap = swap_endian;
|
decoder->uncompressed_swap = swap_endian;
|
||||||
|
|
||||||
// loop until we get everything we want
|
/* loop until we get everything we want */
|
||||||
while (decoder->uncompressed_offset < decoder->uncompressed_length)
|
while (decoder->uncompressed_offset < decoder->uncompressed_length)
|
||||||
if (!FLAC__stream_decoder_process_single(decoder->decoder))
|
if (!FLAC__stream_decoder_process_single(decoder->decoder))
|
||||||
return 0;
|
return 0;
|
||||||
@ -149,20 +146,22 @@ int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
// decode - decode to an multiple independent
|
* decode - decode to an multiple independent
|
||||||
// data streams
|
* data streams
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
|
bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
|
||||||
{
|
{
|
||||||
// make sure we don't have too many channels
|
/* make sure we don't have too many channels */
|
||||||
int chans = channels();
|
int chans = channels();
|
||||||
if (chans > ARRAY_LENGTH(m_uncompressed_start))
|
if (chans > ARRAY_LENGTH(m_uncompressed_start))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// configure the uncompressed buffer
|
/* configure the uncompressed buffer */
|
||||||
memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
|
memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
|
||||||
for (int curchan = 0; curchan < chans; curchan++)
|
for (int curchan = 0; curchan < chans; curchan++)
|
||||||
m_uncompressed_start[curchan] = samples[curchan];
|
m_uncompressed_start[curchan] = samples[curchan];
|
||||||
@ -170,26 +169,27 @@ bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_end
|
|||||||
m_uncompressed_length = num_samples;
|
m_uncompressed_length = num_samples;
|
||||||
m_uncompressed_swap = swap_endian;
|
m_uncompressed_swap = swap_endian;
|
||||||
|
|
||||||
// loop until we get everything we want
|
/* loop until we get everything we want */
|
||||||
while (m_uncompressed_offset < m_uncompressed_length)
|
while (m_uncompressed_offset < m_uncompressed_length)
|
||||||
if (!FLAC__stream_decoder_process_single(m_decoder))
|
if (!FLAC__stream_decoder_process_single(m_decoder))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*/
|
#endif
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// finish - finish up the decode
|
* finish - finish up the decode
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t flac_decoder_finish(flac_decoder* decoder)
|
uint32_t flac_decoder_finish(flac_decoder* decoder)
|
||||||
{
|
{
|
||||||
// get the final decoding position and move forward
|
/* get the final decoding position and move forward */
|
||||||
FLAC__uint64 position = 0;
|
FLAC__uint64 position = 0;
|
||||||
FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
|
FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
|
||||||
FLAC__stream_decoder_finish(decoder->decoder);
|
FLAC__stream_decoder_finish(decoder->decoder);
|
||||||
|
|
||||||
// adjust position if we provided the header
|
/* adjust position if we provided the header */
|
||||||
if (position == 0)
|
if (position == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
|
if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
|
||||||
@ -198,10 +198,11 @@ uint32_t flac_decoder_finish(flac_decoder* decoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// read_callback - handle reads from the input
|
* read_callback - handle reads from the input
|
||||||
// stream
|
* stream
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC
|
|||||||
|
|
||||||
uint32_t expected = *bytes;
|
uint32_t expected = *bytes;
|
||||||
|
|
||||||
// copy from primary buffer first
|
/* copy from primary buffer first */
|
||||||
uint32_t outputpos = 0;
|
uint32_t outputpos = 0;
|
||||||
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
|
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
|
||||||
{
|
{
|
||||||
@ -226,7 +227,7 @@ FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC
|
|||||||
decoder->compressed_offset += bytes_to_copy;
|
decoder->compressed_offset += bytes_to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// once we're out of that, copy from the secondary buffer
|
/* once we're out of that, copy from the secondary buffer */
|
||||||
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
|
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
|
||||||
{
|
{
|
||||||
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
|
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
|
||||||
@ -236,23 +237,24 @@ FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC
|
|||||||
}
|
}
|
||||||
*bytes = outputpos;
|
*bytes = outputpos;
|
||||||
|
|
||||||
// return based on whether we ran out of data
|
/* return based on whether we ran out of data */
|
||||||
return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// metadata_callback - handle STREAMINFO metadata
|
* metadata_callback - handle STREAMINFO metadata
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||||
{
|
{
|
||||||
flac_decoder *fldecoder;
|
flac_decoder *fldecoder;
|
||||||
// ignore all but STREAMINFO metadata
|
/* ignore all but STREAMINFO metadata */
|
||||||
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
|
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// parse out the data we care about
|
/* parse out the data we care about */
|
||||||
fldecoder = (flac_decoder *)(client_data);
|
fldecoder = (flac_decoder *)(client_data);
|
||||||
fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
|
fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
|
||||||
fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
|
fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
|
||||||
@ -260,10 +262,11 @@ void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// tell_callback - handle requests to find out
|
* tell_callback - handle requests to find out
|
||||||
// where in the input stream we are
|
* where in the input stream we are
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||||
{
|
{
|
||||||
@ -272,10 +275,11 @@ FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__Stre
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// write_callback - handle writes to the output
|
* write_callback - handle writes to the output
|
||||||
// stream
|
* stream
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||||
{
|
{
|
||||||
@ -284,28 +288,26 @@ FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__St
|
|||||||
|
|
||||||
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
|
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
|
||||||
{
|
{
|
||||||
|
int sampnum, chan;
|
||||||
int shift, blocksize;
|
int shift, blocksize;
|
||||||
flac_decoder * decoder = (flac_decoder *)client_data;
|
flac_decoder * decoder = (flac_decoder *)client_data;
|
||||||
|
|
||||||
assert(frame->header.channels == channels(decoder));
|
assert(frame->header.channels == decoder->channels);
|
||||||
|
|
||||||
// interleaved case
|
/* interleaved case */
|
||||||
shift = decoder->uncompressed_swap ? 8 : 0;
|
shift = decoder->uncompressed_swap ? 8 : 0;
|
||||||
blocksize = frame->header.blocksize;
|
blocksize = frame->header.blocksize;
|
||||||
|
|
||||||
if (decoder->uncompressed_start[1] == NULL)
|
if (decoder->uncompressed_start[1] == NULL)
|
||||||
{
|
{
|
||||||
int sampnum, chan;
|
|
||||||
int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
|
int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
|
||||||
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
|
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
|
||||||
for (chan = 0; chan < frame->header.channels; chan++)
|
for (chan = 0; chan < frame->header.channels; chan++)
|
||||||
*dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
|
*dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-interleaved case
|
/* non-interleaved case */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int sampnum, chan;
|
|
||||||
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
|
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
|
||||||
for (chan = 0; chan < frame->header.channels; chan++)
|
for (chan = 0; chan < frame->header.channels; chan++)
|
||||||
if (decoder->uncompressed_start[chan] != NULL)
|
if (decoder->uncompressed_start[chan] != NULL)
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
#define __FLAC_H__
|
#define __FLAC_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "FLAC/all.h"
|
#include "FLAC/ordinals.h"
|
||||||
|
#include "FLAC/stream_decoder.h"
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// TYPE DEFINITIONS
|
// TYPE DEFINITIONS
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// license:BSD-3-Clause
|
/* license:BSD-3-Clause
|
||||||
// copyright-holders:Aaron Giles
|
* copyright-holders:Aaron Giles
|
||||||
/***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
huffman.c
|
huffman.c
|
||||||
|
|
||||||
@ -105,26 +105,28 @@
|
|||||||
|
|
||||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
//**************************************************************************
|
/***************************************************************************
|
||||||
// MACROS
|
* MACROS
|
||||||
//**************************************************************************
|
***************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
#define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
|
#define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
/***************************************************************************
|
||||||
// IMPLEMENTATION
|
* IMPLEMENTATION
|
||||||
//**************************************************************************
|
* **************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// huffman_context_base - create an encoding/
|
* huffman_context_base - create an encoding/
|
||||||
// decoding context
|
* decoding context
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
|
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
|
||||||
{
|
{
|
||||||
struct huffman_decoder* decoder;
|
struct huffman_decoder* decoder;
|
||||||
|
|
||||||
/* limit to 24 bits */
|
/* limit to 24 bits */
|
||||||
if (maxbits > 24)
|
if (maxbits > 24)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -140,10 +142,23 @@ struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
|
|||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
void delete_huffman_decoder(struct huffman_decoder* decoder)
|
||||||
// decode_one - decode a single code from the
|
{
|
||||||
// huffman stream
|
if (decoder != NULL)
|
||||||
//-------------------------------------------------
|
{
|
||||||
|
if (decoder->lookup != NULL)
|
||||||
|
free(decoder->lookup);
|
||||||
|
if (decoder->huffnode != NULL)
|
||||||
|
free(decoder->huffnode);
|
||||||
|
free(decoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* decode_one - decode a single code from the
|
||||||
|
* huffman stream
|
||||||
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
||||||
{
|
{
|
||||||
@ -158,17 +173,18 @@ uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* b
|
|||||||
return lookup >> 5;
|
return lookup >> 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// import_tree_rle - import an RLE-encoded
|
* import_tree_rle - import an RLE-encoded
|
||||||
// huffman tree from a source data stream
|
* huffman tree from a source data stream
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
||||||
{
|
{
|
||||||
enum huffman_error error;
|
enum huffman_error error;
|
||||||
int curnode;
|
/* bits per entry depends on the maxbits */
|
||||||
// bits per entry depends on the maxbits
|
|
||||||
int numbits;
|
int numbits;
|
||||||
|
int curnode;
|
||||||
if (decoder->maxbits >= 16)
|
if (decoder->maxbits >= 16)
|
||||||
numbits = 5;
|
numbits = 5;
|
||||||
else if (decoder->maxbits >= 8)
|
else if (decoder->maxbits >= 8)
|
||||||
@ -176,23 +192,23 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
|
|||||||
else
|
else
|
||||||
numbits = 3;
|
numbits = 3;
|
||||||
|
|
||||||
// loop until we read all the nodes
|
/* loop until we read all the nodes */
|
||||||
for (curnode = 0; curnode < decoder->numcodes; )
|
for (curnode = 0; curnode < decoder->numcodes; )
|
||||||
{
|
{
|
||||||
// a non-one value is just raw
|
/* a non-one value is just raw */
|
||||||
int nodebits = bitstream_read(bitbuf, numbits);
|
int nodebits = bitstream_read(bitbuf, numbits);
|
||||||
if (nodebits != 1)
|
if (nodebits != 1)
|
||||||
decoder->huffnode[curnode++].numbits = nodebits;
|
decoder->huffnode[curnode++].numbits = nodebits;
|
||||||
|
|
||||||
// a one value is an escape code
|
/* a one value is an escape code */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// a double 1 is just a single 1
|
/* a double 1 is just a single 1 */
|
||||||
nodebits = bitstream_read(bitbuf, numbits);
|
nodebits = bitstream_read(bitbuf, numbits);
|
||||||
if (nodebits == 1)
|
if (nodebits == 1)
|
||||||
decoder->huffnode[curnode++].numbits = nodebits;
|
decoder->huffnode[curnode++].numbits = nodebits;
|
||||||
|
|
||||||
// otherwise, we need one for value for the repeat count
|
/* otherwise, we need one for value for the repeat count */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int repcount = bitstream_read(bitbuf, numbits) + 3;
|
int repcount = bitstream_read(bitbuf, numbits) + 3;
|
||||||
@ -202,39 +218,39 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we ended up with the right number
|
/* make sure we ended up with the right number */
|
||||||
if (curnode != decoder->numcodes)
|
if (curnode != decoder->numcodes)
|
||||||
return HUFFERR_INVALID_DATA;
|
return HUFFERR_INVALID_DATA;
|
||||||
|
|
||||||
// assign canonical codes for all nodes based on their code lengths
|
/* assign canonical codes for all nodes based on their code lengths */
|
||||||
error = huffman_assign_canonical_codes(decoder);
|
error = huffman_assign_canonical_codes(decoder);
|
||||||
if (error != HUFFERR_NONE)
|
if (error != HUFFERR_NONE)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// build the lookup table
|
/* build the lookup table */
|
||||||
huffman_build_lookup_table(decoder);
|
huffman_build_lookup_table(decoder);
|
||||||
|
|
||||||
// determine final input length and report errors
|
/* determine final input length and report errors */
|
||||||
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// import_tree_huffman - import a huffman-encoded
|
* import_tree_huffman - import a huffman-encoded
|
||||||
// huffman tree from a source data stream
|
* huffman tree from a source data stream
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
|
||||||
{
|
{
|
||||||
int index;
|
|
||||||
int start;
|
|
||||||
int count = 0;
|
|
||||||
uint8_t rlefullbits = 0;
|
|
||||||
int last = 0;
|
int last = 0;
|
||||||
int curcode;
|
int curcode;
|
||||||
enum huffman_error error;
|
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
// start by parsing the lengths for the small tree
|
enum huffman_error error;
|
||||||
|
uint8_t rlefullbits = 0;
|
||||||
|
int index, count = 0;
|
||||||
|
int start;
|
||||||
|
/* start by parsing the lengths for the small tree */
|
||||||
struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
|
struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
|
||||||
|
|
||||||
smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
|
smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
|
||||||
@ -251,18 +267,18 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// then regenerate the tree
|
/* then regenerate the tree */
|
||||||
error = huffman_assign_canonical_codes(smallhuff);
|
error = huffman_assign_canonical_codes(smallhuff);
|
||||||
if (error != HUFFERR_NONE)
|
if (error != HUFFERR_NONE)
|
||||||
return error;
|
return error;
|
||||||
huffman_build_lookup_table(smallhuff);
|
huffman_build_lookup_table(smallhuff);
|
||||||
|
|
||||||
// determine the maximum length of an RLE count
|
/* determine the maximum length of an RLE count */
|
||||||
temp = decoder->numcodes - 9;
|
temp = decoder->numcodes - 9;
|
||||||
while (temp != 0)
|
while (temp != 0)
|
||||||
temp >>= 1, rlefullbits++;
|
temp >>= 1, rlefullbits++;
|
||||||
|
|
||||||
// now process the rest of the data
|
/* now process the rest of the data */
|
||||||
for (curcode = 0; curcode < decoder->numcodes; )
|
for (curcode = 0; curcode < decoder->numcodes; )
|
||||||
{
|
{
|
||||||
int value = huffman_decode_one(smallhuff, bitbuf);
|
int value = huffman_decode_one(smallhuff, bitbuf);
|
||||||
@ -278,52 +294,53 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we ended up with the right number
|
/* make sure we ended up with the right number */
|
||||||
if (curcode != decoder->numcodes)
|
if (curcode != decoder->numcodes)
|
||||||
return HUFFERR_INVALID_DATA;
|
return HUFFERR_INVALID_DATA;
|
||||||
|
|
||||||
// assign canonical codes for all nodes based on their code lengths
|
/* assign canonical codes for all nodes based on their code lengths */
|
||||||
error = huffman_assign_canonical_codes(decoder);
|
error = huffman_assign_canonical_codes(decoder);
|
||||||
if (error != HUFFERR_NONE)
|
if (error != HUFFERR_NONE)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// build the lookup table
|
/* build the lookup table */
|
||||||
huffman_build_lookup_table(decoder);
|
huffman_build_lookup_table(decoder);
|
||||||
|
|
||||||
// determine final input length and report errors
|
/* determine final input length and report errors */
|
||||||
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// compute_tree_from_histo - common backend for
|
* compute_tree_from_histo - common backend for
|
||||||
// computing a tree based on the data histogram
|
* computing a tree based on the data histogram
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
|
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
|
||||||
{
|
{
|
||||||
int i;
|
/* compute the number of data items in the histogram */
|
||||||
|
int i;
|
||||||
uint32_t upperweight;
|
uint32_t upperweight;
|
||||||
uint32_t lowerweight = 0;
|
uint32_t lowerweight = 0;
|
||||||
// compute the number of data items in the histogram
|
|
||||||
uint32_t sdatacount = 0;
|
uint32_t sdatacount = 0;
|
||||||
for (i = 0; i < decoder->numcodes; i++)
|
for (i = 0; i < decoder->numcodes; i++)
|
||||||
sdatacount += decoder->datahisto[i];
|
sdatacount += decoder->datahisto[i];
|
||||||
|
|
||||||
// binary search to achieve the optimum encoding
|
/* binary search to achieve the optimum encoding */
|
||||||
upperweight = sdatacount * 2;
|
upperweight = sdatacount * 2;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
// build a tree using the current weight
|
/* build a tree using the current weight */
|
||||||
uint32_t curweight = (upperweight + lowerweight) / 2;
|
uint32_t curweight = (upperweight + lowerweight) / 2;
|
||||||
int curmaxbits = huffman_build_tree(decoder, sdatacount, curweight);
|
int curmaxbits = huffman_build_tree(decoder, sdatacount, curweight);
|
||||||
|
|
||||||
// apply binary search here
|
/* apply binary search here */
|
||||||
if (curmaxbits <= decoder->maxbits)
|
if (curmaxbits <= decoder->maxbits)
|
||||||
{
|
{
|
||||||
lowerweight = curweight;
|
lowerweight = curweight;
|
||||||
|
|
||||||
// early out if it worked with the raw weights, or if we're done searching
|
/* early out if it worked with the raw weights, or if we're done searching */
|
||||||
if (curweight == sdatacount || (upperweight - lowerweight) <= 1)
|
if (curweight == sdatacount || (upperweight - lowerweight) <= 1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -331,20 +348,22 @@ enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decod
|
|||||||
upperweight = curweight;
|
upperweight = curweight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign canonical codes for all nodes based on their code lengths
|
/* assign canonical codes for all nodes based on their code lengths */
|
||||||
return huffman_assign_canonical_codes(decoder);
|
return huffman_assign_canonical_codes(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
/***************************************************************************
|
||||||
// INTERNAL FUNCTIONS
|
* INTERNAL FUNCTIONS
|
||||||
//**************************************************************************
|
***************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// tree_node_compare - compare two tree nodes
|
* tree_node_compare - compare two tree nodes
|
||||||
// by weight
|
* by weight
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
static int huffman_tree_node_compare(const void *item1, const void *item2)
|
static int huffman_tree_node_compare(const void *item1, const void *item2)
|
||||||
{
|
{
|
||||||
@ -358,19 +377,19 @@ static int huffman_tree_node_compare(const void *item1, const void *item2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// build_tree - build a huffman tree based on the
|
* build_tree - build a huffman tree based on the
|
||||||
// data distribution
|
* data distribution
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
|
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
|
||||||
{
|
{
|
||||||
int curcode;
|
|
||||||
int nextalloc;
|
int nextalloc;
|
||||||
int maxbits = 0;
|
int maxbits = 0;
|
||||||
// make a list of all non-zero nodes
|
/* make a list of all non-zero nodes */
|
||||||
struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
|
struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
|
||||||
int listitems = 0;
|
int curcode, listitems = 0;
|
||||||
memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
|
memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
|
||||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||||
if (decoder->datahisto[curcode] != 0)
|
if (decoder->datahisto[curcode] != 0)
|
||||||
@ -379,7 +398,7 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
decoder->huffnode[curcode].count = decoder->datahisto[curcode];
|
decoder->huffnode[curcode].count = decoder->datahisto[curcode];
|
||||||
decoder->huffnode[curcode].bits = curcode;
|
decoder->huffnode[curcode].bits = curcode;
|
||||||
|
|
||||||
// scale the weight by the current effective length, ensuring we don't go to 0
|
/* scale the weight by the current effective length, ensuring we don't go to 0 */
|
||||||
decoder->huffnode[curcode].weight = ((uint64_t)decoder->datahisto[curcode]) * ((uint64_t)totalweight) / ((uint64_t)totaldata);
|
decoder->huffnode[curcode].weight = ((uint64_t)decoder->datahisto[curcode]) * ((uint64_t)totalweight) / ((uint64_t)totaldata);
|
||||||
if (decoder->huffnode[curcode].weight == 0)
|
if (decoder->huffnode[curcode].weight == 0)
|
||||||
decoder->huffnode[curcode].weight = 1;
|
decoder->huffnode[curcode].weight = 1;
|
||||||
@ -390,7 +409,7 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
|
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// sort the list by weight, largest weight first
|
/* sort the list by weight, largest weight first */
|
||||||
qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
|
qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
|
||||||
/*
|
/*
|
||||||
fprintf(stderr, "Post-sort:\n");
|
fprintf(stderr, "Post-sort:\n");
|
||||||
@ -399,23 +418,23 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
}
|
}
|
||||||
fprintf(stderr, "===================\n");
|
fprintf(stderr, "===================\n");
|
||||||
*/
|
*/
|
||||||
// now build the tree
|
/* now build the tree */
|
||||||
nextalloc = decoder->numcodes;
|
nextalloc = decoder->numcodes;
|
||||||
|
|
||||||
while (listitems > 1)
|
while (listitems > 1)
|
||||||
{
|
{
|
||||||
int curitem;
|
int curitem;
|
||||||
// remove lowest two items
|
/* remove lowest two items */
|
||||||
struct node_t* node1 = &(*list[--listitems]);
|
struct node_t* node1 = &(*list[--listitems]);
|
||||||
struct node_t* node0 = &(*list[--listitems]);
|
struct node_t* node0 = &(*list[--listitems]);
|
||||||
|
|
||||||
// create new node
|
/* create new node */
|
||||||
struct node_t* newnode = &decoder->huffnode[nextalloc++];
|
struct node_t* newnode = &decoder->huffnode[nextalloc++];
|
||||||
newnode->parent = NULL;
|
newnode->parent = NULL;
|
||||||
node0->parent = node1->parent = newnode;
|
node0->parent = node1->parent = newnode;
|
||||||
newnode->weight = node0->weight + node1->weight;
|
newnode->weight = node0->weight + node1->weight;
|
||||||
|
|
||||||
// insert into list at appropriate location
|
/* insert into list at appropriate location */
|
||||||
for (curitem = 0; curitem < listitems; curitem++)
|
for (curitem = 0; curitem < listitems; curitem++)
|
||||||
if (newnode->weight > list[curitem]->weight)
|
if (newnode->weight > list[curitem]->weight)
|
||||||
{
|
{
|
||||||
@ -426,9 +445,10 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
listitems++;
|
listitems++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the number of bits in each code, and fill in another histogram
|
/* compute the number of bits in each code, and fill in another histogram */
|
||||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||||
{
|
{
|
||||||
|
struct node_t *curnode;
|
||||||
struct node_t* node = &decoder->huffnode[curcode];
|
struct node_t* node = &decoder->huffnode[curcode];
|
||||||
node->numbits = 0;
|
node->numbits = 0;
|
||||||
node->bits = 0;
|
node->bits = 0;
|
||||||
@ -436,14 +456,13 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
// if we have a non-zero weight, compute the number of bits
|
// if we have a non-zero weight, compute the number of bits
|
||||||
if (node->weight > 0)
|
if (node->weight > 0)
|
||||||
{
|
{
|
||||||
struct node_t *curnode;
|
/* determine the number of bits for this node */
|
||||||
// determine the number of bits for this node
|
|
||||||
for (curnode = node; curnode->parent != NULL; curnode = curnode->parent)
|
for (curnode = node; curnode->parent != NULL; curnode = curnode->parent)
|
||||||
node->numbits++;
|
node->numbits++;
|
||||||
if (node->numbits == 0)
|
if (node->numbits == 0)
|
||||||
node->numbits = 1;
|
node->numbits = 1;
|
||||||
|
|
||||||
// keep track of the max
|
/* keep track of the max */
|
||||||
maxbits = MAX(maxbits, ((int)node->numbits));
|
maxbits = MAX(maxbits, ((int)node->numbits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,18 +470,18 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// assign_canonical_codes - assign canonical codes
|
* assign_canonical_codes - assign canonical codes
|
||||||
// to all the nodes based on the number of bits
|
* to all the nodes based on the number of bits
|
||||||
// in each
|
* in each
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
|
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
|
||||||
{
|
{
|
||||||
int curcode, codelen;
|
|
||||||
uint32_t curstart = 0;
|
uint32_t curstart = 0;
|
||||||
|
/* build up a histogram of bit lengths */
|
||||||
// build up a histogram of bit lengths
|
int curcode, codelen;
|
||||||
uint32_t bithisto[33] = { 0 };
|
uint32_t bithisto[33] = { 0 };
|
||||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||||
{
|
{
|
||||||
@ -473,7 +492,7 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
|
|||||||
bithisto[node->numbits]++;
|
bithisto[node->numbits]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for each code length, determine the starting code number
|
/* for each code length, determine the starting code number */
|
||||||
for (codelen = 32; codelen > 0; codelen--)
|
for (codelen = 32; codelen > 0; codelen--)
|
||||||
{
|
{
|
||||||
uint32_t nextstart = (curstart + bithisto[codelen]) >> 1;
|
uint32_t nextstart = (curstart + bithisto[codelen]) >> 1;
|
||||||
@ -483,7 +502,7 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
|
|||||||
curstart = nextstart;
|
curstart = nextstart;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now assign canonical codes
|
/* now assign canonical codes */
|
||||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||||
{
|
{
|
||||||
struct node_t* node = &decoder->huffnode[curcode];
|
struct node_t* node = &decoder->huffnode[curcode];
|
||||||
@ -494,33 +513,32 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
// build_lookup_table - build a lookup table for
|
* build_lookup_table - build a lookup table for
|
||||||
// fast decoding
|
* fast decoding
|
||||||
//-------------------------------------------------
|
*-------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void huffman_build_lookup_table(struct huffman_decoder* decoder)
|
void huffman_build_lookup_table(struct huffman_decoder* decoder)
|
||||||
{
|
{
|
||||||
int curcode;
|
/* iterate over all codes */
|
||||||
// iterate over all codes
|
int curcode;
|
||||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||||
{
|
{
|
||||||
// process all nodes which have non-zero bits
|
/* process all nodes which have non-zero bits */
|
||||||
struct node_t* node = &decoder->huffnode[curcode];
|
struct node_t* node = &decoder->huffnode[curcode];
|
||||||
if (node->numbits > 0)
|
if (node->numbits > 0)
|
||||||
{
|
{
|
||||||
int shift;
|
int shift;
|
||||||
lookup_value *dest;
|
lookup_value *dest;
|
||||||
lookup_value *destend;
|
lookup_value *destend;
|
||||||
|
/* set up the entry */
|
||||||
// set up the entry
|
|
||||||
lookup_value value = MAKE_LOOKUP(curcode, node->numbits);
|
lookup_value value = MAKE_LOOKUP(curcode, node->numbits);
|
||||||
|
|
||||||
// fill all matching entries
|
/* fill all matching entries */
|
||||||
shift = decoder->maxbits - node->numbits;
|
shift = decoder->maxbits - node->numbits;
|
||||||
dest = &decoder->lookup[node->bits << shift];
|
dest = &decoder->lookup[node->bits << shift];
|
||||||
destend = &decoder->lookup[((node->bits + 1) << shift) - 1];
|
destend = &decoder->lookup[((node->bits + 1) << shift) - 1];
|
||||||
|
|
||||||
while (dest <= destend)
|
while (dest <= destend)
|
||||||
*dest++ = value;
|
*dest++ = value;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ struct huffman_decoder
|
|||||||
// ======================> huffman_decoder
|
// ======================> huffman_decoder
|
||||||
|
|
||||||
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits);
|
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits);
|
||||||
|
void delete_huffman_decoder(struct huffman_decoder* decoder);
|
||||||
|
|
||||||
// single item operations
|
// single item operations
|
||||||
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf);
|
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user