📄 mp3internals.cpp
字号:
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;#if 0 int powdiff = (single == 3) ? 4 : 0;#endif /* 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);#if 0 gr_info.pow2gain = gainpow2+256 - gr_info.global_gain + powdiff; if (ms_stereo) gr_info.pow2gain += 2;#endif 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 1void 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;}static unsigned MP3BitrateToBitrateIndex(unsigned bitrate /* in kbps */, Boolean isMPEG2) { for (unsigned i = 1; i < 15; ++i) { if (live_tabsel[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 DEBUGfprintf(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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -