⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3internals.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
         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 = '\0';
 shiftBits(toPtr, toBitOffset, &zero, 0,
	   actualOutAduSize*8 - numAduBits);

 return 4 + outFr.sideInfoSize + actualOutAduSize;
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -