📄 huff.c
字号:
/*------------------------------------------------------------------------------ File : HUFF.c Author : St閜hane TAVENARD $VER: HUFF.c 0.4 (24/05/1999) (C) Copyright 1997-1999 St閜hane TAVENARD All Rights Reserved This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #Rev| Date | Comment ----|----------|-------------------------------------------------------- 0 |17/03/1997| Initial revision ST 1 |31/03/1997| First aminet release ST 2 |07/06/1997| Added HUFF_fill_bytes ST 3 |04/07/1997| Fix bug in HUFF_pos & HUFF_read_bits ST 4 |24/05/1999| Added some const ST ------------------------------------------------------------------------ Huffman Codes handling------------------------------------------------------------------------------*/#include "defs.h"#include "mpegaud.h"#include "mpegtab.h"void HUFF_close( HUFFMAN *h )/*--------------------------- Close the huffman stream*/{ if( !h ) return; if( h->buffer ) free( h->buffer ); free( h );} /* HUFF_close */int HUFF_reset( HUFFMAN *h )/*-------------------------- Reset an huffman stream*/{ if( !h ) return -1; h->write_index = h->read_index = 0; h->bit_cache = h->cache_size = 0; h->nul_begin = 576; // begin of last null zone return 0;} /* HUFF_reset */HUFFMAN *HUFF_open( void )/*------------------------ Open an huffman stream*/{ HUFFMAN *h; h = (HUFFMAN *)malloc( sizeof( HUFFMAN ) ); if( !h ) return NULL; memset( h, 0, sizeof( HUFFMAN ) ); h->buffer = malloc( HUFF_BUFFER_SIZE ); if( !h ) { HUFF_close( h ); return NULL; } memset( h->buffer, 0, HUFF_BUFFER_SIZE ); h->buffer_size = HUFF_BUFFER_SIZE; return h;} /* HUFF_open *//* #2 Begin */void HUFF_fill_bytes( HUFFMAN *h, unsigned int count, char *buffer )/*----------------------------------------------------------------- Write bytes to huffman buffer*/{ register unsigned int to_fill; while( count > 0 ) { to_fill = HUFF_BUFFER_SIZE - h->write_index; if( to_fill > count ) to_fill = count; memcpy( &h->buffer[ h->write_index ], buffer, to_fill ); count -= to_fill; buffer += to_fill; h->write_index += to_fill; if( h->write_index >= HUFF_BUFFER_SIZE ) h->write_index = 0; }} /* HUFF_fill_bytes *//* #2 End */int HUFF_set_start( HUFFMAN *h, int start_pos )/*--------------------------------------------- Set the start pos of the huffman buffer relative to the end of buffer (byte size). start_pos is used as a negative offset.*/{ int size; size = h->write_index - h->read_index + (h->cache_size>>3); if( size < 0 ) size += HUFF_BUFFER_SIZE; if( size < start_pos ) {//printf( "* remain size=%d start=%d\n", size, start_pos ); return -1; // Not enough data } h->read_index = (h->write_index - start_pos) & (HUFF_BUFFER_SIZE-1); h->cache_size = 0; // Flush cache return 0;} /* HUFF_set_start */#define FILL_CACHE( h ) { \ h->bit_cache = ((UINT32)h->buffer[ h->read_index & (HUFF_BUFFER_SIZE-1) ])<<24 |\ ((UINT32)h->buffer[ (h->read_index + 1) & (HUFF_BUFFER_SIZE-1) ])<<16 |\ ((UINT32)h->buffer[ (h->read_index + 2) & (HUFF_BUFFER_SIZE-1) ])<<8 |\ ((UINT32)h->buffer[ (h->read_index + 3) & (HUFF_BUFFER_SIZE-1) ]);\ h->read_index = (h->read_index + 4) & (HUFF_BUFFER_SIZE-1);\}int HUFF_seek( HUFFMAN *h, int seek_pos )/*--------------------------------------------- Seek to a bit pos in the huffman buffer (absolute pos)*/{ int advance; h->read_index = (seek_pos >> 3) & (HUFF_BUFFER_SIZE-1); advance = seek_pos & 7; FILL_CACHE( h ); h->cache_size = 32; // Discard some bits if not aligned if( advance ) HUFF_read_bits( h, advance ); return 0;} /* HUFF_seek */unsigned long HUFF_read_bit_cache( HUFFMAN *h )/*-------------------------------------------- Update the bit cache and return next bit*/{ register unsigned long bits; FILL_CACHE( h ); h->cache_size = 31; bits = (h->bit_cache & 0x80000000)?1:0; h->bit_cache <<= 1; return bits;}unsigned long HUFF_read_bits_cache( HUFFMAN *h, unsigned int count )/*----------------------------------------------------------------- Update the bit cache and return next bits*/{ register unsigned long bits; if( h->cache_size > 0 ) { // #3 bits = h->bit_cache >> (32 - count); count -= h->cache_size; } else bits = 0; FILL_CACHE( h ); h->cache_size = 32 - count; bits |= h->bit_cache >> (32 - count); h->bit_cache <<= count; return bits;}/* Huffman tables *///static const UINT32 h0[1]={0x0};static const UINT32 h1[4]={0x311, 0x20000301, 0x40000210, 0x80000100};static const UINT32 h2[9]={0x622, 0x4000602, 0x8000512, 0x10000521, 0x18000520, 0x20000311, 0x40000301, 0x60000310, 0x80000100};static const UINT32 h3[9]={ 0x622, 0x4000602, 0x8000512, 0x10000521, 0x18000520, 0x20000310, 0x40000211, 0x80000201, 0xc0000200};static const UINT32 h5[16]={0x833, 0x1000823, 0x2000732, 0x4000631, 0x8000713, 0xa000703, 0xc000730, 0xe000722, 0x10000612, 0x14000621, 0x18000602, 0x1c000620, 0x20000311, 0x40000301, 0x60000310, 0x80000100};static const UINT32 h6[16]={0x733, 0x2000703, 0x4000623, 0x8000632, 0xc000630, 0x10000513, 0x18000531, 0x20000522, 0x28000502, 0x30000412, 0x40000421, 0x50000420, 0x60000301, 0x80000211, 0xc0000310, 0xe0000300};static const UINT32 h7[36]={ 0xa55, 0x400a45, 0x800a54, 0xc00a53, 0x1000935, 0x1800944, 0x2000925, 0x2800952, 0x3000815, 0x4000851, 0x5000905, 0x5800934, 0x6000850, 0x7000943, 0x7800933, 0x8000824, 0x9000842, 0xa000714, 0xc000741, 0xe000740, 0x10000804, 0x11000823, 0x12000832, 0x13000803, 0x14000713, 0x16000731, 0x18000730, 0x1a000722, 0x1c000612, 0x20000521, 0x28000602, 0x2c000620, 0x30000411, 0x40000301, 0x60000310, 0x80000100};static const UINT32 h8[36]={0xb55, 0x200b54, 0x400a45, 0x800953, 0x1000a35, 0x1400a44, 0x1800925, 0x2000952, 0x2800905, 0x3000815, 0x4000851, 0x5000934, 0x5800943, 0x6000950, 0x6800933, 0x7000824, 0x8000842, 0x9000814, 0xa000741, 0xc000804, 0xd000840, 0xe000823, 0xf000832, 0x10000813, 0x11000831, 0x12000803, 0x13000830, 0x14000622, 0x18000602, 0x1c000620, 0x20000412, 0x30000421, 0x40000211, 0x80000301, 0xa0000310, 0xc0000200};static const UINT32 h9[36]={ 0x00000955, 0x00800945, 0x01000835, 0x02000853, 0x03000954, 0x03800905, 0x04000844, 0x05000825, 0x06000852, 0x07000815, 0x08000751, 0x0a000734, 0x0c000743, 0x0e000850, 0x0f000804, 0x10000724, 0x12000742, 0x14000733, 0x16000740, 0x18000614, 0x1c000641, 0x20000623, 0x24000632, 0x28000513, 0x30000531, 0x38000603, 0x3c000630, 0x40000522, 0x48000502, 0x50000412, 0x60000421, 0x70000420, 0x80000311, 0xa0000301, 0xc0000310, 0xe0000300};static const UINT32 h10[64]={ 0xb77, 0x200b67, 0x400b76, 0x600b57, 0x800b75, 0xa00b66, 0xc00a47, 0x1000a74, 0x1400a56, 0x1800a65, 0x1c00a37, 0x2000a73, 0x2400a46, 0x2800b55, 0x2a00b54, 0x2c00a63, 0x3000927, 0x3800972, 0x4000a64, 0x4400a07, 0x4800970, 0x5000962, 0x5800a45, 0x5c00a35, 0x6000906, 0x6800a53, 0x6c00a44, 0x7000817, 0x8000871, 0x9000936, 0x9800926, 0xa000a25, 0xa400a52, 0xa800915, 0xb000951, 0xb800a34, 0xbc00a43, 0xc000816, 0xd000861, 0xe000860, 0xf000905, 0xf800950, 0x10000924, 0x10800942, 0x11000933, 0x11800904, 0x12000814, 0x13000841, 0x14000840, 0x15000823, 0x16000832, 0x17000803, 0x18000713, 0x1a000731, 0x1c000730, 0x1e000722, 0x20000612, 0x24000621, 0x28000602, 0x2c000620, 0x30000411, 0x40000301, 0x60000310, 0x80000100};static const UINT32 h11[64]={ 0xa77, 0x400a67, 0x800a76, 0xc00a75, 0x1000a66, 0x1400a47, 0x1800a74, 0x1c00b57,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -