📄 mp3internals.cpp
字号:
}
}
}
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%08x\n", 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->%d\n", 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: %d\n", 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -