📄 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.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 + -