MP3Internals.cpp
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:31k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /**********
- This library is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2.1 of the License, or (at your
- option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
- This library 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 Lesser General Public License for
- more details.
- You should have received a copy of the GNU Lesser General Public License
- along 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-2001 Live Networks, Inc. All rights reserved.
- // MP3 internal implementation details
- // Implementation
- #include <stdlib.h>
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #include "MP3Internals.hh"
- // This is crufty old code that needs to be cleaned up #####
- unsigned tabsel_123[2][3][16] = {
- { {32,32,64,96,128,160,192,224,256,288,320,352,384,416,448,448},
- {32,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,384},
- {32,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,320} },
- { {32,32,48,56,64,80,96,112,128,144,160,176,192,224,256,256},
- {8,8,16,24,32,40,48,56,64,80,96,112,128,144,160,160},
- {8,8,16,24,32,40,48,56,64,80,96,112,128,144,160,160} }
- };
- /* Note: tabsel_123[*][*][0 or 15] shouldn't occur; use dummy values there */
- long freqs[7] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 };
- static float ispow[8207];
- static float aa_ca[8], aa_cs[8];
- static float COS1[12][6];
- static float win[4][36];
- static float win1[4][36];
- static float COS9[9];
- static float COS6_1,COS6_2;
- static float tfcos36[9];
- static float tfcos12[3];
- int longLimit[7][23];
- int shortLimit[7][14];
- struct bandInfoStruct {
- int longIdx[23];
- int longDiff[22];
- int shortIdx[14];
- int shortDiff[13];
- };
- struct bandInfoStruct bandInfo[7] = {
- /* MPEG 1.0 */
- { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576},
- {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158},
- {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3},
- {4,4,4,4,6,8,10,12,14,18,22,30,56} } ,
- { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576},
- {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192},
- {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3},
- {4,4,4,4,6,6,10,12,14,16,20,26,66} } ,
- { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} ,
- {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} ,
- {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} ,
- {4,4,4,4,6,8,12,16,20,26,34,42,12} } ,
- /* MPEG 2.0 */
- { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
- {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } ,
- {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} ,
- {4,4,4,6,6,8,10,14,18,26,32,42,18 } } ,
- { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576},
- {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,52,64,70,76,36 } ,
- {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} ,
- {4,4,4,6,8,10,12,14,18,24,32,44,12 } } ,
- { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
- {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 },
- {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3},
- {4,4,4,6,8,10,12,14,18,24,30,40,18 } } ,
- /* MPEG 2.5, wrong! table (it's just a copy of MPEG 2.0/44.1kHz) */
- { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
- {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } ,
- {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} ,
- {4,4,4,6,6,8,10,14,18,26,32,42,18 } } ,
- };
- static int mapbuf0[7][152];
- static int mapbuf1[7][156];
- static int mapbuf2[7][44];
- static int *map[7][3];
- static int *mapend[7][3];
- unsigned int n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */
- unsigned int i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */
- static float tan1_1[16],tan2_1[16],tan1_2[16],tan2_2[16];
- static float pow1_1[2][16],pow2_1[2][16],pow1_2[2][16],pow2_2[2][16];
- // Init tables for layer-3
- static float gainpow2[256+118+4];
- #define MPG_MD_MONO 3
- #ifndef M_PI
- #define M_PI 3.14159265358979323846 /* pi */
- #endif
- #ifndef M_SQRT2
- #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
- #endif
- ////////// MP3FrameParams //////////
- MP3FrameParams::MP3FrameParams()
- : bv(frameBytes, 0, sizeof frameBytes) /* by default */ {
- oldHdr = firstHdr = 0;
- static Boolean doneInit = False;
- if (doneInit) return;
- doneInit = True;
- int i,j,k,l;
- for (i=-256;i<118+4;i++) {
- gainpow2[i+256] = pow((double)2.0,-0.25 * (double) (i+210) );
- }
- for (i=0;i<8207;i++) {
- ispow[i] = pow((double)i,(double)4.0/3.0);
- }
- for (i=0;i<8;i++) {
- static double Ci[8]={-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037};
- double sq=sqrt(1.0+Ci[i]*Ci[i]);
- aa_cs[i] = 1.0/sq;
- aa_ca[i] = Ci[i]/sq;
- }
- for (i=0;i<18;i++) {
- win[0][i] = win[1][i] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+0) +1) ) / cos ( M_PI * (double) (2*(i+0) +19) / 72.0 );
- win[0][i+18] = win[3][i+18] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+18)+1) ) / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 );
- }
- for (i=0;i<6;i++) {
- win[1][i+18] = 0.5 / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 );
- win[3][i+12] = 0.5 / cos ( M_PI * (double) (2*(i+12)+19) / 72.0 );
- win[1][i+24] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+13) ) / cos ( M_PI * (double) (2*(i+24)+19) / 72.0 );
- win[1][i+30] = win[3][i] = 0.0;
- win[3][i+6 ] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*(i+6 )+19) / 72.0 );
- }
- for (i=0;i<9;i++) {
- COS9[i] = cos( M_PI / 18.0 * (double) i);
- }
- for (i=0;i<9;i++) {
- tfcos36[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 36.0 );
- }
- for(i=0;i<3;i++) {
- tfcos12[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 12.0 );
- }
- COS6_1 = cos( M_PI / 6.0 * (double) 1);
- COS6_2 = cos( M_PI / 6.0 * (double) 2);
- for (i=0;i<12;i++) {
- win[2][i] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*i+7) / 24.0 );
- for (j=0;j<6;j++) {
- COS1[i][j] = cos( M_PI / 24.0 * (double) ((2*i+7)*(2*j+1)) );
- }
- }
- for (j=0;j<4;j++) {
- static int len[4] = { 36,36,12,36 };
- for (i=0;i<len[j];i+=2) {
- win1[j][i] = + win[j][i];
- }
- for (i=1;i<len[j];i+=2) {
- win1[j][i] = - win[j][i];
- }
- }
- for (i=0;i<16;i++) {
- double t = tan( (double) i * M_PI / 12.0 );
- tan1_1[i] = t / (1.0+t);
- tan2_1[i] = 1.0 / (1.0 + t);
- tan1_2[i] = M_SQRT2 * t / (1.0+t);
- tan2_2[i] = M_SQRT2 / (1.0 + t);
- for (j=0;j<2;j++) {
- double base = pow(2.0,-0.25*(j+1.0));
- double p1=1.0,p2=1.0;
- if (i > 0) {
- if (i & 1) {
- p1 = pow(base,(i+1.0)*0.5);
- } else {
- p2 = pow(base,i*0.5);
- }
- }
- pow1_1[j][i] = p1;
- pow2_1[j][i] = p2;
- pow1_2[j][i] = M_SQRT2 * p1;
- pow2_2[j][i] = M_SQRT2 * p2;
- }
- }
- for (j=0;j<7;j++) {
- struct bandInfoStruct *bi = &bandInfo[j];
- int *mp;
- int cb,lwin;
- int *bdf;
- mp = map[j][0] = mapbuf0[j];
- bdf = bi->longDiff;
- for (i=0,cb = 0; cb < 8 ; cb++,i+=*bdf++) {
- *mp++ = (*bdf) >> 1;
- *mp++ = i;
- *mp++ = 3;
- *mp++ = cb;
- }
- bdf = bi->shortDiff+3;
- for (cb=3;cb<13;cb++) {
- int l = (*bdf++) >> 1;
- for(lwin=0;lwin<3;lwin++) {
- *mp++ = l;
- *mp++ = i + lwin;
- *mp++ = lwin;
- *mp++ = cb;
- }
- i += 6*l;
- }
- mapend[j][0] = mp;
- mp = map[j][1] = mapbuf1[j];
- bdf = bi->shortDiff+0;
- for (i=0,cb=0;cb<13;cb++) {
- int l = (*bdf++) >> 1;
- for (lwin=0;lwin<3;lwin++) {
- *mp++ = l;
- *mp++ = i + lwin;
- *mp++ = lwin;
- *mp++ = cb;
- }
- i += 6*l;
- }
- mapend[j][1] = mp;
- mp = map[j][2] = mapbuf2[j];
- bdf = bi->longDiff;
- for (cb = 0; cb < 22 ; cb++) {
- *mp++ = (*bdf++) >> 1;
- *mp++ = cb;
- }
- mapend[j][2] = mp;
- }
- for (j=0;j<7;j++) {
- for (i=0;i<23;i++) {
- longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1;
- if (longLimit[j][i] > SBLIMIT) {
- longLimit[j][i] = SBLIMIT;
- }
- }
- for (i=0;i<14;i++) {
- shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1;
- if (shortLimit[j][i] > SBLIMIT) {
- shortLimit[j][i] = SBLIMIT;
- }
- }
- }
- for (i=0;i<5;i++) {
- for (j=0;j<6;j++) {
- for (k=0;k<6;k++) {
- int n = k + j * 6 + i * 36;
- i_slen2[n] = i|(j<<3)|(k<<6)|(3<<12);
- }
- }
- }
- for (i=0;i<4;i++) {
- for (j=0;j<4;j++) {
- for (k=0;k<4;k++) {
- int n = k + j * 4 + i * 16;
- i_slen2[n+180] = i|(j<<3)|(k<<6)|(4<<12);
- }
- }
- }
- for (i=0;i<4;i++) {
- for (j=0;j<3;j++) {
- int n = j + i * 3;
- i_slen2[n+244] = i|(j<<3) | (5<<12);
- n_slen2[n+500] = i|(j<<3) | (2<<12) | (1<<15);
- }
- }
- for (i=0;i<5;i++) {
- for (j=0;j<5;j++) {
- for (k=0;k<4;k++) {
- for (l=0;l<4;l++) {
- int n = l + k * 4 + j * 16 + i * 80;
- n_slen2[n] = i|(j<<3)|(k<<6)|(l<<9)|(0<<12);
- }
- }
- }
- }
- for (i=0;i<5;i++) {
- for (j=0;j<5;j++) {
- for (k=0;k<4;k++) {
- int n = k + j * 4 + i * 20;
- n_slen2[n+400] = i|(j<<3)|(k<<6)|(1<<12);
- }
- }
- }
- }
- MP3FrameParams::~MP3FrameParams() {
- }
- void MP3FrameParams::setParamsFromHeader() {
- if (hdr & (1<<20)) {
- isMPEG2 = (hdr & (1<<19)) ? 0x0 : 0x1;
- isMPEG2_5 = 0;
- }
- else {
- isMPEG2 = 1;
- isMPEG2_5 = 1;
- }
- layer = 4-((hdr>>17)&3);
- if (layer == 4) layer = 3; // layer==4 is not allowed
- bitrateIndex = ((hdr>>12)&0xf);
- if (isMPEG2_5) {
- samplingFreqIndex = 6;
- } else {
- samplingFreqIndex = ((hdr>>10)&0x3) + (isMPEG2*3);
- }
- hasCRC = ((hdr>>16)&0x1)^0x1;
- padding = ((hdr>>9)&0x1);
- extension = ((hdr>>8)&0x1);
- mode = ((hdr>>6)&0x3);
- mode_ext = ((hdr>>4)&0x3);
- copyright = ((hdr>>3)&0x1);
- original = ((hdr>>2)&0x1);
- emphasis = hdr & 0x3;
- stereo = (mode == MPG_MD_MONO) ? 1 : 2;
- if (((hdr>>10)&0x3) == 0x3) {
- #ifdef DEBUG_ERRORS
- fprintf(stderr,"Stream error - hdr: 0x%08xn", hdr);
- #endif
- }
- bitrate = tabsel_123[isMPEG2][layer-1][bitrateIndex];
- samplingFreq = freqs[samplingFreqIndex];
- isStereo = (stereo > 1);
- isFreeFormat = (bitrateIndex == 0);
- frameSize
- = ComputeFrameSize(bitrate, samplingFreq, padding, isMPEG2, layer);
- sideInfoSize = computeSideInfoSize();
- }
- unsigned MP3FrameParams::computeSideInfoSize() {
- unsigned size;
- if (isMPEG2) {
- size = isStereo ? 17 : 9;
- } else {
- size = isStereo ? 32 : 17;
- }
- if (hasCRC) {
- size += 2;
- }
- return size;
- }
- unsigned ComputeFrameSize(unsigned bitrate, unsigned samplingFreq,
- Boolean usePadding, Boolean isMPEG2,
- unsigned char layer) {
- unsigned const bitrateMultiplier = (layer == 1) ? 12000*4 : 144000;
- unsigned framesize;
- framesize = bitrate*bitrateMultiplier;
- framesize /= samplingFreq<<isMPEG2;
- framesize = framesize + usePadding - 4;
- return framesize;
- }
- #if 0
- #define TRUNC_FAIRLY
- static unsigned updateSideInfoSizes(MP3SideInfo& sideInfo, Boolean isMPEG2,
- unsigned char const* mainDataPtr,
- unsigned allowedNumBits,
- unsigned& part23Length0a,
- unsigned& part23Length0aTruncation,
- unsigned& part23Length0b,
- unsigned& part23Length0bTruncation,
- unsigned& part23Length1a,
- unsigned& part23Length1aTruncation,
- unsigned& part23Length1b,
- unsigned& part23Length1bTruncation) {
- unsigned p23L0, p23L1 = 0, p23L0Trunc = 0, p23L1Trunc = 0;
- p23L0 = sideInfo.ch[0].gr[0].part2_3_length;
- p23L1 = isMPEG2 ? 0 : sideInfo.ch[0].gr[1].part2_3_length;
- #ifdef TRUNC_ONLY0
- if (p23L0 < allowedNumBits)
- allowedNumBits = p23L0;
- #endif
- #ifdef TRUNC_ONLY1
- if (p23L1 < allowedNumBits)
- allowedNumBits = p23L1;
- #endif
- if (p23L0 + p23L1 > allowedNumBits) {
- /* We need to shorten one or both fields */
- unsigned truncation = p23L0 + p23L1 - allowedNumBits;
- #ifdef TRUNC_FAIRLY
- p23L0Trunc = (truncation*p23L0)/(p23L0 + p23L1);
- p23L1Trunc = truncation - p23L0Trunc;
- #endif
- #if defined(TRUNC_FAVOR0) || defined(TRUNC_ONLY0)
- p23L1Trunc = (truncation>p23L1) ? p23L1 : truncation;
- p23L0Trunc = truncation - p23L1Trunc;
- #endif
- #if defined(TRUNC_FAVOR1) || defined(TRUNC_ONLY1)
- p23L0Trunc = (truncation>p23L0) ? p23L0 : truncation;
- p23L1Trunc = truncation - p23L0Trunc;
- #endif
- }
- /* ASSERT: (p23L0Trunc <= p23L0) && (p23l1Trunc <= p23L1) */
- p23L0 -= p23L0Trunc; p23L1 -= p23L1Trunc;
- #ifdef DEBUG
- fprintf(stderr, "updateSideInfoSizes (allowed: %d): %d->%d, %d->%dn", allowedNumBits, p23L0+p23L0Trunc, p23L0, p23L1+p23L1Trunc, p23L1);
- #endif
- // The truncations computed above are still estimates. We need to
- // adjust them so that the new fields will continue to end on
- // Huffman-encoded sample boundaries:
- updateSideInfoForHuffman(sideInfo, isMPEG2, mainDataPtr,
- p23L0, p23L1,
- part23Length0a, part23Length0aTruncation,
- part23Length0b, part23Length0bTruncation,
- part23Length1a, part23Length1aTruncation,
- part23Length1b, part23Length1bTruncation);
- p23L0 = part23Length0a + part23Length0b;
- p23L1 = part23Length1a + part23Length1b;
- sideInfo.ch[0].gr[0].part2_3_length = p23L0;
- sideInfo.ch[0].gr[1].part2_3_length = p23L1;
- part23Length0bTruncation
- += sideInfo.ch[1].gr[0].part2_3_length; /* allow for stereo */
- sideInfo.ch[1].gr[0].part2_3_length = 0; /* output mono */
- sideInfo.ch[1].gr[1].part2_3_length = 0; /* output mono */
- return p23L0 + p23L1;
- }
- #endif
- Boolean GetADUInfoFromMP3Frame(unsigned char const* framePtr,
- unsigned totFrameSize,
- unsigned& hdr, unsigned& frameSize,
- MP3SideInfo& sideInfo, unsigned& sideInfoSize,
- unsigned& backpointer, unsigned& aduSize) {
- if (totFrameSize < 4) return False; // there's not enough data
- MP3FrameParams fr;
- fr.hdr = ((unsigned)framePtr[0] << 24) | ((unsigned)framePtr[1] << 16)
- | ((unsigned)framePtr[2] << 8) | (unsigned)framePtr[3];
- fr.setParamsFromHeader();
- fr.setBytePointer(framePtr + 4, totFrameSize - 4); // skip hdr
- frameSize = 4 + fr.frameSize;
- sideInfoSize = fr.sideInfoSize;
- if (totFrameSize < 4 + sideInfoSize) return False; // not enough data
- fr.getSideInfo(sideInfo);
- hdr = fr.hdr;
- backpointer = sideInfo.main_data_begin;
- unsigned numBits = sideInfo.ch[0].gr[0].part2_3_length;
- numBits += sideInfo.ch[0].gr[1].part2_3_length;
- numBits += sideInfo.ch[1].gr[0].part2_3_length;
- numBits += sideInfo.ch[1].gr[1].part2_3_length;
- aduSize = (numBits+7)/8;
- #ifdef DEBUG
- fprintf(stderr, "mp3GetADUInfoFromFrame: hdr: %08x, frameSize: %d, part2_3_lengths: %d,%d,%d,%d, aduSize: %d, backpointer: %dn", hdr, frameSize, sideInfo.ch[0].gr[0].part2_3_length, sideInfo.ch[0].gr[1].part2_3_length, sideInfo.ch[1].gr[0].part2_3_length, sideInfo.ch[1].gr[1].part2_3_length, aduSize, backpointer);
- #endif
- return True;
- }
- static void getSideInfo1(MP3FrameParams& fr, MP3SideInfo& si,
- int stereo, int ms_stereo, long sfreq, int single) {
- int ch, gr;
- int powdiff = (single == 3) ? 4 : 0;
- /* initialize all four "part2_3_length" fields to zero: */
- si.ch[0].gr[0].part2_3_length = 0; si.ch[1].gr[0].part2_3_length = 0;
- si.ch[0].gr[1].part2_3_length = 0; si.ch[1].gr[1].part2_3_length = 0;
- si.main_data_begin = fr.getBits(9);
- if (stereo == 1)
- si.private_bits = fr.getBits(5);
- else
- si.private_bits = fr.getBits(3);
- for (ch=0; ch<stereo; ch++) {
- si.ch[ch].gr[0].scfsi = -1;
- si.ch[ch].gr[1].scfsi = fr.getBits(4);
- }
- for (gr=0; gr<2; gr++) {
- for (ch=0; ch<stereo; ch++) {
- MP3SideInfo::gr_info_s_t& gr_info = si.ch[ch].gr[gr];
- gr_info.part2_3_length = fr.getBits(12);
- gr_info.big_values = fr.getBits(9);
- gr_info.global_gain = fr.getBits(8);
- gr_info.pow2gain = gainpow2+256 - gr_info.global_gain + powdiff;
- if (ms_stereo) gr_info.pow2gain += 2;
- gr_info.scalefac_compress = fr.getBits(4);
- /* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */
- gr_info.window_switching_flag = fr.get1Bit();
- if (gr_info.window_switching_flag) {
- int i;
- gr_info.block_type = fr.getBits(2);
- gr_info.mixed_block_flag = fr.get1Bit();
- gr_info.table_select[0] = fr.getBits(5);
- gr_info.table_select[1] = fr.getBits(5);
- /*
- * table_select[2] not needed, because there is no region2,
- * but to satisfy some verifications tools we set it either.
- */
- gr_info.table_select[2] = 0;
- for (i=0;i<3;i++) {
- gr_info.subblock_gain[i] = fr.getBits(3);
- gr_info.full_gain[i]
- = gr_info.pow2gain + ((gr_info.subblock_gain[i])<<3);
- }
- #ifdef DEBUG_ERRORS
- if (gr_info.block_type == 0) {
- fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.n");
- }
- #endif
- /* region_count/start parameters are implicit in this case. */
- gr_info.region1start = 36>>1;
- gr_info.region2start = 576>>1;
- }
- else
- {
- int i,r0c,r1c;
- for (i=0; i<3; i++) {
- gr_info.table_select[i] = fr.getBits(5);
- }
- r0c = gr_info.region0_count = fr.getBits(4);
- r1c = gr_info.region1_count = fr.getBits(3);
- gr_info.region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ;
- gr_info.region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1;
- gr_info.block_type = 0;
- gr_info.mixed_block_flag = 0;
- }
- gr_info.preflag = fr.get1Bit();
- gr_info.scalefac_scale = fr.get1Bit();
- gr_info.count1table_select = fr.get1Bit();
- }
- }
- }
- static void getSideInfo2(MP3FrameParams& fr, MP3SideInfo& si,
- int stereo, int ms_stereo, long sfreq, int single) {
- int ch;
- int powdiff = (single == 3) ? 4 : 0;
- /* initialize all four "part2_3_length" fields to zero: */
- si.ch[0].gr[0].part2_3_length = 0; si.ch[1].gr[0].part2_3_length = 0;
- si.ch[0].gr[1].part2_3_length = 0; si.ch[1].gr[1].part2_3_length = 0;
- si.main_data_begin = fr.getBits(8);
- if (stereo == 1)
- si.private_bits = fr.get1Bit();
- else
- si.private_bits = fr.getBits(2);
- for (ch=0; ch<stereo; ch++) {
- MP3SideInfo::gr_info_s_t& gr_info = si.ch[ch].gr[0];
- gr_info.part2_3_length = fr.getBits(12);
- si.ch[ch].gr[1].part2_3_length = 0; /* to ensure granule 1 unused */
- gr_info.big_values = fr.getBits(9);
- gr_info.global_gain = fr.getBits(8);
- gr_info.pow2gain = gainpow2+256 - gr_info.global_gain + powdiff;
- if (ms_stereo) gr_info.pow2gain += 2;
- gr_info.scalefac_compress = fr.getBits(9);
- /* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */
- gr_info.window_switching_flag = fr.get1Bit();
- if (gr_info.window_switching_flag) {
- int i;
- gr_info.block_type = fr.getBits(2);
- gr_info.mixed_block_flag = fr.get1Bit();
- gr_info.table_select[0] = fr.getBits(5);
- gr_info.table_select[1] = fr.getBits(5);
- /*
- * table_select[2] not needed, because there is no region2,
- * but to satisfy some verifications tools we set it either.
- */
- gr_info.table_select[2] = 0;
- for (i=0;i<3;i++) {
- gr_info.subblock_gain[i] = fr.getBits(3);
- gr_info.full_gain[i]
- = gr_info.pow2gain + ((gr_info.subblock_gain[i])<<3);
- }
- #ifdef DEBUG_ERRORS
- if (gr_info.block_type == 0) {
- fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.n");
- }
- #endif
- /* region_count/start parameters are implicit in this case. */
- /* check this again! */
- if (gr_info.block_type == 2)
- gr_info.region1start = 36>>1;
- else {
- gr_info.region1start = 54>>1;
- }
- gr_info.region2start = 576>>1;
- }
- else
- {
- int i,r0c,r1c;
- for (i=0; i<3; i++) {
- gr_info.table_select[i] = fr.getBits(5);
- }
- r0c = gr_info.region0_count = fr.getBits(4);
- r1c = gr_info.region1_count = fr.getBits(3);
- gr_info.region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ;
- gr_info.region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1;
- gr_info.block_type = 0;
- gr_info.mixed_block_flag = 0;
- }
- gr_info.scalefac_scale = fr.get1Bit();
- gr_info.count1table_select = fr.get1Bit();
- }
- }
- #define MPG_MD_JOINT_STEREO 1
- void MP3FrameParams::getSideInfo(MP3SideInfo& si) {
- // First skip over the CRC if present:
- if (hasCRC) getBits(16);
- int single = -1;
- int ms_stereo, i_stereo;
- int sfreq = samplingFreqIndex;
- if (stereo == 1) {
- single = 0;
- }
- ms_stereo = (mode == MPG_MD_JOINT_STEREO) && (mode_ext & 0x2);
- i_stereo = (mode == MPG_MD_JOINT_STEREO) && (mode_ext & 0x1);
- if (isMPEG2) {
- getSideInfo2(*this, si, stereo, ms_stereo, sfreq, single);
- } else {
- getSideInfo1(*this, si, stereo, ms_stereo, sfreq, single);
- }
- }
- static void putSideInfo1(BitVector& bv,
- MP3SideInfo const& si, Boolean isStereo) {
- int ch, gr, i;
- int stereo = isStereo ? 2 : 1;
- bv.putBits(si.main_data_begin,9);
- if (stereo == 1)
- bv.putBits(si.private_bits, 5);
- else
- bv.putBits(si.private_bits, 3);
- for (ch=0; ch<stereo; ch++) {
- bv.putBits(si.ch[ch].gr[1].scfsi, 4);
- }
- for (gr=0; gr<2; gr++) {
- for (ch=0; ch<stereo; ch++) {
- MP3SideInfo::gr_info_s_t const& gr_info = si.ch[ch].gr[gr];
- bv.putBits(gr_info.part2_3_length, 12);
- bv.putBits(gr_info.big_values, 9);
- bv.putBits(gr_info.global_gain, 8);
- bv.putBits(gr_info.scalefac_compress, 4);
- bv.put1Bit(gr_info.window_switching_flag);
- if (gr_info.window_switching_flag) {
- bv.putBits(gr_info.block_type, 2);
- bv.put1Bit(gr_info.mixed_block_flag);
- for (i=0; i<2; i++)
- bv.putBits(gr_info.table_select[i], 5);
- for (i=0; i<3; i++)
- bv.putBits(gr_info.subblock_gain[i], 3);
- }
- else {
- for (i=0; i<3; i++)
- bv.putBits(gr_info.table_select[i], 5);
- bv.putBits(gr_info.region0_count, 4);
- bv.putBits(gr_info.region1_count, 3);
- }
- bv.put1Bit(gr_info.preflag);
- bv.put1Bit(gr_info.scalefac_scale);
- bv.put1Bit(gr_info.count1table_select);
- }
- }
- }
- static void putSideInfo2(BitVector& bv,
- MP3SideInfo const& si, Boolean isStereo) {
- int ch, i;
- int stereo = isStereo ? 2 : 1;
- bv.putBits(si.main_data_begin,8);
- if (stereo == 1)
- bv.put1Bit(si.private_bits);
- else
- bv.putBits(si.private_bits, 2);
- for (ch=0; ch<stereo; ch++) {
- MP3SideInfo::gr_info_s_t const& gr_info = si.ch[ch].gr[0];
- bv.putBits(gr_info.part2_3_length, 12);
- bv.putBits(gr_info.big_values, 9);
- bv.putBits(gr_info.global_gain, 8);
- bv.putBits(gr_info.scalefac_compress, 9);
- bv.put1Bit(gr_info.window_switching_flag);
- if (gr_info.window_switching_flag) {
- bv.putBits(gr_info.block_type, 2);
- bv.put1Bit(gr_info.mixed_block_flag);
- for (i=0; i<2; i++)
- bv.putBits(gr_info.table_select[i], 5);
- for (i=0; i<3; i++)
- bv.putBits(gr_info.subblock_gain[i], 3);
- }
- else {
- for (i=0; i<3; i++)
- bv.putBits(gr_info.table_select[i], 5);
- bv.putBits(gr_info.region0_count, 4);
- bv.putBits(gr_info.region1_count, 3);
- }
- bv.put1Bit(gr_info.scalefac_scale);
- bv.put1Bit(gr_info.count1table_select);
- }
- }
- static void PutMP3SideInfoIntoFrame(MP3SideInfo const& si,
- MP3FrameParams const& fr,
- unsigned char* framePtr) {
- if (fr.hasCRC) framePtr += 2; // skip CRC
- BitVector bv(framePtr, 0, 8*fr.sideInfoSize);
- if (fr.isMPEG2) {
- putSideInfo2(bv, si, fr.isStereo);
- } else {
- putSideInfo1(bv, si, fr.isStereo);
- }
- }
- Boolean ZeroOutMP3SideInfo(unsigned char* framePtr, unsigned totFrameSize,
- unsigned newBackpointer) {
- if (totFrameSize < 4) return False; // there's not enough data
- MP3FrameParams fr;
- fr.hdr = ((unsigned)framePtr[0] << 24) | ((unsigned)framePtr[1] << 16)
- | ((unsigned)framePtr[2] << 8) | (unsigned)framePtr[3];
- fr.setParamsFromHeader();
- fr.setBytePointer(framePtr + 4, totFrameSize - 4); // skip hdr
- if (totFrameSize < 4 + fr.sideInfoSize) return False; // not enough data
- MP3SideInfo si;
- fr.getSideInfo(si);
- si.main_data_begin = newBackpointer; /* backpointer */
- /* set all four "part2_3_length" and "big_values" fields to zero: */
- si.ch[0].gr[0].part2_3_length = si.ch[0].gr[0].big_values = 0;
- si.ch[1].gr[0].part2_3_length = si.ch[1].gr[0].big_values = 0;
- si.ch[0].gr[1].part2_3_length = si.ch[0].gr[1].big_values = 0;
- si.ch[1].gr[1].part2_3_length = si.ch[1].gr[1].big_values = 0;
- PutMP3SideInfoIntoFrame(si, fr, framePtr + 4);
- return True;
- }
- #if 0
- static unsigned MP3BitrateToBitrateIndex(unsigned bitrate /* in kbps */,
- Boolean isMPEG2) {
- for (unsigned i = 1; i < 15; ++i) {
- if (tabsel_123[isMPEG2][2][i] >= bitrate)
- return i;
- }
- // "bitrate" was larger than any possible, so return the largest possible:
- return 14;
- }
- static void outputHeader(unsigned char* toPtr, unsigned hdr) {
- toPtr[0] = (unsigned char)(hdr>>24);
- toPtr[1] = (unsigned char)(hdr>>16);
- toPtr[2] = (unsigned char)(hdr>>8);
- toPtr[3] = (unsigned char)(hdr);
- }
- static void assignADUBackpointer(MP3FrameParams const& fr,
- unsigned aduSize,
- MP3SideInfo& sideInfo,
- unsigned& availableBytesForBackpointer) {
- // Give the ADU as large a backpointer as possible:
- unsigned maxBackpointerSize = fr.isMPEG2 ? 255 : 511;
- unsigned backpointerSize = availableBytesForBackpointer;
- if (backpointerSize > maxBackpointerSize) {
- backpointerSize = maxBackpointerSize;
- }
- // Store the new backpointer now:
- sideInfo.main_data_begin = backpointerSize;
- // Figure out how many bytes are available for the *next* ADU's backpointer:
- availableBytesForBackpointer
- = backpointerSize + fr.frameSize - fr.sideInfoSize ;
- if (availableBytesForBackpointer < aduSize) {
- availableBytesForBackpointer = 0;
- } else {
- availableBytesForBackpointer -= aduSize;
- }
- }
- unsigned TranscodeMP3ADU(unsigned char const* fromPtr, unsigned fromSize,
- unsigned toBitrate,
- unsigned char* toPtr, unsigned toMaxSize,
- unsigned& availableBytesForBackpointer) {
- // Begin by parsing the input ADU's parameters:
- unsigned hdr, inFrameSize, inSideInfoSize, backpointer, inAduSize;
- MP3SideInfo sideInfo;
- if (!GetADUInfoFromMP3Frame(fromPtr, fromSize,
- hdr, inFrameSize, sideInfo, inSideInfoSize,
- backpointer, inAduSize)) {
- return 0;
- }
- fromPtr += (4+inSideInfoSize); // skip to 'main data'
- // Alter the 4-byte MPEG header to reflect the output ADU:
- // (different bitrate; mono; no CRC)
- Boolean isMPEG2 = ((hdr&0x00080000) == 0);
- unsigned toBitrateIndex = MP3BitrateToBitrateIndex(toBitrate, isMPEG2);
- hdr &=~ 0xF000; hdr |= (toBitrateIndex<<12); // set bitrate index
- hdr |= 0x10200; // turn on !error-prot and padding bits
- hdr &=~ 0xC0; hdr |= 0xC0; // set mode to 3 (mono)
- // Set up the rest of the parameters of the new ADU:
- MP3FrameParams outFr;
- outFr.hdr = hdr;
- outFr.setParamsFromHeader();
- // Figure out how big to make the output ADU:
- unsigned inAveAduSize = inFrameSize - inSideInfoSize;
- unsigned outAveAduSize = outFr.frameSize - outFr.sideInfoSize;
- unsigned desiredOutAduSize /*=inAduSize*outAveAduSize/inAveAduSize*/
- = (2*inAduSize*outAveAduSize + inAveAduSize)/(2*inAveAduSize);
- // this rounds to the nearest integer
- if (toMaxSize < (4 + outFr.sideInfoSize)) return 0;
- unsigned maxOutAduSize = toMaxSize - (4 + outFr.sideInfoSize);
- if (desiredOutAduSize > maxOutAduSize) {
- desiredOutAduSize = maxOutAduSize;
- }
- // Figure out the new sizes of the various 'part23 lengths',
- // and how much they are truncated:
- unsigned part23Length0a, part23Length0aTruncation;
- unsigned part23Length0b, part23Length0bTruncation;
- unsigned part23Length1a, part23Length1aTruncation;
- unsigned part23Length1b, part23Length1bTruncation;
- unsigned numAduBits
- = updateSideInfoSizes(sideInfo, outFr.isMPEG2,
- fromPtr, 8*desiredOutAduSize,
- part23Length0a, part23Length0aTruncation,
- part23Length0b, part23Length0bTruncation,
- part23Length1a, part23Length1aTruncation,
- part23Length1b, part23Length1bTruncation);
- #ifdef DEBUG
- fprintf(stderr, "shrinkage %d->%d [(%d,%d),(%d,%d)] (trunc: [(%d,%d),(%d,%d)]) {%d}n", inAduSize, (numAduBits+7)/8,
- part23Length0a, part23Length0b, part23Length1a, part23Length1b,
- part23Length0aTruncation, part23Length0bTruncation,
- part23Length1aTruncation, part23Length1bTruncation,
- maxOutAduSize);
- #endif
- unsigned actualOutAduSize = (numAduBits+7)/8;
- // Give the new ADU an appropriate 'backpointer':
- assignADUBackpointer(outFr, actualOutAduSize, sideInfo, availableBytesForBackpointer);
- ///// Now output the new ADU:
- // 4-byte header
- outputHeader(toPtr, hdr); toPtr += 4;
- // side info
- PutMP3SideInfoIntoFrame(sideInfo, outFr, toPtr); toPtr += outFr.sideInfoSize;
- // 'main data', using the new lengths
- unsigned toBitOffset = 0;
- unsigned fromBitOffset = 0;
- /* rebuild portion 0a: */
- memmove(toPtr, fromPtr, (part23Length0a+7)/8);
- toBitOffset += part23Length0a;
- fromBitOffset += part23Length0a + part23Length0aTruncation;
- /* rebuild portion 0b: */
- shiftBits(toPtr, toBitOffset, fromPtr, fromBitOffset, part23Length0b);
- toBitOffset += part23Length0b;
- fromBitOffset += part23Length0b + part23Length0bTruncation;
- /* rebuild portion 1a: */
- shiftBits(toPtr, toBitOffset, fromPtr, fromBitOffset, part23Length1a);
- toBitOffset += part23Length1a;
- fromBitOffset += part23Length1a + part23Length1aTruncation;
- /* rebuild portion 1b: */
- shiftBits(toPtr, toBitOffset, fromPtr, fromBitOffset, part23Length1b);
- toBitOffset += part23Length1b;
- /* zero out any remaining bits (probably unnecessary, but...) */
- unsigned char const zero = ' ';
- shiftBits(toPtr, toBitOffset, &zero, 0,
- actualOutAduSize*8 - numAduBits);
- return 4 + outFr.sideInfoSize + actualOutAduSize;
- }
- #endif