📄 mp3internalshuffman.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// "liveMedia"// Copyright (c) 1996-2004 Live Networks, Inc. All rights reserved.// MP3 internal implementation details (Huffman encoding)// Implementation#include "MP3InternalsHuffman.hh"#include <stdio.h>#include <string.h>#include <stdlib.h>MP3HuffmanEncodingInfo::MP3HuffmanEncodingInfo(Boolean includeDecodedValues) { if (includeDecodedValues) { decodedValues = new unsigned[(SBLIMIT*SSLIMIT + 1)*4]; } else { decodedValues = NULL; }}MP3HuffmanEncodingInfo::~MP3HuffmanEncodingInfo() { delete[] decodedValues;}// This is crufty old code that needs to be cleaned up #####static unsigned debugCount = 0; /* for debugging */#define TRUNC_FAVORavoid updateSideInfoForHuffman(MP3SideInfo& sideInfo, Boolean isMPEG2, unsigned char const* mainDataPtr, unsigned p23L0, unsigned p23L1, unsigned& part23Length0a, unsigned& part23Length0aTruncation, unsigned& part23Length0b, unsigned& part23Length0bTruncation, unsigned& part23Length1a, unsigned& part23Length1aTruncation, unsigned& part23Length1b, unsigned& part23Length1bTruncation) { int i, j; unsigned sfLength, origTotABsize, adjustment; MP3SideInfo::gr_info_s_t* gr; /* First, Huffman-decode each part of the segment's main data, to see at which bit-boundaries the samples appear: */ MP3HuffmanEncodingInfo hei; ++debugCount;#ifdef DEBUG fprintf(stderr, "usifh-start: p23L0: %d, p23L1: %d\n", p23L0, p23L1);#endif /* Process granule 0 */ { gr = &(sideInfo.ch[0].gr[0]); origTotABsize = gr->part2_3_length; MP3HuffmanDecode(gr, isMPEG2, mainDataPtr, 0, origTotABsize, sfLength, hei); /* Begin by computing new sizes for parts a & b (& their truncations) */#ifdef DEBUG fprintf(stderr, "usifh-0: %d, %d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n", hei.numSamples, sfLength/8, sfLength%8, hei.reg1Start/8, hei.reg1Start%8, hei.reg2Start/8, hei.reg2Start%8, hei.bigvalStart/8, hei.bigvalStart%8, origTotABsize/8, origTotABsize%8);#ifdef undef { unsigned k; for (k = 0; k < hei.numSamples; ++k) { fprintf(stderr, " %d:%d", hei.allBitOffsets[k]/8, hei.allBitOffsets[k]%8); } fprintf(stderr, "\n"); }#endif#endif if (p23L0 < sfLength) { /* We can't use this, so give it all to the next granule: */ p23L1 += p23L0; p23L0 = 0; } part23Length0a = hei.bigvalStart; part23Length0b = origTotABsize - hei.bigvalStart; part23Length0aTruncation = part23Length0bTruncation = 0; if (origTotABsize > p23L0) { /* We need to shorten one or both of fields a & b */ unsigned truncation = origTotABsize - p23L0;#ifdef TRUNC_FAIRLY part23Length0aTruncation = (truncation*(part23Length0a-sfLength)) /(origTotABsize-sfLength); part23Length0bTruncation = truncation - part23Length0aTruncation;#endif#ifdef TRUNC_FAVORa part23Length0bTruncation = (truncation > part23Length0b) ? part23Length0b : truncation; part23Length0aTruncation = truncation - part23Length0bTruncation;#endif#ifdef TRUNC_FAVORb part23Length0aTruncation = (truncation > part23Length0a-sfLength) ? (part23Length0a-sfLength) : truncation; part23Length0bTruncation = truncation - part23Length0aTruncation;#endif } /* ASSERT: part23Length0xTruncation <= part23Length0x */ part23Length0a -= part23Length0aTruncation; part23Length0b -= part23Length0bTruncation;#ifdef DEBUG fprintf(stderr, "usifh-0: interim sizes: %d (%d), %d (%d)\n", part23Length0a, part23Length0aTruncation, part23Length0b, part23Length0bTruncation);#endif /* Adjust these new lengths so they end on sample bit boundaries: */ for (i = 0; i < (int)hei.numSamples; ++i) { if (hei.allBitOffsets[i] == part23Length0a) break; else if (hei.allBitOffsets[i] > part23Length0a) {--i; break;} } if (i < 0) { /* should happen only if we couldn't fit sfLength */ i = 0; adjustment = 0; } else { adjustment = part23Length0a - hei.allBitOffsets[i]; }#ifdef DEBUG fprintf(stderr, "%d usifh-0: adjustment 1: %d\n", debugCount, adjustment);#endif part23Length0a -= adjustment; part23Length0aTruncation += adjustment; /* Assign the bits we just shaved to field b and granule 1: */ if (part23Length0bTruncation < adjustment) { p23L1 += (adjustment - part23Length0bTruncation); adjustment = part23Length0bTruncation; } part23Length0b += adjustment; part23Length0bTruncation -= adjustment; for (j = i; j < (int)hei.numSamples; ++j) { if (hei.allBitOffsets[j] == part23Length0a + part23Length0aTruncation + part23Length0b) break; else if (hei.allBitOffsets[j] > part23Length0a + part23Length0aTruncation + part23Length0b) {--j; break;} } if (j < 0) { /* should happen only if we couldn't fit sfLength */ j = 0; adjustment = 0; } else { adjustment = part23Length0a+part23Length0aTruncation+part23Length0b - hei.allBitOffsets[j]; }#ifdef DEBUG fprintf(stderr, "%d usifh-0: adjustment 2: %d\n", debugCount, adjustment);#endif if (adjustment > part23Length0b) adjustment = part23Length0b; /*sanity*/ part23Length0b -= adjustment; part23Length0bTruncation += adjustment; /* Assign the bits we just shaved to granule 1 */ p23L1 += adjustment; if (part23Length0aTruncation > 0) { /* Change the granule's 'big_values' field to reflect the truncation */ gr->big_values = i; } } /* Process granule 1 (MPEG-1 only) */ if (isMPEG2) { part23Length1a = part23Length1b = 0; part23Length1aTruncation = part23Length1bTruncation = 0; } else { unsigned granule1Offset = origTotABsize + sideInfo.ch[1].gr[0].part2_3_length; gr = &(sideInfo.ch[0].gr[1]); origTotABsize = gr->part2_3_length; MP3HuffmanDecode(gr, isMPEG2, mainDataPtr, granule1Offset, origTotABsize, sfLength, hei); /* Begin by computing new sizes for parts a & b (& their truncations) */#ifdef DEBUG fprintf(stderr, "usifh-1: %d, %d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n", hei.numSamples, sfLength/8, sfLength%8, hei.reg1Start/8, hei.reg1Start%8, hei.reg2Start/8, hei.reg2Start%8, hei.bigvalStart/8, hei.bigvalStart%8, origTotABsize/8, origTotABsize%8);#ifdef undef { unsigned k; for (k = 0; k < hei.numSamples; ++k) { fprintf(stderr, " %d:%d", hei.allBitOffsets[k]/8, hei.allBitOffsets[k]%8); } fprintf(stderr, "\n"); }#endif#endif if (p23L1 < sfLength) { /* We can't use this, so give up on this granule: */ p23L1 = 0; } part23Length1a = hei.bigvalStart; part23Length1b = origTotABsize - hei.bigvalStart; part23Length1aTruncation = part23Length1bTruncation = 0; if (origTotABsize > p23L1) { /* We need to shorten one or both of fields a & b */ unsigned truncation = origTotABsize - p23L1;#ifdef TRUNC_FAIRLY part23Length1aTruncation = (truncation*(part23Length1a-sfLength)) /(origTotABsize-sfLength); part23Length1bTruncation = truncation - part23Length1aTruncation;#endif#ifdef TRUNC_FAVORa part23Length1bTruncation = (truncation > part23Length1b) ? part23Length1b : truncation; part23Length1aTruncation = truncation - part23Length1bTruncation;#endif#ifdef TRUNC_FAVORb part23Length1aTruncation = (truncation > part23Length1a-sfLength) ? (part23Length1a-sfLength) : truncation; part23Length1bTruncation = truncation - part23Length1aTruncation;#endif } /* ASSERT: part23Length1xTruncation <= part23Length1x */ part23Length1a -= part23Length1aTruncation; part23Length1b -= part23Length1bTruncation;#ifdef DEBUG fprintf(stderr, "usifh-1: interim sizes: %d (%d), %d (%d)\n", part23Length1a, part23Length1aTruncation, part23Length1b, part23Length1bTruncation);#endif /* Adjust these new lengths so they end on sample bit boundaries: */ for (i = 0; i < (int)hei.numSamples; ++i) { if (hei.allBitOffsets[i] == part23Length1a) break; else if (hei.allBitOffsets[i] > part23Length1a) {--i; break;} } if (i < 0) { /* should happen only if we couldn't fit sfLength */ i = 0; adjustment = 0; } else { adjustment = part23Length1a - hei.allBitOffsets[i]; }#ifdef DEBUG fprintf(stderr, "%d usifh-1: adjustment 0: %d\n", debugCount, adjustment);#endif part23Length1a -= adjustment; part23Length1aTruncation += adjustment; /* Assign the bits we just shaved to field b: */ if (part23Length1bTruncation < adjustment) { adjustment = part23Length1bTruncation; } part23Length1b += adjustment; part23Length1bTruncation -= adjustment; for (j = i; j < (int)hei.numSamples; ++j) { if (hei.allBitOffsets[j] == part23Length1a + part23Length1aTruncation + part23Length1b) break; else if (hei.allBitOffsets[j] > part23Length1a + part23Length1aTruncation + part23Length1b) {--j; break;} } if (j < 0) { /* should happen only if we couldn't fit sfLength */ j = 0; adjustment = 0; } else { adjustment = part23Length1a+part23Length1aTruncation+part23Length1b - hei.allBitOffsets[j]; }#ifdef DEBUG fprintf(stderr, "%d usifh-1: adjustment 1: %d\n", debugCount, adjustment);#endif if (adjustment > part23Length1b) adjustment = part23Length1b; /*sanity*/ part23Length1b -= adjustment; part23Length1bTruncation += adjustment; if (part23Length1aTruncation > 0) { /* Change the granule's 'big_values' field to reflect the truncation */ gr->big_values = i; } }#ifdef DEBUG fprintf(stderr, "usifh-end, new vals: %d (%d), %d (%d), %d (%d), %d (%d)\n", part23Length0a, part23Length0aTruncation, part23Length0b, part23Length0bTruncation, part23Length1a, part23Length1aTruncation, part23Length1b, part23Length1bTruncation);#endif}static void rsf_getline(char* line, unsigned max, unsigned char**fi) { unsigned i; for (i = 0; i < max; ++i) { line[i] = *(*fi)++; if (line[i] == '\n') { line[i++] = '\0'; return; } } line[i] = '\0';}static void rsfscanf(unsigned char **fi, unsigned int* v) { while (sscanf((char*)*fi, "%x", v) == 0) { /* skip past the next '\0' */ while (*(*fi)++ != '\0') {} } /* skip past any white-space before the value: */ while (*(*fi) <= ' ') ++(*fi); /* skip past the value: */ while (*(*fi) > ' ') ++(*fi);}#define HUFFBITS unsigned long int#define SIZEOF_HUFFBITS 4#define HTN 34#define MXOFF 250struct huffcodetab { char tablename[3]; /*string, containing table_description */ unsigned int xlen; /*max. x-index+ */ unsigned int ylen; /*max. y-index+ */ unsigned int linbits; /*number of linbits */ unsigned int linmax; /*max number to be stored in linbits */ int ref; /*a positive value indicates a reference*/ HUFFBITS *table; /*pointer to array[xlen][ylen] */ unsigned char *hlen; /*pointer to array[xlen][ylen] */ unsigned char(*val)[2];/*decoder tree */ unsigned int treelen; /*length of decoder tree */};static struct huffcodetab rsf_ht[HTN]; // array of all huffcodetable headers /* 0..31 Huffman code table 0..31 */ /* 32,33 count1-tables *//* read the huffman decoder table */static int read_decoder_table(unsigned char* fi) { int n,i,nn,t; unsigned int v0,v1; char command[100],line[100]; for (n=0;n<HTN;n++) { rsf_ht[n].table = NULL; rsf_ht[n].hlen = NULL; /* .table number treelen xlen ylen linbits */ do { rsf_getline(line,99,&fi); } while ((line[0] == '#') || (line[0] < ' ')); sscanf(line,"%s %s %u %u %u %u",command,rsf_ht[n].tablename, &rsf_ht[n].treelen, &rsf_ht[n].xlen, &rsf_ht[n].ylen, &rsf_ht[n].linbits); if (strcmp(command,".end")==0) return n; else if (strcmp(command,".table")!=0) {#ifdef DEBUG fprintf(stderr,"huffman table %u data corrupted\n",n);#endif return -1; } rsf_ht[n].linmax = (1<<rsf_ht[n].linbits)-1; sscanf(rsf_ht[n].tablename,"%u",&nn); if (nn != n) {#ifdef DEBUG fprintf(stderr,"wrong table number %u\n",n);#endif return(-2); } do { rsf_getline(line,99,&fi); } while ((line[0] == '#') || (line[0] < ' ')); sscanf(line,"%s %u",command,&t); if (strcmp(command,".reference")==0) { rsf_ht[n].ref = t; rsf_ht[n].val = rsf_ht[t].val; rsf_ht[n].treelen = rsf_ht[t].treelen; if ( (rsf_ht[n].xlen != rsf_ht[t].xlen) || (rsf_ht[n].ylen != rsf_ht[t].ylen) ) {#ifdef DEBUG fprintf(stderr,"wrong table %u reference\n",n);#endif return (-3); }; while ((line[0] == '#') || (line[0] < ' ') ) { rsf_getline(line,99,&fi); } } else if (strcmp(command,".treedata")==0) { rsf_ht[n].ref = -1; rsf_ht[n].val = (unsigned char (*)[2]) new unsigned char[2*(rsf_ht[n].treelen)]; if ((rsf_ht[n].val == NULL) && ( rsf_ht[n].treelen != 0 )){#ifdef DEBUG fprintf(stderr, "heaperror at table %d\n",n);#endif exit (-10); } for (i=0;(unsigned)i<rsf_ht[n].treelen; i++) { rsfscanf(&fi, &v0); rsfscanf(&fi, &v1);/*replaces fscanf(fi,"%x %x",&v0, &v1);*/ rsf_ht[n].val[i][0]=(unsigned char)v0; rsf_ht[n].val[i][1]=(unsigned char)v1; } rsf_getline(line,99,&fi); /* read the rest of the line */ } else {#ifdef DEBUG fprintf(stderr,"huffman decodertable error at table %d\n",n);#endif } } return n;}static void initialize_huffman() { static Boolean huffman_initialized = False; if (huffman_initialized) return; if (read_decoder_table(huffdec) != HTN) {#ifdef DEBUG fprintf(stderr,"decoder table read error\n");#endif exit(4); } huffman_initialized = True;}static unsigned char const slen[2][16] = { {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}};static unsigned char const stab[3][6][4] = { { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} }}; static unsigned rsf_get_scale_factors_1(MP3SideInfo::gr_info_s_t *gr_info) { int numbits; int num0 = slen[0][gr_info->scalefac_compress]; int num1 = slen[1][gr_info->scalefac_compress]; if (gr_info->block_type == 2) { numbits = (num0 + num1) * 18; if (gr_info->mixed_block_flag) { numbits -= num0; /* num0 * 17 + num1 * 18 */ } } else { int scfsi = gr_info->scfsi; if(scfsi < 0) { /* scfsi < 0 => granule == 0 */ numbits = (num0 + num1) * 10 + num0; } else { numbits = 0; if(!(scfsi & 0x8)) { numbits += num0 * 6; } else { } if(!(scfsi & 0x4)) { numbits += num0 * 5; } else { } if(!(scfsi & 0x2)) { numbits += num1 * 5; } else { } if(!(scfsi & 0x1)) { numbits += num1 * 5; } else { } } } return numbits;}extern unsigned n_slen2[];extern unsigned i_slen2[];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -