mp3_parse.cpp
来自「更新mp3」· C++ 代码 · 共 569 行 · 第 1/2 页
CPP
569 行
switch (_tmpheader->layer) { case 3: _mp3_header_output->layer = MPEGLAYER_I; break; case 2: _mp3_header_output->layer = MPEGLAYER_II; break; case 1: _mp3_header_output->layer = MPEGLAYER_III; break; case 0: this->Clean(); return false; //wouldn't know how to handle it break; default: this->Clean(); return false; //how can two unsigned bits be something else?? break; }; // mpegversion, layer and bitrate are all valid _mp3_header_output->bitrate = _mp3_bitrates[bitrate_index][3-_tmpheader->layer][_tmpheader->bitrate_index]; if (_mp3_header_output->bitrate == MP3BITRATE_FALSE) { this->Clean(); return false; } _mp3_header_output->frequency = _mp3_frequencies[_tmpheader->id][_tmpheader->frequency]; if (_mp3_header_output->frequency == MP3FREQUENCIES_Reserved) { this->Clean(); return false; } _mp3_header_output->privatebit = (bool)_tmpheader->private_bit; _mp3_header_output->copyrighted = (bool)_tmpheader->copyright; _mp3_header_output->original = (bool)_tmpheader->original; _mp3_header_output->crc = (Mp3_Crc)!(bool)_tmpheader->protection_bit; switch (_tmpheader->mode) { case 3: _mp3_header_output->channelmode = MP3CHANNELMODE_SINGLE_CHANNEL; break; case 2: _mp3_header_output->channelmode = MP3CHANNELMODE_DUAL_CHANNEL; break; case 1: _mp3_header_output->channelmode = MP3CHANNELMODE_JOINT_STEREO; break; case 0: _mp3_header_output->channelmode = MP3CHANNELMODE_STEREO; break; default: this->Clean(); return false; //wouldn't know how to handle it break; } if (_mp3_header_output->channelmode == MP3CHANNELMODE_JOINT_STEREO) { // these have a different meaning for different layers, better give them a generic name in the enum switch (_tmpheader->mode_ext) { case 3: _mp3_header_output->modeext = MP3MODEEXT_3; break; case 2: _mp3_header_output->modeext = MP3MODEEXT_2; break; case 1: _mp3_header_output->modeext = MP3MODEEXT_1; break; case 0: _mp3_header_output->modeext = MP3MODEEXT_0; break; default: this->Clean(); return false; //wouldn't know how to handle it break; } } else //it's valid to have a valid false one in this case, since it's only used with joint stereo _mp3_header_output->modeext = MP3MODEEXT_FALSE; switch (_tmpheader->emphasis) { case 3: _mp3_header_output->emphasis = MP3EMPHASIS_CCIT_J17; break; case 2: _mp3_header_output->emphasis = MP3EMPHASIS_Reserved; break; case 1: _mp3_header_output->emphasis = MP3EMPHASIS_50_15MS; break; case 0: _mp3_header_output->emphasis = MP3EMPHASIS_NONE; break; default: this->Clean(); return false; //wouldn't know how to handle it break; }//http://www.mp3-tech.org/programmer/frame_header.html if (_mp3_header_output->bitrate != MP3BITRATE_NONE && _mp3_header_output->frequency > 0) { switch(_mp3_header_output->layer) { case MPEGLAYER_I: // Layer 1 _mp3_header_output->framesize = 4 * (12 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0)); break; case MPEGLAYER_II: // Layer 2 _mp3_header_output->framesize = 144 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0); break; case MPEGLAYER_III: // Layer 3 if(_mp3_header_output->version == MPEGVERSION_2_5) _mp3_header_output->framesize = 144 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0); //Mpeg1 else _mp3_header_output->framesize = 72000 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0); //Mpeg2 + Mpeg2.5 break; }// if (_mp3_header_output->layer == MPEGLAYER_I)// _mp3_header_output->framesize = fto_nearest_i((float)((48 * (float)_mp3_header_output->bitrate) / _mp3_header_output->frequency)) + (_tmpheader->padding_bit ? 4 : 0);// else// _mp3_header_output->framesize = fto_nearest_i((float)((144 * (float)_mp3_header_output->bitrate) / _mp3_header_output->frequency)) + (_tmpheader->padding_bit ? 1 : 0); } else _mp3_header_output->framesize = 0; //unable to determine const size_t CRCSIZE = 2; size_t sideinfo_len; if (_mp3_header_output->version == MPEGVERSION_1) /* MPEG 1 */ sideinfo_len = (_mp3_header_output->channelmode == MP3CHANNELMODE_SINGLE_CHANNEL) ? 4 + 17 : 4 + 32; else /* MPEG 2 */ sideinfo_len = (_mp3_header_output->channelmode == MP3CHANNELMODE_SINGLE_CHANNEL) ? 4 + 9 : 4 + 17; int vbr_header_offest = beg + sideinfo_len; int vbr_frames = 0; sideinfo_len += 2; // add two for the crc itself if ((_mp3_header_output->crc == MP3CRC_OK) && mp3size < sideinfo_len) _mp3_header_output->crc = MP3CRC_ERROR_SIZE; if (_mp3_header_output->crc == MP3CRC_OK) { char audiodata[38 + 1]; //+1 to hold the 0 char uint16 crc16; uint16 crcstored; _mp3_header_output->crc = MP3CRC_MISMATCH; //as a starting point, we assume the worst reader.setCur(beg); reader.readChars(audiodata, sideinfo_len); audiodata[sideinfo_len] = '\0'; crc16 = calcCRC(audiodata, sideinfo_len); beg = end; end = beg + CRCSIZE; reader.setCur(beg); crcstored = (uint16)io::readBENumber(reader, CRCSIZE); // a mismatch doesn't mean the file is unusable // it has just some bits in the wrong place if (crcstored == crc16) _mp3_header_output->crc = MP3CRC_OK; } // read xing/vbr header if present // derived from code in vbrheadersdk.zip // from http://www.xingtech.com/developer/mp3/ const size_t VBR_HEADER_MIN_SIZE = 8; // "xing" + flags are fixed const size_t VBR_HEADER_MAX_SIZE = 116; // frames, bytes, toc and scale are optional if (mp3size >= vbr_header_offest + VBR_HEADER_MIN_SIZE) { char vbrheaderdata[VBR_HEADER_MAX_SIZE+1]; //+1 to hold the 0 char unsigned char *pvbrdata = (unsigned char *)vbrheaderdata; int vbr_filesize = 0; int vbr_scale = 0; int vbr_flags = 0; // get fixed part of vbr header // and check if valid beg = vbr_header_offest; reader.setCur(beg); reader.readChars(vbrheaderdata, VBR_HEADER_MIN_SIZE); vbrheaderdata[VBR_HEADER_MIN_SIZE] = '\0'; if (pvbrdata[0] == 'X' && pvbrdata[1] == 'i' && pvbrdata[2] == 'n' && pvbrdata[3] == 'g') { // get vbr flags pvbrdata += 4; vbr_flags = ExtractI4(pvbrdata); pvbrdata += 4; // read entire vbr header int vbr_header_size = VBR_HEADER_MIN_SIZE + ((vbr_flags & FRAMES_FLAG)? 4:0) + ((vbr_flags & BYTES_FLAG)? 4:0) + ((vbr_flags & TOC_FLAG)? 100:0) + ((vbr_flags & SCALE_FLAG)? 4:0); if (mp3size >= vbr_header_offest + vbr_header_size) { reader.readChars(&vbrheaderdata[VBR_HEADER_MIN_SIZE], vbr_header_size - VBR_HEADER_MIN_SIZE); vbrheaderdata[vbr_header_size] = '\0'; // get frames, bytes, toc and scale if (vbr_flags & FRAMES_FLAG) { vbr_frames = ExtractI4(pvbrdata); pvbrdata +=4; } if (vbr_flags & BYTES_FLAG) { vbr_filesize = ExtractI4(pvbrdata); pvbrdata +=4; } if (vbr_flags & TOC_FLAG) { // seek offsets // we are not using // for(i=0;i<100;i++) seek_offsets[i] = pvbrdata[i]; pvbrdata +=100; } if (vbr_flags & SCALE_FLAG) { vbr_scale = ExtractI4(pvbrdata); pvbrdata +=4; } if (vbr_frames > 0) { _mp3_header_output->vbr_bitrate = (((vbr_filesize!=0) ? vbr_filesize : mp3size) / vbr_frames) * _mp3_header_output->frequency / 144; _mp3_header_output->vbr_bitrate -= _mp3_header_output->vbr_bitrate%1000; // round the bitrate: } } } } if (_mp3_header_output->framesize > 0 && mp3size >= _mp3_header_output->framesize) // this means bitrate is not none too { if (vbr_frames == 0) _mp3_header_output->frames = fto_nearest_i((float)mp3size / _mp3_header_output->framesize); else _mp3_header_output->frames = vbr_frames; // bitrate becomes byterate (per second) if divided by 8 if (_mp3_header_output->vbr_bitrate == 0) _mp3_header_output->time = fto_nearest_i( (float)mp3size / (_mp3_header_output->bitrate / 8) ); else _mp3_header_output->time = fto_nearest_i( (float)mp3size / (_mp3_header_output->vbr_bitrate / 8) ); } else { _mp3_header_output->frames = 0; _mp3_header_output->time = 0; } //if we got to here it's okay return true;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?