/* Copyright (c) MediaArea.net SARL. All Rights Reserved. * * Use of this source code is governed by a BSD-style license that can * be found in the License.html file in the root of the source tree. */ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // A good start : http://www.codeproject.com/audio/MPEGAudioInfo.asp // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //--------------------------------------------------------------------------- // Pre-compilation #include "MediaInfo/PreComp.h" #ifdef __BORLANDC__ #pragma hdrstop #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Setup.h" //--------------------------------------------------------------------------- //*************************************************************************** // Constants (Common) //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_MPEGA_YES) || defined(MEDIAINFO_MPEGTS_YES) || defined(MEDIAINFO_MPEGPS_YES) //--------------------------------------------------------------------------- #include "ZenLib/Conf.h" using namespace ZenLib; namespace MediaInfoLib { //--------------------------------------------------------------------------- const char* Mpega_Version[4]= { "MPA2.5", "", "MPA2", "MPA1" }; //--------------------------------------------------------------------------- const char* Mpega_Layer[4]= { "", "L3", "L2", "L1", }; //--------------------------------------------------------------------------- const char* Mpega_Format_Profile_Version[4]= { "Version 2.5", "", "Version 2", "Version 1" }; //--------------------------------------------------------------------------- const char* Mpega_Format_Profile_Layer[4]= { "", "Layer 3", "Layer 2", "Layer 1", }; //--------------------------------------------------------------------------- } //NameSpace //--------------------------------------------------------------------------- #endif //... //--------------------------------------------------------------------------- //*************************************************************************** // //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_MPEGA_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Audio/File_Mpega.h" #include "ZenLib/BitStream.h" #include "ZenLib/Utils.h" #include "MediaInfo/MediaInfo_Config_MediaInfo.h" using namespace ZenLib; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Constants //*************************************************************************** //--------------------------------------------------------------------------- static const char* Mpega_Version_String[4]= { "MPEG-2.5 Audio", "", "MPEG-2 Audio", "MPEG-1 Audio", }; //--------------------------------------------------------------------------- static const char* Mpega_Layer_String[4]= { "", " layer 3", " layer 2", " layer 1", }; //--------------------------------------------------------------------------- static const int16u Mpega_BitRate[4][4][16]= { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio 2.5 layer X {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, //MPEG Audio 2.5 layer 3 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, //MPEG Audio 2.5 layer 2 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}}, //MPEG Audio 2.5 layer 1 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio X layer X {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio X layer 3 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio X layer 2 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //MPEG Audio X layer 1 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio 2 layer X {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, //MPEG Audio 2 layer 3 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, //MPEG Audio 2 layer 2 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}}, //MPEG Audio 2 layer 1 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //MPEG Audio 1 layer X {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, //MPEG Audio 1 layer 3 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, //MPEG Audio 1 layer 2 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}}, //MPEG Audio 1 layer 1 }; //--------------------------------------------------------------------------- static const int16u Mpega_SamplingRate[4][4]= { {11025, 12000, 8000, 0}, //MPEG Audio 2.5 { 0, 0, 0, 0}, //MPEG Audio X {22050, 24000, 16000, 0}, //MPEG Audio 2 {44100, 48000, 32000, 0}, //MPEG Audio 1 }; //--------------------------------------------------------------------------- static const int16u Mpega_Channels[4]= { 2, 2, 2, 1, }; //--------------------------------------------------------------------------- static const char* Mpega_Codec_Profile[4]= { "", "Joint stereo", "Dual mono", "", }; //--------------------------------------------------------------------------- static const char* Mpega_Codec_Profile_Extension[]= { "", "Intensity Stereo", "MS Stereo", "Intensity Stereo + MS Stereo", }; //--------------------------------------------------------------------------- static const char* Mpega_Emphasis[]= { "", "50/15ms", "Reserved", "CCITT", }; //--------------------------------------------------------------------------- static const char* Lame_BitRate_Mode[]= { "", "CBR", "VBR", "VBR", "VBR", "VBR", "VBR", "", "CBR", "VBR", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Lame_Method[]= { "", "CBR", "ABR", "VBR (rh)", "VBR (mtrh)", "VBR (rh)", "VBR", "", "CBR (2-pass)", "ABR (2-pass)", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const int8u Mpega_Coefficient[4][4] = //Samples per Frame / 8 { { 0, 72, 144, 12}, //MPEG Audio 2.5 { 0, 0, 0, 0}, //MPEG Audio X { 0, 72, 144, 12}, //MPEG Audio 2 { 0, 144, 144, 12}, //MPEG Audio 1 }; //--------------------------------------------------------------------------- static const int8u Mpega_SlotSize[4]= //A frame is coposed of slots { 0, // Layer X 1, // Layer3 1, // Layer2 4, // Layer1 }; //--------------------------------------------------------------------------- static const int16u Mpega_CRC12_Table[]= { 0x000, 0x80f, 0x811, 0x01e, 0x82d, 0x022, 0x03c, 0x833, 0x855, 0x05a, 0x044, 0x84b, 0x078, 0x877, 0x869, 0x066, 0x8a5, 0x0aa, 0x0b4, 0x8bb, 0x088, 0x887, 0x899, 0x096, 0x0f0, 0x8ff, 0x8e1, 0x0ee, 0x8dd, 0x0d2, 0x0cc, 0x8c3, 0x945, 0x14a, 0x154, 0x95b, 0x168, 0x967, 0x979, 0x176, 0x110, 0x91f, 0x901, 0x10e, 0x93d, 0x132, 0x12c, 0x923, 0x1e0, 0x9ef, 0x9f1, 0x1fe, 0x9cd, 0x1c2, 0x1dc, 0x9d3, 0x9b5, 0x1ba, 0x1a4, 0x9ab, 0x198, 0x997, 0x989, 0x186, 0xa85, 0x28a, 0x294, 0xa9b, 0x2a8, 0xaa7, 0xab9, 0x2b6, 0x2d0, 0xadf, 0xac1, 0x2ce, 0xafd, 0x2f2, 0x2ec, 0xae3, 0x220, 0xa2f, 0xa31, 0x23e, 0xa0d, 0x202, 0x21c, 0xa13, 0xa75, 0x27a, 0x264, 0xa6b, 0x258, 0xa57, 0xa49, 0x246, 0x3c0, 0xbcf, 0xbd1, 0x3de, 0xbed, 0x3e2, 0x3fc, 0xbf3, 0xb95, 0x39a, 0x384, 0xb8b, 0x3b8, 0xbb7, 0xba9, 0x3a6, 0xb65, 0x36a, 0x374, 0xb7b, 0x348, 0xb47, 0xb59, 0x356, 0x330, 0xb3f, 0xb21, 0x32e, 0xb1d, 0x312, 0x30c, 0xb03, 0xd05, 0x50a, 0x514, 0xd1b, 0x528, 0xd27, 0xd39, 0x536, 0x550, 0xd5f, 0xd41, 0x54e, 0xd7d, 0x572, 0x56c, 0xd63, 0x5a0, 0xdaf, 0xdb1, 0x5be, 0xd8d, 0x582, 0x59c, 0xd93, 0xdf5, 0x5fa, 0x5e4, 0xdeb, 0x5d8, 0xdd7, 0xdc9, 0x5c6, 0x440, 0xc4f, 0xc51, 0x45e, 0xc6d, 0x462, 0x47c, 0xc73, 0xc15, 0x41a, 0x404, 0xc0b, 0x438, 0xc37, 0xc29, 0x426, 0xce5, 0x4ea, 0x4f4, 0xcfb, 0x4c8, 0xcc7, 0xcd9, 0x4d6, 0x4b0, 0xcbf, 0xca1, 0x4ae, 0xc9d, 0x492, 0x48c, 0xc83, 0x780, 0xf8f, 0xf91, 0x79e, 0xfad, 0x7a2, 0x7bc, 0xfb3, 0xfd5, 0x7da, 0x7c4, 0xfcb, 0x7f8, 0xff7, 0xfe9, 0x7e6, 0xf25, 0x72a, 0x734, 0xf3b, 0x708, 0xf07, 0xf19, 0x716, 0x770, 0xf7f, 0xf61, 0x76e, 0xf5d, 0x752, 0x74c, 0xf43, 0xec5, 0x6ca, 0x6d4, 0xedb, 0x6e8, 0xee7, 0xef9, 0x6f6, 0x690, 0xe9f, 0xe81, 0x68e, 0xebd, 0x6b2, 0x6ac, 0xea3, 0x660, 0xe6f, 0xe71, 0x67e, 0xe4d, 0x642, 0x65c, 0xe53, 0xe35, 0x63a, 0x624, 0xe2b, 0x618, 0xe17, 0xe09, 0x606 }; //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Mpega::File_Mpega() :File__Analyze(), File__Tags_Helper() { //File__Tags_Helper Base=this; //Configuration #if MEDIAINFO_TRACE Trace_Layers_Update(8); //Stream #endif //MEDIAINFO_TRACE MustSynchronize=true; Buffer_TotalBytes_FirstSynched_Max=64*1024; PTS_DTS_Needed=true; StreamSource=IsStream; Frame_Count_NotParsedIncluded=0; //In Frame_Count_Valid=0; FrameIsAlwaysComplete=false; CalculateDelay=false; //Temp - BitStream info Surround_Frames=0; Block_Count[0]=0; Block_Count[1]=0; Block_Count[2]=0; Channels_Count[0]=0; Channels_Count[1]=0; Channels_Count[2]=0; Channels_Count[3]=0; Extension_Count[0]=0; Extension_Count[1]=0; Extension_Count[2]=0; Extension_Count[3]=0; Emphasis_Count[0]=0; Emphasis_Count[1]=0; Emphasis_Count[2]=0; Emphasis_Count[3]=0; Scfsi=0; Scalefac=0; Reservoir=0; LastSync_Offset=(int64u)-1; VBR_FileSize=0; VBR_Frames=0; Reservoir_Max=0; Xing_Scale=0; BitRate=0; MpegPsPattern_Count=0; VBR_Frames_IsCbr=false; } //*************************************************************************** // Streams management //*************************************************************************** //--------------------------------------------------------------------------- void File_Mpega::Streams_Fill() { File__Tags_Helper::Stream_Prepare(Stream_Audio); Fill(Stream_Audio, 0, Audio_Format, "MPEG Audio"); if (!Frame_Count) return; //VBR detection without header if (VBR_Frames==0) { //How much kinds of bitrates? if (BitRate_Count.size()>1) BitRate_Mode=__T("VBR"); } Fill(Stream_Audio, 0, Audio_Format_Version, Mpega_Format_Profile_Version[ID]); Fill(Stream_Audio, 0, Audio_Format_Profile, Mpega_Format_Profile_Layer[layer]); if (mode && mode<4) { Fill(Stream_Audio, 0, Audio_Format_Settings, Mpega_Codec_Profile[mode]); Fill(Stream_Audio, 0, Audio_Format_Settings_Mode, Mpega_Codec_Profile[mode]); } if (mode_extension && mode_extension<4) { Fill(Stream_Audio, 0, Audio_Format_Settings, Mpega_Codec_Profile_Extension[mode_extension]); Fill(Stream_Audio, 0, Audio_Format_Settings_ModeExtension, Mpega_Codec_Profile_Extension[mode_extension]); } if (emphasis && emphasis<4) { Fill(Stream_Audio, 0, Audio_Format_Settings, Mpega_Emphasis[emphasis]); Fill(Stream_Audio, 0, Audio_Format_Settings_Emphasis, Mpega_Emphasis[emphasis]); } Fill(Stream_Audio, 0, Audio_Codec, Ztring(Mpega_Version[ID])+Ztring(Mpega_Layer[layer])); Fill(Stream_Audio, 0, Audio_Codec_String, Ztring(Mpega_Version_String[ID])+Ztring(Mpega_Layer_String[layer]), true); Fill(Stream_Audio, 0, Audio_SamplingRate, Mpega_SamplingRate[ID][sampling_frequency]); if (mode<4) { Fill(Stream_Audio, 0, Audio_Channel_s_, Mpega_Channels[mode]); Fill(Stream_Audio, 0, Audio_Codec_Profile, Mpega_Codec_Profile[mode]); } //Bitrate, if CBR if (VBR_Frames==0 && BitRate_Mode!=__T("VBR")) { BitRate_Mode=__T("CBR"); BitRate=Mpega_BitRate[ID][layer][bitrate_index]*1000; Fill(Stream_General, 0, General_OverallBitRate, BitRate); Fill(Stream_Audio, 0, Audio_BitRate, BitRate); if (CalculateDelay && Buffer_TotalBytes_FirstSynched>10 && BitRate>0) { Fill(Stream_Audio, 0, Audio_Delay, Buffer_TotalBytes_FirstSynched*8*1000/BitRate, 0); Fill(Stream_Audio, 0, Audio_Delay_Source, "Stream"); } } //Bitrate mode Fill(Stream_Audio, 0, Audio_BitRate_Mode, BitRate_Mode); Fill(Stream_Audio, 0, Audio_BitRate_Minimum, BitRate_Minimum); Fill(Stream_Audio, 0, Audio_BitRate_Nominal, BitRate_Nominal); #if MEDIAINFO_ADVANCED if (!IsSub && !VBR_Frames && !VBR_FileSize && BitRate_Mode==__T("VBR") && ID<4 && sampling_frequency<4 && Retrieve_Const(Stream_Audio, 0, Audio_BitRate).empty() && Config->File_RiskyBitRateEstimation_Get()) { size_t Divider; if (ID==3 && layer==3) //MPEG 1 layer 1 Divider=384/8; else if ((ID==2 || ID==0) && layer==3) ///MPEG 2 or 2.5 layer 1 Divider=192/8; else if ((ID==2 || ID==0) && layer==1) //MPEG 2 or 2.5 layer 3 Divider=576/8; else Divider=1152/8; BitRate=(int32u)((File_Offset+Buffer_Offset+Element_Size)*Mpega_SamplingRate[ID][sampling_frequency]/Frame_Count/Divider); Fill(Stream_Audio, 0, Audio_BitRate, BitRate); } #endif //MEDIAINFO_ADVANCED //Tags File__Tags_Helper::Streams_Fill(); } //--------------------------------------------------------------------------- void File_Mpega::Streams_Finish() { //Reservoir //Fill("Reservoir_Avg", Reservoir/Frame_Count); //Fill("Reservoir_Max", Reservoir_Max); //size_t Granules=(Mpeg==3?2:1); //size_t Ch=Mpega_Channels[Channels]; //Fill("Scalefactors", Ztring::ToZtring(Scalefac*100/(Granules*Ch*Frame_Count))+__T('%')); //VBR_FileSize calculation if (!IsSub && (File_Size!=(int64u)-1 || LastSync_Offset!=(int64u)-1) && VBR_FileSize==0) { //We calculate VBR_FileSize from the last synch or File_Size if (LastSync_Offset!=(int64u)-1) { VBR_FileSize=LastSync_Offset; VBR_FileSize-=File_BeginTagSize; } else { VBR_FileSize=File_Size; VBR_FileSize-=File_BeginTagSize; VBR_FileSize-=File_EndTagSize; } } //Bitrate calculation if VBR int64u FrameCount=0; if (VBR_Frames>0) { FrameCount=VBR_Frames; float32 FrameLength=((float32)(VBR_FileSize?VBR_FileSize:File_Size-File_EndTagSize-File_BeginTagSize))/VBR_Frames; size_t Divider; if (ID==3 && layer==3) //MPEG 1 layer 1 Divider=384/8; else if ((ID==2 || ID==0) && layer==3) ///MPEG 2 or 2.5 layer 1 Divider=192/8; else if ((ID==2 || ID==0) && layer==1) //MPEG 2 or 2.5 layer 3 Divider=576/8; else Divider=1152/8; if (ID<4 && sampling_frequency<4) BitRate=float32_int32s(FrameLength*Mpega_SamplingRate[ID][sampling_frequency]/Divider); BitRate_Mode=(VBR_Frames_IsCbr?__T("CBR"):__T("VBR")); } //if (BitRate_Count.size()>1) //{ // Ztring BitRate_VBR; // if (!BitRate_VBR.empty()) // BitRate_VBR+=__T(' '); // BitRate_VBR+=Ztring::ToZtring(8); // BitRate_VBR+=__T(':'); // BitRate_VBR+=Ztring::ToZtring(BitRate_Count[8]); // Fill("BitRate_VBR", Ztring::ToZtring(BitRate_Count[8])); //} if (VBR_FileSize) { if (BitRate) { Fill(Stream_General, 0, General_Duration, VBR_FileSize*8*1000/BitRate, 10, true); Fill(Stream_General, 0, General_OverallBitRate, BitRate, 10, true); Fill(Stream_Audio, 0, Audio_BitRate, BitRate, 10, true); if (CalculateDelay && Buffer_TotalBytes_FirstSynched>10 && BitRate>0) { Fill(Stream_Audio, 0, Audio_Delay, Buffer_TotalBytes_FirstSynched*8*1000/BitRate, 0, true); Fill(Stream_Audio, 0, Audio_Delay_Source, "Stream", Unlimited, true, true); } } Fill(Stream_Audio, 0, Audio_StreamSize, VBR_FileSize); } Fill(Stream_Audio, 0, Audio_BitRate_Mode, BitRate_Mode, true); //Encoding library if (Encoded_Library.empty()) Encoded_Library_Guess(); if (!Encoded_Library.empty()) { Ztring Encoded_LibraryZ; Encoded_LibraryZ.From_UTF8(Encoded_Library.c_str()); if (Encoded_LibraryZ.empty()) Encoded_LibraryZ.From_ISO_8859_1(Encoded_Library.c_str()); Fill(Stream_General, 0, General_Encoded_Library, Encoded_LibraryZ, true); Fill(Stream_Audio, 0, Audio_Encoded_Library, Encoded_LibraryZ, true); Fill(Stream_Audio, 0, Audio_Encoded_Library_Settings, Encoded_Library_Settings, true); } //Surround if (Surround_Frames>=Frame_Count*0.9) { //Fill(Stream_Audio, 0, Audio_Channel_s_, 6); } if (FrameInfo.PTS!=(int64u)-1 && FrameInfo.PTS>PTS_Begin) { Fill(Stream_Audio, 0, Audio_Duration, float64_int64s(((float64)(FrameInfo.PTS-PTS_Begin))/1000000)); if (Retrieve(Stream_Audio, 0, Audio_BitRate_Mode)==__T("CBR") && ID<4 && sampling_frequency<4) { int16u Samples; if (ID==3 && layer==3) //MPEG 1 layer 1 Samples=384; else if ((ID==2 || ID==0) && layer==1) //MPEG 2 or 2.5 layer 3 Samples=576; else Samples=1152; float64 Frame_Duration=((float64)1)/Mpega_SamplingRate[ID][sampling_frequency]*Samples; FrameCount=float64_int64s(((float64)(FrameInfo.PTS-PTS_Begin))/1000000000/Frame_Duration); } } if (FrameCount==0 && VBR_FileSize && Retrieve(Stream_Audio, 0, Audio_BitRate_Mode)==__T("CBR") && ID<4 && layer<4 && sampling_frequency<4 && bitrate_index<16 && Mpega_SamplingRate[ID][sampling_frequency]) { float64 Size=((float64)Mpega_Coefficient[ID][layer]*Mpega_BitRate[ID][layer][bitrate_index]*1000/Mpega_SamplingRate[ID][sampling_frequency])*Mpega_SlotSize[layer]; if (Size) FrameCount=float64_int64s(VBR_FileSize/Size); } if (FrameCount) { int16u Samples; if (ID==3 && layer==3) //MPEG 1 layer 1 Samples=384; else if ((ID==2 || ID==0) && layer==1) //MPEG 2 or 2.5 layer 3 Samples=576; else Samples=1152; Fill(Stream_Audio, 0, Audio_FrameCount, FrameCount, 10, true); Fill(Stream_Audio, 0, Audio_SamplingCount, FrameCount*Samples, 10, true); float64 audio_fps = (float64)((float64)Mpega_SamplingRate[ID][sampling_frequency] / (float64)Samples); Fill(Stream_Audio, 0, Audio_FrameRate, audio_fps, 3, true); } File__Tags_Helper::Streams_Finish(); } //*************************************************************************** // Buffer - File header //*************************************************************************** //--------------------------------------------------------------------------- bool File_Mpega::FileHeader_Begin() { //Buffer size if (Buffer_Size<8) return File_Size<8; //Must wait for more data //Detecting WAV/SWF/FLV/ELF/DPG/WM/MZ/DLG files int32u Magic4=CC4(Buffer); int32u Magic3=Magic4>>8; int16u Magic2=Magic4>>16; if (Magic4==0x52494646 || Magic3==0x465753 || Magic3==0x464C56 || Magic4==0x7F454C46 || Magic4==0x44504730 || Magic4==0x3026B275 || Magic2==0x4D5A || Magic4==0x000001BA || Magic4==0x000001B3 || Magic4==0x00000100 || CC8(Buffer+Buffer_Offset)==0x444C472056312E30LL) { File__Tags_Helper::Reject("MPEG Audio"); return false; } //Seems OK if (!Frame_Count_Valid) Frame_Count_Valid=Config->ParseSpeed>=0.5?128:(Config->ParseSpeed>=0.3?32:(IsSub?1:4)); return true; } //*************************************************************************** // Buffer - Synchro //*************************************************************************** //--------------------------------------------------------------------------- bool File_Mpega::Synchronize() { //Tags bool Tag_Found_Begin; if (!File__Tags_Helper::Synchronize(Tag_Found_Begin)) return false; if (Tag_Found_Begin) return true; //Synchro if (Buffer_Offset+3>Buffer_Size) return false; if (!Status[IsAccepted] && Buffer[Buffer_Offset+0]==0x46 //"FLV" && Buffer[Buffer_Offset+1]==0x4C && Buffer[Buffer_Offset+2]==0x56) { File__Tags_Helper::Reject(); //Parser accepts too easily FLV files with MPEG Audio (synchronization lost due to FLV header is not enough), rejecting if FLV magic value is found before the first synchro return false; } //Synchronizing while (Buffer_Offset+4<=Buffer_Size) { while (Buffer_Offset+4<=Buffer_Size) { if (Buffer[Buffer_Offset ]==0xFF && (Buffer[Buffer_Offset+1]&0xE0)==0xE0 && (Buffer[Buffer_Offset+2]&0xF0)!=0xF0 && (Buffer[Buffer_Offset+2]&0x0C)!=0x0C) break; //while() //Tags bool Tag_Found_Synchro; if (!File__Tags_Helper::Synchronize(Tag_Found_Synchro)) return false; if (Tag_Found_Synchro) return true; //Better detect MPEG-PS if (Frame_Count==0 && Buffer[Buffer_Offset ]==0x00 && Buffer[Buffer_Offset+1]==0x00 && Buffer[Buffer_Offset+2]==0x01 && Buffer[Buffer_Offset+3]==0xBA) { MpegPsPattern_Count++; if (MpegPsPattern_Count>=2) { File__Tags_Helper::Reject("MPEG Audio"); return false; } } Buffer_Offset++; } if (Buffer_Offset+4<=Buffer_Size)//Testing if size is coherant { //Retrieving some info int8u ID0 =(CC1(Buffer+Buffer_Offset+1)>>3)&0x03; int8u layer0 =(CC1(Buffer+Buffer_Offset+1)>>1)&0x03; int8u bitrate_index0 =(CC1(Buffer+Buffer_Offset+2)>>4)&0x0F; int8u sampling_frequency0=(CC1(Buffer+Buffer_Offset+2)>>2)&0x03; int8u padding_bit0 =(CC1(Buffer+Buffer_Offset+2)>>1)&0x01; //Coherancy if (Mpega_SamplingRate[ID0][sampling_frequency0]==0 || Mpega_Coefficient[ID0][layer0]==0 || Mpega_BitRate[ID0][layer0][bitrate_index0]==0 || Mpega_SlotSize[layer0]==0) Buffer_Offset++; //False start else { //Testing next start, to be sure size_t Size0=(Mpega_Coefficient[ID0][layer0]*Mpega_BitRate[ID0][layer0][bitrate_index0]*1000/Mpega_SamplingRate[ID0][sampling_frequency0]+(padding_bit0?1:0))*Mpega_SlotSize[layer0]; if (IsSub && Buffer_Offset+Size0==Buffer_Size) break; if (File_Offset+Buffer_Offset+Size0!=File_Size-File_EndTagSize) { //Padding while (Buffer_Offset+Size0+4<=Buffer_Size && Buffer[Buffer_Offset+Size0]==0x00) Size0++; if (Buffer_Offset+Size0+4>Buffer_Size) return false; //Need more data //Tags bool Tag_Found0; if (!File__Tags_Helper::Synchronize(Tag_Found0, Size0)) return false; if (Tag_Found0) return true; if (File_Offset+Buffer_Offset+Size0==File_Size-File_EndTagSize) break; //Testing if ((CC2(Buffer+Buffer_Offset+Size0)&0xFFE0)!=0xFFE0 || (CC1(Buffer+Buffer_Offset+Size0+2)&0xF0)==0xF0 || (CC1(Buffer+Buffer_Offset+Size0+2)&0x0C)==0x0C) { //Testing VBRI in a malformed frame bool VbriFound=false; for (size_t Pos=Buffer_Offset+4; Pos+4>3)&0x03; int8u layer1 =(CC1(Buffer+Buffer_Offset+Size0+1)>>1)&0x03; int8u bitrate_index1 =(CC1(Buffer+Buffer_Offset+Size0+2)>>4)&0x0F; int8u sampling_frequency1=(CC1(Buffer+Buffer_Offset+Size0+2)>>2)&0x03; int8u padding_bit1 =(CC1(Buffer+Buffer_Offset+Size0+2)>>1)&0x01; //Coherancy if (Mpega_SamplingRate[ID1][sampling_frequency1]==0 || Mpega_Coefficient[ID1][layer1]==0 || Mpega_BitRate[ID1][layer1][bitrate_index1]==0 || Mpega_SlotSize[layer1]==0) Buffer_Offset++; //False start else { //Testing next start, to be sure size_t Size1=(Mpega_Coefficient[ID1][layer1]*Mpega_BitRate[ID1][layer1][bitrate_index1]*1000/Mpega_SamplingRate[ID1][sampling_frequency1]+(padding_bit1?1:0))*Mpega_SlotSize[layer1]; if (IsSub && Buffer_Offset+Size0+Size1==Buffer_Size) break; if (File_Offset+Buffer_Offset+Size0+Size1!=File_Size-File_EndTagSize) { //Padding while (Buffer_Offset+Size0+Size1+4<=Buffer_Size && Buffer[Buffer_Offset+Size0+Size1]==0x00) Size0++; if (Buffer_Offset+Size0+Size1+4>Buffer_Size) return false; //Need more data //Tags bool Tag_Found1; if (!File__Tags_Helper::Synchronize(Tag_Found1, Size0+Size1)) return false; if (Tag_Found1) return true; if (File_Offset+Buffer_Offset+Size0+Size1==File_Size-File_EndTagSize) break; //Testing if ((CC2(Buffer+Buffer_Offset+Size0+Size1)&0xFFE0)!=0xFFE0 || (CC1(Buffer+Buffer_Offset+Size0+Size1+2)&0xF0)==0xF0 || (CC1(Buffer+Buffer_Offset+Size0+Size1+2)&0x0C)==0x0C) Buffer_Offset++; else { //Retrieving some info int8u ID2 =(CC1(Buffer+Buffer_Offset+Size0+Size1+1)>>3)&0x03; int8u layer2 =(CC1(Buffer+Buffer_Offset+Size0+Size1+1)>>1)&0x03; int8u bitrate_index2 =(CC1(Buffer+Buffer_Offset+Size0+Size1+2)>>4)&0x0F; int8u sampling_frequency2=(CC1(Buffer+Buffer_Offset+Size0+Size1+2)>>2)&0x03; int8u padding_bit2 =(CC1(Buffer+Buffer_Offset+Size0+Size1+2)>>1)&0x01; //Coherancy if (Mpega_SamplingRate[ID2][sampling_frequency2]==0 || Mpega_Coefficient[ID2][layer2]==0 || Mpega_BitRate[ID2][layer2][bitrate_index2]==0 || Mpega_SlotSize[layer2]==0) Buffer_Offset++; //False start else { //Testing next start, to be sure size_t Size2=(Mpega_Coefficient[ID2][layer2]*Mpega_BitRate[ID2][layer2][bitrate_index2]*1000/Mpega_SamplingRate[ID2][sampling_frequency2]+(padding_bit2?1:0))*Mpega_SlotSize[layer2]; if (IsSub && Buffer_Offset+Size0+Size1+Size2==Buffer_Size) break; if (File_Offset+Buffer_Offset+Size0+Size1+Size2!=File_Size-File_EndTagSize) { //Padding while (Buffer_Offset+Size0+Size1+Size2+4<=Buffer_Size && Buffer[Buffer_Offset+Size0+Size1+Size2]==0x00) Size0++; if (Buffer_Offset+Size0+Size1+Size2+4>Buffer_Size) { if (IsSub || File_Offset+Buffer_Offset+Size0+Size1+Size2Buffer_Size) { if (Buffer_Offset+3==Buffer_Size && (CC2(Buffer+Buffer_Offset)&0xFFE0)!=0xFFE0) Buffer_Offset++; if (Buffer_Offset+2==Buffer_Size && (CC2(Buffer+Buffer_Offset)&0xFFE0)!=0xFFE0) Buffer_Offset++; if (Buffer_Offset+1==Buffer_Size && CC1(Buffer+Buffer_Offset)!=0x00) Buffer_Offset++; return false; } //Synched is OK return true; } //--------------------------------------------------------------------------- bool File_Mpega::Synched_Test() { //Tags if (!File__Tags_Helper::Synched_Test()) return false; //Padding while (Buffer_OffsetBuffer_Size) return false; //Quick test of synchro if (Buffer[Buffer_Offset ]!=0xFF || (Buffer[Buffer_Offset+1]&0xE0)!=0xE0 || (Buffer[Buffer_Offset+2]&0xF0)==0xF0 || (Buffer[Buffer_Offset+2]&0x0C)==0x0C) { SynchLost("MPEG-Audio"); return true; } //Retrieving some info int8u ID0 =(CC1(Buffer+Buffer_Offset+1)>>3)&0x03; int8u layer0 =(CC1(Buffer+Buffer_Offset+1)>>1)&0x03; int8u bitrate_index0 =(CC1(Buffer+Buffer_Offset+2)>>4)&0x0F; int8u sampling_frequency0=(CC1(Buffer+Buffer_Offset+2)>>2)&0x03; if (Mpega_SamplingRate[ID0][sampling_frequency0]==0 || Mpega_Coefficient[ID0][layer0]==0 || Mpega_BitRate[ID0][layer0][bitrate_index0]==0 || Mpega_SlotSize[layer0]==0) { SynchLost("MPEG Audio"); return true; } //We continue return true; } //*************************************************************************** // Buffer - Demux //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_DEMUX bool File_Mpega::Demux_UnpacketizeContainer_Test() { //Retrieving some info int8u ID0 =(CC1(Buffer+Buffer_Offset+1)>>3)&0x03; int8u layer0 =(CC1(Buffer+Buffer_Offset+1)>>1)&0x03; int8u bitrate_index0 =(CC1(Buffer+Buffer_Offset+2)>>4)&0x0F; int8u sampling_frequency0=(CC1(Buffer+Buffer_Offset+2)>>2)&0x03; int8u padding_bit0 =(CC1(Buffer+Buffer_Offset+2)>>1)&0x01; if (Mpega_SamplingRate[ID][sampling_frequency]==0 || Mpega_Coefficient[ID][layer]==0 || Mpega_BitRate[ID][layer][bitrate_index]==0 || Mpega_SlotSize[layer]==0) return true; //Synhro issue #if MEDIAINFO_ADVANCED if (Frame_Count && File_Demux_Unpacketize_StreamLayoutChange_Skip) { int8u mode0 =CC1(Buffer+Buffer_Offset+3)>>6; if (sampling_frequency0!=sampling_frequency_Frame0 || Mpega_Channels[mode0]!=Mpega_Channels[mode_Frame0]) { return true; } } #endif //MEDIAINFO_ADVANCED Demux_Offset=Buffer_Offset+(Mpega_Coefficient[ID0][layer0]*Mpega_BitRate[ID0][layer0][bitrate_index0]*1000/Mpega_SamplingRate[ID0][sampling_frequency0]+(padding_bit0?1:0))*Mpega_SlotSize[layer0]; if (Demux_Offset>Buffer_Size) return false; Demux_UnpacketizeContainer_Demux(); return true; } #endif //MEDIAINFO_DEMUX //*************************************************************************** // Buffer - Per element //*************************************************************************** //--------------------------------------------------------------------------- void File_Mpega::Header_Parse() { //Parsing BS_Begin(); Skip_S2(11, "syncword"); Get_S1 (2, ID, "ID"); Param_Info1(Mpega_Version[ID]); Get_S1 (2, layer, "layer"); Param_Info1(Mpega_Layer[layer]); Get_SB ( protection_bit, "protection_bit"); Get_S1 (4, bitrate_index, "bitrate_index"); Param_Info2(Mpega_BitRate[ID][layer][bitrate_index], " Kbps"); Get_S1 (2, sampling_frequency, "sampling_frequency"); Param_Info2(Mpega_SamplingRate[ID][sampling_frequency], " Hz"); Get_SB ( padding_bit, "padding_bit"); Skip_SB( "private_bit"); Get_S1 (2, mode, "mode"); Param_Info2(Mpega_Channels[mode], " channels"); Param_Info1(Mpega_Codec_Profile[mode]); Get_S1 (2, mode_extension, "mode_extension"); Param_Info1(Mpega_Codec_Profile_Extension[mode_extension]); Get_SB ( copyright, "copyright"); Get_SB ( original_home, "original_home"); Get_S1 (2, emphasis, "emphasis"); Param_Info1(Mpega_Emphasis[emphasis]); BS_End(); //Coherancy if (Mpega_SamplingRate[ID][sampling_frequency]==0 || Mpega_Coefficient[ID][layer]==0 || Mpega_BitRate[ID][layer][bitrate_index]==0 || Mpega_SlotSize[layer]==0) { Element_Offset=1; Header_Fill_Size(1); Header_Fill_Code(0, "False start"); Synched=false; return; } //Filling int64u Size = ((int64u)Mpega_Coefficient[ID][layer] * (int64u)Mpega_BitRate[ID][layer][bitrate_index] * 1000 / (int64u)Mpega_SamplingRate[ID][sampling_frequency] + (padding_bit ? 1 : 0)) * (int64u)Mpega_SlotSize[layer]; //Special case: tags is inside the last frame if (File_Offset+Buffer_Offset+Size>=File_Size-File_EndTagSize) Size=File_Size-File_EndTagSize-(File_Offset+Buffer_Offset); Header_Fill_Size(Size); Header_Fill_Code(0, "frame"); //Filling error detection sampling_frequency_Count[sampling_frequency]++; mode_Count[mode]++; FILLING_BEGIN(); #if MEDIAINFO_DEMUX #if MEDIAINFO_ADVANCED if (!Frame_Count) { File_Demux_Unpacketize_StreamLayoutChange_Skip=Config->File_Demux_Unpacketize_StreamLayoutChange_Skip_Get(); if (File_Demux_Unpacketize_StreamLayoutChange_Skip) { sampling_frequency_Frame0=sampling_frequency; mode_Frame0=mode; } } #endif //MEDIAINFO_ADVANCED #endif //MEDIAINFO_DEMUX FILLING_END(); } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Mpega::Data_Parse() { //If false start if (Element_Size==0) { Element_DoNotShow(); return; } //Partial frame auto FrameSize = ((int64u)Mpega_Coefficient[ID][layer] * (int64u)Mpega_BitRate[ID][layer][bitrate_index] * 1000 / (int64u)Mpega_SamplingRate[ID][sampling_frequency] + (padding_bit ? 1 : 0))* (int64u)Mpega_SlotSize[layer]; auto RealFrameSize = Header_Size + Element_Size; if (RealFrameSize < FrameSize) { IsTruncated(File_Offset+Buffer_Offset+RealFrameSize, true, "MPEG-Audio"); Element_Name("Partial frame"); Skip_XX(Element_Size, "Data"); return; } //PTS Element_Info1C((FrameInfo.PTS!=(int64u)-1), __T("PTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PTS)/1000000))); //Name Element_Info1(__T("Frame ")+Ztring::ToZtring(Frame_Count)); //VBR and library headers if (Frame_Count<3) //No need to do it too much { if (!Header_Xing()) Header_VBRI(); } //Counting if (File_Offset+Buffer_Offset+Element_Size==File_Size-File_EndTagSize) Frame_Count_Valid=Frame_Count; //Finish MPEG Audio frames in case of there are less than Frame_Count_Valid frames if (Frame_Count==0 && Frame_Count_NotParsedIncluded==0) PTS_Begin=FrameInfo.PTS; LastSync_Offset=File_Offset+Buffer_Offset+Element_Size; { int16u Samples; if (ID==3 && layer==3) //MPEG 1 layer 1 Samples=384; else if ((ID==2 || ID==0) && layer==1) //MPEG 2 or 2.5 layer 3 Samples=576; else Samples=1152; Frequency_b=Mpega_SamplingRate[ID][sampling_frequency]; TS_Add(Samples); } //LAME if (Encoded_Library.empty() && (Frame_Count>4); int16u CRC12 =((Buffer[(size_t)(Buffer_Offset+Element_Offset_S+2)]&0x0F)<<8) | Buffer[(size_t)(Buffer_Offset+Element_Offset_S+3)]; if (Element_Offset_S+Surround_Size-4>Element_Size) break; //CRC int16u CRC12_Calculated=0x0FFF; int8u* Data=(int8u*)Buffer+(size_t)(Buffer_Offset+Element_Offset_S+4); if (Element_Offset_S+Surround_Size+4>=Element_Size) break; for (int8u Surround_Pos=0; Surround_Pos>4) ^ *Data++) & 0xff]); if (CRC12_Calculated!=CRC12) break; //Parsing Skip_XX(Element_Offset_S-Element_Offset, "data"); BS_Begin(); Element_Begin1("Surround"); Skip_S2(12, "Sync"); Skip_S1( 8, "Size"); Skip_S2(12, "CRC12"); BS_End(); Skip_XX(Surround_Size-4, "data"); Element_End0(); //Filling Surround_Frames++; break; } } if (Element_Offset1 && !Encoded_Library.empty()) Frame_Count_Valid=Frame_Count; if (!Status[IsAccepted]) File__Analyze::Accept("MPEG Audio"); if (!Status[IsFilled] && Frame_Count>=Frame_Count_Valid) { Fill("MPEG Audio"); //Jumping if (!IsSub && Config->ParseSpeed<1.0 && File_Offset+Buffer_OffsetFile_Size-File_EndTagSize) { Open_Buffer_Unsynch(); File__Analyze::Data_GoTo(File_Size-File_EndTagSize, "Tags inside a frame, parsing the tags"); } FILLING_END(); } //--------------------------------------------------------------------------- void File_Mpega::audio_data_Layer3() { if (mode>=4) return; const bool mono=(mode==3); const bool mpeg1=(ID==3); int16u main_data_end; BS_Begin(); Get_S2 (mpeg1?9:8, main_data_end, "main_data_end"); if ((int32u)main_data_end>Reservoir_Max) Reservoir_Max=main_data_end; Reservoir+=main_data_end; if (mpeg1) //MPEG-1 { Skip_S1(mono?5:3, "private_bits"); } else { Skip_S1(mono?1:2, "private_bits"); } if (mpeg1) //MPEG-1 { Element_Begin1("scfsi"); for(int8u ch=0; chElement_Size-Xing_Header_Offset) return false; //Error tag size //Parsing if (FrameCount) { Get_B4 (VBR_Frames, "FrameCount"); //FrameCount exclude this frame VBR_Frames_IsCbr=(CC4(Xing_Header)==CC4("Info")); } if (FileSize) { int32u VBR_FileSize_Temp; Get_B4 (VBR_FileSize_Temp, "FileSize"); if (VBR_FileSize_Temp>4+Element_Size) VBR_FileSize=VBR_FileSize_Temp-4-Element_Size; //FileSize include the Xing element } if (TOC) Skip_XX(100, "TOC"); if (Scale) Get_B4 (Xing_Scale, "Scale"); string Lib; Element_End0(); Peek_String(4, Lib); if (Lame || Lib=="LAME" || Lib=="GOGO" || Lib=="L3.9") Header_Encoders_Lame(); //Clearing Error detection sampling_frequency_Count.clear(); mode_Count.clear(); return true; } } return false; } //--------------------------------------------------------------------------- bool File_Mpega::Header_VBRI() { const size_t Fraunhofer_Header_Offset=36-4; if (Buffer_Offset+Fraunhofer_Header_Offset+32=32KHz, else 576) --> Duration in samples Get_B2 (TableSize, "TableSize"); Get_B2 (TableScale, "TableScale"); Get_B2 (EntryBytes, "EntryBytes"); Skip_B2( "EntryFrames"); //Count of frames per entry Element_Begin1("Table"); for (int16u Pos=0; Pos '3' // v4 or more || (Tag[4]=='3' && Tag[6]=='9') // v3.9yz-v3.9yz || Tag[4]=='3' && Tag[8]>='0' && Tag[8]<='9') // v3.xy0-v3.xy9 HasInfoTag=true; } if (Name==0x4C414D45 && Tag[4]=='H') // "LAMEH", Helix MP3 encoder HasInfoTag=true; if (Name==0x4C332E39 // "L3.9" && Tag[4]=='9') HasInfoTag=true; //Form old code, to be confirmed: Ugly version string in Lame 3.99.1 "L3.99r1\0". } if (HasInfoTag) { int8u Flags, lowpass, EncodingFlags, BitRate, StereoMode; Param_Info1(Ztring(__T("V "))+Ztring::ToZtring((100-Xing_Scale)/10)); Param_Info1(Ztring(__T("q "))+Ztring::ToZtring((100-Xing_Scale)%10)); Get_String (9, Encoded_Library, "Encoded_Library"); Get_B1 (Flags, "Flags"); if ((Flags&0xF0)<=0x20) //Rev. 0 or 1, http://gabriel.mp3-tech.org/mp3infotag.html and Rev. 2 was seen. { Param_Info1(Lame_Method[Flags&0x0F]); BitRate_Mode=Lame_BitRate_Mode[Flags&0x0F]; if ((Flags&0x0F)==1 || (Flags&0x0F)==8) //2 possible values for CBR VBR_Frames=0; } Get_B1 (lowpass, "Lowpass filter value"); Param_Info2(lowpass*100, " Hz"); Skip_B4( "Peak signal amplitude"); Skip_B2( "Radio Replay Gain"); Skip_B2( "Audiophile Replay Gain"); Get_B1 (EncodingFlags, "Encoding Flags"); Param_Info1(Ztring(__T("ATH Type="))+Ztring::ToZtring(Flags&0x0F)); Skip_Flags(EncodingFlags, 4, "nspsytune"); Skip_Flags(EncodingFlags, 5, "nssafejoint"); Skip_Flags(EncodingFlags, 6, "nogap (after)"); Skip_Flags(EncodingFlags, 7, "nogap (before)"); Get_B1 (BitRate, "BitRate"); Skip_B3( "Encoder delays"); BS_Begin(); Skip_S1(2, "Source sample frequency"); Skip_SB( "unwise settings used"); Get_S1 (3, StereoMode, "Stereo mode"); Skip_S1(2, "noise shapings"); BS_End(); Skip_B1( "MP3 Gain"); Skip_B2( "Preset and surround info"); Skip_B4( "MusicLength"); Skip_B2( "MusicCRC"); Skip_B2( "CRC-16 of Info Tag"); FILLING_BEGIN(); Encoded_Library_Settings+=__T("-m "); switch(StereoMode) { case 0 : Encoded_Library_Settings+=__T("m"); break; case 1 : Encoded_Library_Settings+=__T("s"); break; case 2 : Encoded_Library_Settings+=__T("d"); break; case 3 : Encoded_Library_Settings+=__T("j"); break; case 4 : Encoded_Library_Settings+=__T("f"); break; case 5 : Encoded_Library_Settings+=__T("a"); break; case 6 : Encoded_Library_Settings+=__T("i"); break; default: ; } if (Xing_Scale<=100) //Xing_Scale is used for LAME quality { Encoded_Library_Settings+=__T( " -V ")+Ztring::ToZtring((100-Xing_Scale)/10); Encoded_Library_Settings+=__T( " -q ")+Ztring::ToZtring((100-Xing_Scale)%10); } if (lowpass) Encoded_Library_Settings+=(Encoded_Library_Settings.empty()?__T("-lowpass "):__T(" -lowpass "))+((lowpass%10)?Ztring::ToZtring(((float)lowpass)/10, 1):Ztring::ToZtring(lowpass/10)); switch (Flags&0x0F) { case 2 : case 9 : //ABR Encoded_Library_Settings+=__T(" --abr"); break; case 3 : //VBR (old/rh) Encoded_Library_Settings+=__T(" --vbr-old"); break; case 4 : //VBR (new/mtrh) Encoded_Library_Settings+=__T(" --vbr-new"); break; case 5 : //VBR (?/mt) Encoded_Library_Settings+=__T(" --vbr-mt"); break; default : ; } if (BitRate!=0x00 && BitRate!=0xFF) { switch (Flags&0x0F) { case 1 : case 8 : //CBR Encoded_Library_Settings+=__T(" -b ")+Ztring::ToZtring(BitRate); break; case 2 : case 9 : //ABR BitRate_Nominal.From_Number(BitRate*1000); Encoded_Library_Settings+=__T(" ")+Ztring::ToZtring(BitRate); break; case 3 : //VBR (old/rh) case 4 : //VBR (new/mtrh) case 5 : //VBR (?/mt) BitRate_Minimum.From_Number(BitRate*1000); Encoded_Library_Settings+=__T(" -b ")+Ztring::ToZtring(BitRate); break; default : ; } } FILLING_END(); } else Get_String (20, Encoded_Library, "Encoded_Library"); } void File_Mpega::Encoded_Library_Guess() { //TODO: Not yet enough precise /* if (Block_Count[1]==0) //No short blocks { if (mode==2) //Dual Mono { if (Scfsi>0) //scfsi used {} else //no scfsi { if (Scalefac>0) //scalefacors used {} else //scalefacors not used Encoded_Library="Shine"; } } else //Other than dual mono { if (Extension_Count[1]>0 || Extension_Count[3]>0) //Intensity Stereo Encoded_Library="Xing (very old)"; else //No Intensity Stereo { if (Scfsi>0) //Scfsi used Encoded_Library="Xing (new)"; else //Scsfi not used { if (Channels_Count[2]>0) //Joint Stereo { if (Channels_Count[0]>0) //also includes no Joint Stereo frames { if (padding_bit) //Padding { if (original_home) Encoded_Library="FhG (l3enc)"; else Encoded_Library="FhG (fastenc or mp3enc)"; } else //No padding Encoded_Library="FhG (ACM or producer pro)"; } else //No stereo frames: joint stereo was forced { if (padding_bit && !original_home && !copyright) Encoded_Library="QDesign (fast mode)"; } } else { if (Channels_Count[0]>0 && Scalefac==0 && !original_home) //Stereo Encoded_Library="Plugger"; else Encoded_Library="Xing (old)"; } } } } } else //Short blocks { if (Scfsi) //scfsi used { if (Scalefac>0) //Scalefactor used Encoded_Library="Gogo (after 3.0)"; //Could be lame, but with a label, detected elsewhere before else Encoded_Library="Lame (old) or m3e"; } else //Scfsi not used { if (Scalefac>0) //Scalefactor used { if (padding_bit) { if (original_home) { //10 last bytes //int sum = get_final_sum(data); //if (sum==0) // return guess = __T("FhG (fastenc, low quality mode)"); //else if (sum==10 * 0xFF) // return guess = __T("FhG (l3enc)"); //else if (sum==5 * 0x20) // return guess = __T("FhG (fastenc, medium or high quality mode)"); //else // return guess = __T("FhG (l3enc or fastenc)"); } else { if (Channels_Count[1]>0 && Extension_Count[1]>0) //Joint Stereo and some Intensity Stereo Encoded_Library="Thomson mp3PRO Encoder"; else Encoded_Library="FhG (fastenc or mp3enc)"; } } else //No padding { if (BitRate_Mode.find(__T("VBR"))==0) //VBR Encoded_Library="FhG (fastenc)"; else Encoded_Library="FhG (ACM or producer pro)"; } } else //scalefactors not used { if (Channels_Count[1]>0) //Joint Stereo { if (padding_bit && !original_home && !copyright) Encoded_Library="QDesign"; } else //Joint Stereo not used { if (BitRate_Mode.find(__T("VBR"))==0) //VBR Encoded_Library="Lame (old)"; else //CBR { if (mode==2) //Dual Mono { if (padding_bit) Encoded_Library="Blade"; else Encoded_Library="dist10 encoder or other encoder"; } else //Stereo or Mono { //if (data.av_reservoir < 40 && !data.vbr) //ISO based encoders are unable to properly use bit reservoir... average reservoir usage is about 10 //{ // if (data.padding) // return guess = __T("Blade"); // else // return guess = __T("dist10 encoder or other encoder"); //} //else // return guess = __T("Gogo (before 3.0)"); } } } } } } */ } //*************************************************************************** // C++ //*************************************************************************** } //NameSpace #endif //MEDIAINFO_MPEGA_YES