/********************************************************************** * ISO MPEG Audio Subgroup Software Simulation Group (1996) * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension * **********************************************************************/ /* Revision History: Date Programmer Comment ========== ========================= =============================== 1995/08/06 mc@fivebats.com created 1995/09/06 mc@fivebats.com modified to use formatBitstream */ #include #include "lame.h" #include "l3bitstream.h" /* the public interface */ #include "encoder.h" #include "quantize.h" #include "quantize-pvt.h" #include "formatBitstream.h" #include "tables.h" #include #include "l3bitstream-pvt.h" static Bit_stream_struc *bs = NULL; BF_FrameData *frameData = NULL; BF_FrameResults *frameResults = NULL; int PartHoldersInitialized = 0; BF_PartHolder *headerPH; BF_PartHolder *frameSIPH; BF_PartHolder *channelSIPH[ MAX_CHANNELS ]; BF_PartHolder *spectrumSIPH[ MAX_GRANULES ][ MAX_CHANNELS ]; BF_PartHolder *scaleFactorsPH[ MAX_GRANULES ][ MAX_CHANNELS ]; BF_PartHolder *codedDataPH[ MAX_GRANULES ][ MAX_CHANNELS ]; BF_PartHolder *userSpectrumPH[ MAX_GRANULES ][ MAX_CHANNELS ]; BF_PartHolder *userFrameDataPH; void putMyBits( u_int val, u_int len ) { putbits( bs, val, len ); } /* III_format_bitstream() This is called after a frame of audio has been quantized and coded. It will write the encoded audio to the bitstream. Note that from a layer3 encoder's perspective the bit stream is primarily a series of main_data() blocks, with header and side information inserted at the proper locations to maintain framing. (See Figure A.7 in the IS). */ void III_format_bitstream( lame_global_flags *gfp, int bitsPerFrame, int l3_enc[2][2][576], III_side_info_t *l3_side, III_scalefac_t scalefac[2][2], Bit_stream_struc *in_bs) { int gr, ch; bs = in_bs; if ( frameData == NULL ) { frameData = calloc( 1,sizeof *frameData); assert( frameData ); } if ( frameResults == NULL ) { frameResults = calloc( 1,sizeof *frameResults); assert( frameResults ); } if ( !PartHoldersInitialized ) { headerPH = BF_newPartHolder( 14 ); frameSIPH = BF_newPartHolder( 12 ); for ( ch = 0; ch < MAX_CHANNELS; ch++ ) channelSIPH[ch] = BF_newPartHolder( 8 ); for ( gr = 0; gr < MAX_GRANULES; gr++ ) for ( ch = 0; ch < MAX_CHANNELS; ch++ ) { spectrumSIPH[gr][ch] = BF_newPartHolder( 32 ); scaleFactorsPH[gr][ch] = BF_newPartHolder( 64 ); codedDataPH[gr][ch] = BF_newPartHolder( 576 ); userSpectrumPH[gr][ch] = BF_newPartHolder( 4 ); } userFrameDataPH = BF_newPartHolder( 8 ); PartHoldersInitialized = 1; } encodeSideInfo( gfp,l3_side ); encodeMainData( gfp,l3_enc, l3_side, scalefac ); drain_into_ancillary_data( l3_side->resvDrain ); /* Put frameData together for the call to BitstreamFrame() */ frameData->frameLength = bitsPerFrame; frameData->nGranules = gfp->mode_gr; frameData->nChannels = gfp->stereo; frameData->header = headerPH->part; frameData->frameSI = frameSIPH->part; for ( ch = 0; ch < gfp->stereo; ch++ ) frameData->channelSI[ch] = channelSIPH[ch]->part; for ( gr = 0; gr < gfp->mode_gr; gr++ ) for ( ch = 0; ch < gfp->stereo; ch++ ) { frameData->spectrumSI[gr][ch] = spectrumSIPH[gr][ch]->part; frameData->scaleFactors[gr][ch] = scaleFactorsPH[gr][ch]->part; frameData->codedData[gr][ch] = codedDataPH[gr][ch]->part; frameData->userSpectrum[gr][ch] = userSpectrumPH[gr][ch]->part; } frameData->userFrameData = userFrameDataPH->part; BF_BitstreamFrame( frameData, frameResults ); /* we set this here -- it will be tested in the next loops iteration */ l3_side->main_data_begin = frameResults->nextBackPtr; } void III_FlushBitstream(void) { if (PartHoldersInitialized!=0) BF_FlushBitstream( frameData, frameResults ); } static unsigned slen1_tab[16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; static unsigned slen2_tab[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; static void encodeMainData( lame_global_flags *gfp, int l3_enc[2][2][576], III_side_info_t *si, III_scalefac_t scalefac[2][2] ) { int i, gr, ch, sfb, window; for ( gr = 0; gr < gfp->mode_gr; gr++ ) for ( ch = 0; ch < gfp->stereo; ch++ ) scaleFactorsPH[gr][ch]->part->nrEntries = 0; for ( gr = 0; gr < gfp->mode_gr; gr++ ) for ( ch = 0; ch < gfp->stereo; ch++ ) codedDataPH[gr][ch]->part->nrEntries = 0; if ( gfp->version == 1 ) { /* MPEG 1 */ for ( gr = 0; gr < 2; gr++ ) { for ( ch = 0; ch < gfp->stereo; ch++ ) { BF_PartHolder **pph = &scaleFactorsPH[gr][ch]; gr_info *gi = &(si->gr[gr].ch[ch].tt); unsigned slen1 = slen1_tab[ gi->scalefac_compress ]; unsigned slen2 = slen2_tab[ gi->scalefac_compress ]; int *ix = &l3_enc[gr][ch][0]; if (gi->block_type == SHORT_TYPE) { #ifdef ALLOW_MIXED if ( gi->mixed_block_flag ) { for ( sfb = 0; sfb < 8; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen1 ); for ( sfb = 3; sfb < 6; sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen1 ); for ( sfb = 6; sfb < 12; sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen2 ); } else #endif { for ( sfb = 0; sfb < 6; sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen1 ); for ( sfb = 6; sfb < 12; sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen2 ); } } else { if ( (gr == 0) || (si->scfsi[ch][0] == 0) ) for ( sfb = 0; sfb < 6; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen1 ); if ( (gr == 0) || (si->scfsi[ch][1] == 0) ) for ( sfb = 6; sfb < 11; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen1 ); if ( (gr == 0) || (si->scfsi[ch][2] == 0) ) for ( sfb = 11; sfb < 16; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen2 ); if ( (gr == 0) || (si->scfsi[ch][3] == 0) ) for ( sfb = 16; sfb < 21; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen2 ); } Huffmancodebits( &codedDataPH[gr][ch], ix, gi ); } /* for ch */ } /* for gr */ } else { /* MPEG 2 */ gr = 0; for ( ch = 0; ch < gfp->stereo; ch++ ) { BF_PartHolder **pph = &scaleFactorsPH[gr][ch]; gr_info *gi = &(si->gr[gr].ch[ch].tt); int *ix = &l3_enc[gr][ch][0]; int sfb_partition; assert( gi->sfb_partition_table ); if (gi->block_type == SHORT_TYPE) { #ifdef ALLOW_MIXED if ( gi->mixed_block_flag ) { sfb_partition = 0; for ( sfb = 0; sfb < 8; sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], gi->slen[sfb_partition] ); for ( sfb = 3, sfb_partition = 1; sfb_partition < 4; sfb_partition++ ) { int sfbs = gi->sfb_partition_table[ sfb_partition ] / 3; int slen = gi->slen[ sfb_partition ]; for ( i = 0; i < sfbs; i++, sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen ); } } else #endif { for ( sfb = 0, sfb_partition = 0; sfb_partition < 4; sfb_partition++ ) { int sfbs = gi->sfb_partition_table[ sfb_partition ] / 3; int slen = gi->slen[ sfb_partition ]; for ( i = 0; i < sfbs; i++, sfb++ ) for ( window = 0; window < 3; window++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].s[sfb][window], slen ); } } } else { for ( sfb = 0, sfb_partition = 0; sfb_partition < 4; sfb_partition++ ) { int sfbs = gi->sfb_partition_table[ sfb_partition ]; int slen = gi->slen[ sfb_partition ]; for ( i = 0; i < sfbs; i++, sfb++ ) *pph = BF_addEntry( *pph, scalefac[gr][ch].l[sfb], slen ); } } Huffmancodebits( &codedDataPH[gr][ch], ix, gi ); } /* for ch */ } } /* main_data */ static unsigned int crc = 0; /* (jo) current crc */ /* (jo) this wrapper function for BF_addEntry() updates also the crc */ static BF_PartHolder *CRC_BF_addEntry( BF_PartHolder *thePH, u_int value, u_int length ) { u_int bit = 1 << length; while((bit >>= 1)){ crc <<= 1; if (!(crc & 0x10000) ^ !(value & bit)) crc ^= CRC16_POLYNOMIAL; } crc &= 0xffff; return BF_addEntry(thePH, value, length); } static int encodeSideInfo( lame_global_flags *gfp,III_side_info_t *si ) { int gr, ch, scfsi_band, region, window, bits_sent; crc = 0xffff; /* (jo) init crc16 for error_protection */ headerPH->part->nrEntries = 0; headerPH = BF_addEntry( headerPH, 0xfff, 12 ); headerPH = BF_addEntry( headerPH, gfp->version, 1 ); headerPH = BF_addEntry( headerPH, 1, 2 ); headerPH = BF_addEntry( headerPH, !gfp->error_protection, 1 ); /* (jo) from now on call the CRC_BF_addEntry() wrapper to update crc */ headerPH = CRC_BF_addEntry( headerPH, gfp->bitrate_index, 4 ); headerPH = CRC_BF_addEntry( headerPH, gfp->samplerate_index, 2 ); headerPH = CRC_BF_addEntry( headerPH, gfp->padding, 1 ); headerPH = CRC_BF_addEntry( headerPH, gfp->extension, 1 ); headerPH = CRC_BF_addEntry( headerPH, gfp->mode, 2 ); headerPH = CRC_BF_addEntry( headerPH, gfp->mode_ext, 2 ); headerPH = CRC_BF_addEntry( headerPH, gfp->copyright, 1 ); headerPH = CRC_BF_addEntry( headerPH, gfp->original, 1 ); headerPH = CRC_BF_addEntry( headerPH, gfp->emphasis, 2 ); bits_sent = 32; /* (jo) see below for BF_addEntry( headerPH, crc, 16 ); */ frameSIPH->part->nrEntries = 0; for (ch = 0; ch < gfp->stereo; ch++ ) channelSIPH[ch]->part->nrEntries = 0; for ( gr = 0; gr < gfp->mode_gr; gr++ ) for ( ch = 0; ch < gfp->stereo; ch++ ) spectrumSIPH[gr][ch]->part->nrEntries = 0; if ( gfp->version == 1 ) { /* MPEG1 */ frameSIPH = CRC_BF_addEntry( frameSIPH, si->main_data_begin, 9 ); if ( gfp->stereo == 2 ) frameSIPH = CRC_BF_addEntry( frameSIPH, si->private_bits, 3 ); else frameSIPH = CRC_BF_addEntry( frameSIPH, si->private_bits, 5 ); for ( ch = 0; ch < gfp->stereo; ch++ ) for ( scfsi_band = 0; scfsi_band < 4; scfsi_band++ ) { BF_PartHolder **pph = &channelSIPH[ch]; *pph = CRC_BF_addEntry( *pph, si->scfsi[ch][scfsi_band], 1 ); } for ( gr = 0; gr < 2; gr++ ) for ( ch = 0; ch < gfp->stereo; ch++ ) { BF_PartHolder **pph = &spectrumSIPH[gr][ch]; gr_info *gi = &(si->gr[gr].ch[ch].tt); *pph = CRC_BF_addEntry( *pph, gi->part2_3_length, 12 ); *pph = CRC_BF_addEntry( *pph, gi->big_values, 9 ); *pph = CRC_BF_addEntry( *pph, gi->global_gain, 8 ); *pph = CRC_BF_addEntry( *pph, gi->scalefac_compress, 4 ); *pph = CRC_BF_addEntry( *pph, gi->window_switching_flag, 1 ); if ( gi->window_switching_flag ) { *pph = CRC_BF_addEntry( *pph, gi->block_type, 2 ); *pph = CRC_BF_addEntry( *pph, gi->mixed_block_flag, 1 ); for ( region = 0; region < 2; region++ ) *pph = CRC_BF_addEntry( *pph, gi->table_select[region], 5 ); for ( window = 0; window < 3; window++ ) *pph = CRC_BF_addEntry( *pph, gi->subblock_gain[window], 3 ); } else { assert( gi->block_type == NORM_TYPE ); for ( region = 0; region < 3; region++ ) *pph = CRC_BF_addEntry( *pph, gi->table_select[region], 5 ); *pph = CRC_BF_addEntry( *pph, gi->region0_count, 4 ); *pph = CRC_BF_addEntry( *pph, gi->region1_count, 3 ); } *pph = CRC_BF_addEntry( *pph, gi->preflag, 1 ); *pph = CRC_BF_addEntry( *pph, gi->scalefac_scale, 1 ); *pph = CRC_BF_addEntry( *pph, gi->count1table_select, 1 ); } if ( gfp->stereo == 2 ) bits_sent += 256; else bits_sent += 136; } else { /* MPEG2 */ frameSIPH = CRC_BF_addEntry( frameSIPH, si->main_data_begin, 8 ); if ( gfp->stereo == 2 ) frameSIPH = CRC_BF_addEntry( frameSIPH, si->private_bits, 2 ); else frameSIPH = CRC_BF_addEntry( frameSIPH, si->private_bits, 1 ); gr = 0; for ( ch = 0; ch < gfp->stereo; ch++ ) { BF_PartHolder **pph = &spectrumSIPH[gr][ch]; gr_info *gi = &(si->gr[gr].ch[ch].tt); *pph = CRC_BF_addEntry( *pph, gi->part2_3_length, 12 ); *pph = CRC_BF_addEntry( *pph, gi->big_values, 9 ); *pph = CRC_BF_addEntry( *pph, gi->global_gain, 8 ); *pph = CRC_BF_addEntry( *pph, gi->scalefac_compress, 9 ); *pph = CRC_BF_addEntry( *pph, gi->window_switching_flag, 1 ); if ( gi->window_switching_flag ) { *pph = CRC_BF_addEntry( *pph, gi->block_type, 2 ); *pph = CRC_BF_addEntry( *pph, gi->mixed_block_flag, 1 ); for ( region = 0; region < 2; region++ ) *pph = CRC_BF_addEntry( *pph, gi->table_select[region], 5 ); for ( window = 0; window < 3; window++ ) *pph = CRC_BF_addEntry( *pph, gi->subblock_gain[window], 3 ); } else { for ( region = 0; region < 3; region++ ) *pph = CRC_BF_addEntry( *pph, gi->table_select[region], 5 ); *pph = CRC_BF_addEntry( *pph, gi->region0_count, 4 ); *pph = CRC_BF_addEntry( *pph, gi->region1_count, 3 ); } *pph = CRC_BF_addEntry( *pph, gi->scalefac_scale, 1 ); *pph = CRC_BF_addEntry( *pph, gi->count1table_select, 1 ); } if ( gfp->stereo == 2 ) bits_sent += 136; else bits_sent += 72; } if ( gfp->error_protection ) { /* (jo) error_protection: add crc16 information to header */ headerPH = BF_addEntry( headerPH, crc, 16 ); bits_sent += 16; } return bits_sent; } /* Some combinations of bitrate, Fs, and stereo make it impossible to stuff out a frame using just main_data, due to the limited number of bits to indicate main_data_length. In these situations, we put stuffing bits into the ancillary data... */ static void drain_into_ancillary_data( int lengthInBits ) { /* */ int wordsToSend = lengthInBits / 32; int remainingBits = lengthInBits % 32; int i; /* userFrameDataPH->part->nrEntries set by call to write_ancillary_data() */ userFrameDataPH->part->nrEntries = 0; for ( i = 0; i < wordsToSend; i++ ) userFrameDataPH = BF_addEntry( userFrameDataPH, 0, 32 ); if ( remainingBits ) userFrameDataPH = BF_addEntry( userFrameDataPH, 0, remainingBits ); } /* Note the discussion of huffmancodebits() on pages 28 and 29 of the IS, as well as the definitions of the side information on pages 26 and 27. */ static void Huffmancodebits( BF_PartHolder **pph, int *ix, gr_info *gi ) { int L3_huffman_coder_count1( BF_PartHolder **pph, struct huffcodetab *h, int v, int w, int x, int y ); int region1Start; int region2Start; int i, bigvalues, count1End; int v, w, x, y, bits, cbits, xbits, stuffingBits; unsigned int code, ext; #ifdef DEBUG int bvbits, c1bits; #endif int bitsWritten = 0; /* 1: Write the bigvalues */ bigvalues = gi->big_values * 2; if ( bigvalues ) { if ( !(gi->mixed_block_flag) && (gi->block_type == SHORT_TYPE) ) { /* Three short blocks */ /* Within each scalefactor band, data is given for successive time windows, beginning with window 0 and ending with window 2. Within each window, the quantized values are then arranged in order of increasing frequency... */ int sfb, window, line, start, end; I192_3 *ix_s; ix_s = (I192_3 *) ix; region1Start = 12; region2Start = 576; for ( sfb = 0; sfb < 13; sfb++ ) { unsigned tableindex = 100; start = scalefac_band.s[ sfb ]; end = scalefac_band.s[ sfb+1 ]; if ( start < region1Start ) tableindex = gi->table_select[ 0 ]; else tableindex = gi->table_select[ 1 ]; assert( tableindex < 32 ); for ( window = 0; window < 3; window++ ) for ( line = start; line < end; line += 2 ) { x = (*ix_s)[line][window]; y = (*ix_s)[line + 1][window]; bits = HuffmanCode( tableindex, x, y, &code, &ext, &cbits, &xbits ); *pph = BF_addEntry( *pph, code, cbits ); *pph = BF_addEntry( *pph, ext, xbits ); bitsWritten += bits; } } } else #ifdef ALLOW_MIXED if ( gi->mixed_block_flag && gi->block_type == SHORT_TYPE ) { /* Mixed blocks long, short */ int sfb, window, line, start, end; unsigned tableindex; I192_3 *ix_s; ix_s = (I192_3 *) ix; /* Write the long block region */ tableindex = gi->table_select[0]; if ( tableindex ) for ( i = 0; i < 36; i += 2 ) { x = ix[i]; y = ix[i + 1]; bits = HuffmanCode( tableindex, x, y, &code, &ext, &cbits, &xbits ); *pph = BF_addEntry( *pph, code, cbits ); *pph = BF_addEntry( *pph, ext, xbits ); bitsWritten += bits; } /* Write the short block region */ tableindex = gi->table_select[ 1 ]; assert( tableindex < 32 ); for ( sfb = 3; sfb < 13; sfb++ ) { start = scalefac_band.s[ sfb ]; end = scalefac_band.s[ sfb+1 ]; for ( window = 0; window < 3; window++ ) for ( line = start; line < end; line += 2 ) { x = (*ix_s)[line][window]; y = (*ix_s)[line + 1][window]; bits = HuffmanCode( tableindex, x, y, &code, &ext, &cbits, &xbits ); *pph = BF_addEntry( *pph, code, cbits ); *pph = BF_addEntry( *pph, ext, xbits ); bitsWritten += bits; } } } else #endif { /* Long blocks */ unsigned scalefac_index = 100; if ( gi->mixed_block_flag ) { region1Start = 36; region2Start = 576; } else { scalefac_index = gi->region0_count + 1; assert( scalefac_index < 23 ); region1Start = scalefac_band.l[ scalefac_index ]; scalefac_index += gi->region1_count + 1; assert( scalefac_index < 23 ); region2Start = scalefac_band.l[ scalefac_index ]; } for ( i = 0; i < bigvalues; i += 2 ) { unsigned tableindex = 100; /* get table pointer */ if ( i < region1Start ) { tableindex = gi->table_select[0]; } else if ( i < region2Start ) { tableindex = gi->table_select[1]; } else { tableindex = gi->table_select[2]; } assert( tableindex < 32 ); /* get huffman code */ x = ix[i]; y = ix[i + 1]; if ( tableindex ) { bits = HuffmanCode( tableindex, x, y, &code, &ext, &cbits, &xbits ); *pph = BF_addEntry( *pph, code, cbits ); *pph = BF_addEntry( *pph, ext, xbits ); bitsWritten += bits; } } } } #ifdef DEBUG bvbits = bitsWritten; #endif /* 2: Write count1 area */ assert( (gi->count1table_select < 2) ); count1End = bigvalues + (gi->count1 * 4); assert( count1End <= 576 ); for ( i = bigvalues; i < count1End; i += 4 ) { v = ix[i]; w = ix[i+1]; x = ix[i+2]; y = ix[i+3]; bitsWritten += L3_huffman_coder_count1( pph, &ht[gi->count1table_select + 32], v, w, x, y ); } #ifdef DEBUG c1bits = bitsWritten - bvbits; #endif if ( (stuffingBits = gi->part2_3_length - gi->part2_length - bitsWritten) ) { int stuffingWords = stuffingBits / 32; int remainingBits = stuffingBits % 32; fprintf(stderr,"opps - adding stuffing bits = %i.\n",stuffingBits); fprintf(stderr,"this should not happen...\n"); /* Due to the nature of the Huffman code tables, we will pad with ones */ while ( stuffingWords-- ) *pph = BF_addEntry( *pph, ~(u_int)0, 32 ); if ( remainingBits ) *pph = BF_addEntry( *pph, ~(u_int)0, remainingBits ); bitsWritten += stuffingBits; } assert( bitsWritten == (int)(gi->part2_3_length - gi->part2_length) ); #ifdef DEBUG fprintf(stderr, "## %d Huffman bits written (%02d + %02d), part2_length = %d, part2_3_length = %d, %d stuffing ##\n", bitsWritten, bvbits, c1bits, gi->part2_length, gi->part2_3_length, stuffingBits ); #endif } int abs_and_sign( int *x ) { if ( *x > 0 ) return 0; *x *= -1; return 1; } int L3_huffman_coder_count1( BF_PartHolder **pph, struct huffcodetab *h, int v, int w, int x, int y ) { HUFFBITS huffbits; unsigned int signv, signw, signx, signy, p; int len; int totalBits = 0; signv = abs_and_sign( &v ); signw = abs_and_sign( &w ); signx = abs_and_sign( &x ); signy = abs_and_sign( &y ); /* bug fix from Leonid A. Kulakov 9/1999:*/ p = (v << 3) + (w << 2) + (x << 1) + y; huffbits = h->table[p]; len = h->hlen[ p ]; *pph = BF_addEntry(*pph, huffbits, len); totalBits= 0; #if 0 if ( v ) { *pph = BF_addEntry( *pph, signv, 1 ); totalBits += 1; } if ( w ) { *pph = BF_addEntry( *pph, signw, 1 ); totalBits += 1; } if ( x ) { *pph = BF_addEntry( *pph, signx, 1 ); totalBits += 1; } if ( y ) { *pph = BF_addEntry( *pph, signy, 1 ); totalBits += 1; } #endif p=0; if ( v ) { p = signv; ++totalBits; } if ( w ){ p = 2*p + signw; ++totalBits; } if ( x ) { p = 2*p + signx; ++totalBits; } if ( y ) { p = 2*p + signy; ++totalBits; } *pph = BF_addEntry(*pph, p, totalBits); return totalBits+len; } /* Implements the pseudocode of page 98 of the IS */ int HuffmanCode( int table_select, int x, int y, unsigned int *code, unsigned int *ext, int *cbits, int *xbits ) { unsigned signx, signy, linbitsx, linbitsy, linbits, idx; struct huffcodetab *h; *cbits = 0; *xbits = 0; *code = 0; *ext = 0; if ( table_select == 0 ) return 0; signx = abs_and_sign( &x ); signy = abs_and_sign( &y ); h = &(ht[table_select]); if ( table_select > 15 ) { /* ESC-table is used */ linbits = h->xlen; linbitsx = linbitsy = 0; if ( x > 14 ) { linbitsx = x - 15; assert( linbitsx <= h->linmax ); x = 15; } if ( y > 14 ) { linbitsy = y - 15; assert( linbitsy <= h->linmax ); y = 15; } idx = x * 16 + y; *code = h->table[idx]; *cbits = h->hlen[ idx ]; if ( x > 14 ) { *ext |= linbitsx; *xbits += linbits; } if ( x != 0 ) { *ext <<= 1; *ext |= signx; *xbits += 1; } if ( y > 14 ) { *ext <<= linbits; *ext |= linbitsy; *xbits += linbits; } if ( y != 0 ) { *ext <<= 1; *ext |= signy; *xbits += 1; } } else { /* No ESC-words */ idx = x * 16 + y; *code = h->table[idx]; *cbits += h->hlen[ idx ]; if ( x != 0 ) { *code <<= 1; *code |= signx; *cbits += 1; } if ( y != 0 ) { *code <<= 1; *code |= signy; *cbits += 1; } } assert( *cbits <= 32 ); assert( *xbits <= 32 ); return *cbits + *xbits; }