/* 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. */ //--------------------------------------------------------------------------- // Pre-compilation #include "MediaInfo/PreComp.h" #ifdef __BORLANDC__ #pragma hdrstop #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Setup.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if defined(MEDIAINFO_DSDIFF_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Audio/File_Dsdiff.h" #if defined(MEDIAINFO_ID3V2_YES) #include "MediaInfo/Tag/File_Id3v2.h" #endif //MEDIAINFO_ID3V2_YES #include using namespace ZenLib; using namespace std; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Infos //*************************************************************************** //--------------------------------------------------------------------------- static const size_t DSDIFF_lsConfig_Size=5; static const char* DSDIFF_lsConfig[DSDIFF_lsConfig_Size]= { "Front: L R", "", "", "Front: L C R, Side: L R", "Front: L C R, Side: L R, LFE", }; static const char* DSDIFF_lsConfig_ChannelPositions2[]= { "2", "", "", "3/2", "3/2.1", }; static const char* DSDIFF_lsConfig_ChannelLayout[DSDIFF_lsConfig_Size] = { "L R", "", "", "L R C Ls Rs", "L R C LFE Ls Rs", }; //--------------------------------------------------------------------------- static Ztring DSDIFF_CHNL_chID(int32u chID) { switch (chID) { case 0x43202020 : return __T("C"); case 0x4D4C4654 : case 0x534C4654 : return __T("L"); case 0x4D524754 : case 0x53524754 : return __T("R"); case 0x4C532020 : return __T("Ls"); case 0x52532020 : return __T("Rs"); case 0x4C464520 : return __T("LFE"); default : return Ztring().From_CC4(chID).Trim(); } } //--------------------------------------------------------------------------- static void DSDIFF_CHNL_chID_ChannelPositions(int32u chID, int32u& Mask) { switch (chID) { case 0x43202020 : Mask |= 1<<1; break; //C case 0x4D4C4654 : case 0x534C4654 : Mask |= 1<<0; break; //L case 0x4D524754 : case 0x53524754 : Mask |= 1<<2; break; //R case 0x4C532020 : Mask |= 1<<3; break; //Ls case 0x52532020 : Mask |= 1<<4; break; //Rs case 0x4C464520 : Mask |= 1<<5; break; //LFE default : Mask=(int32u)-1; ; //Unknown; } } static Ztring DSDIFF_CHNL_chID_ChannelPositions(int32u Mask) { if (Mask==(int32u)-1) return Ztring(); Ztring ToReturn; if (Mask&((1<<0)|(1<<1)|(1<<2))) { ToReturn+=__T("Front: "); if (Mask&(1<<0)) ToReturn+=__T("L "); if (Mask&(1<<1)) ToReturn+=__T("C "); if (Mask&(1<<2)) ToReturn+=__T("R "); ToReturn.resize(ToReturn.size()-1); } if (Mask&((1<<3)|(1<<4))) { if (!ToReturn.empty()) ToReturn+=__T(", "); ToReturn+=__T("Side: "); if (Mask&(1<<3)) ToReturn+=__T("L "); if (Mask&(1<<4)) ToReturn+=__T("R "); ToReturn.resize(ToReturn.size()-1); } if (Mask&(1<<5)) { if (!ToReturn.empty()) ToReturn+=__T(", "); ToReturn+=__T("LFE"); } return ToReturn; } //--------------------------------------------------------------------------- static void DSDIFF_CHNL_chID_ChannelPositions2(int32u chID, int32u& Mask) { switch (chID) { case 0x43202020 : case 0x4D4C4654 : case 0x534C4654 : case 0x4D524754 : case 0x53524754 : Mask += 1; break; //Front case 0x4C532020 : case 0x52532020 : Mask += 1<<8; break; //Side case 0x4C464520 : Mask += 1<<24; break; //LFE default : Mask = (int32u)-1; ; //Unknown; } } static Ztring DSDIFF_CHNL_chID_ChannelPositions2(int32u Mask) { if (Mask==(int32u)-1) return Ztring(); Ztring ToReturn=Ztring::ToZtring(Mask&0xFF); if ((Mask>>8)&0xFFFF) { ToReturn+=__T('/')+Ztring::ToZtring((Mask>>8)&0xFF); if ((Mask>>16)&0xFF) ToReturn+=__T('/')+Ztring::ToZtring((Mask>>16)&0xFF); } if ((Mask>>24)&0xFF) ToReturn+=__T('.')+Ztring::ToZtring((Mask>>24)&0xFF); return ToReturn; } //*************************************************************************** // Constants //*************************************************************************** //--------------------------------------------------------------------------- namespace Elements { const int64u DSD_ = 0x44534420; const int64u DSD__COMT = 0x434F4D54; const int64u DSD__DIIN = 0x4449494E; const int64u DSD__DIIN_DIAR = 0x44494152; const int64u DSD__DIIN_DITI = 0x44495449; const int64u DSD__DIIN_EMID = 0x454D4944; const int64u DSD__DIIN_MARK = 0x4D41524B; const int64u DSD__DSD_ = 0x44534420; const int64u DSD__DST_ = 0x44535420; const int64u DSD__DST__DSTC = 0x44535443; const int64u DSD__DST__DSTF = 0x44535446; const int64u DSD__DST__FRTE = 0x46525445; const int64u DSD__DSTI = 0x44535449; const int64u DSD__FVER = 0x46564552; const int64u DSD__ID3_ = 0x49443320; const int64u DSD__PROP = 0x50524F50; const int64u DSD__PROP_ABSS = 0x41425353; const int64u DSD__PROP_CHNL = 0x43484E4C; const int64u DSD__PROP_CMPR = 0x434D5052; const int64u DSD__PROP_FS__ = 0x46532020; const int64u DSD__PROP_LSCO = 0x4C53434F; const int64u FRM8 = 0x46524D38; } //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Dsdiff::File_Dsdiff() :File__Analyze() { //Configuration ParserName="Dsdiff"; #if MEDIAINFO_EVENTS //ParserIDs[0]=MediaInfo_Parser_Dsdiff; StreamIDs_Width[0]=0; #endif //MEDIAINFO_EVENTS DataMustAlwaysBeComplete=false; } //--------------------------------------------------------------------------- void File_Dsdiff::Streams_Accept() { Fill(Stream_General, 0, General_Format, "DSDIFF"); Stream_Prepare(Stream_Audio); } //--------------------------------------------------------------------------- void File_Dsdiff::Streams_Finish() { int32u sampleRate=Retrieve(Stream_Audio, 0, Audio_SamplingRate).To_int32u(); if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("DSD")) { int64u DSDsoundData_Size=Retrieve(Stream_Audio, 0, Audio_StreamSize).To_int64u(); int16u numChannels=Retrieve(Stream_Audio, 0, Audio_Channel_s_).To_int16u(); if (DSDsoundData_Size && sampleRate && numChannels) Fill(Stream_Audio, 0, Audio_Duration, ((float64)DSDsoundData_Size)*8*1000/numChannels/sampleRate, 3); } for (int64u Multiplier=64; Multiplier<=512; Multiplier*=2) { int64u BaseFrequency=sampleRate/Multiplier; if (BaseFrequency==48000 || BaseFrequency==44100) { Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, __T("DSD")+Ztring::ToZtring(Multiplier)); break; } } } //*************************************************************************** // Buffer - File header //*************************************************************************** //--------------------------------------------------------------------------- bool File_Dsdiff::FileHeader_Begin() { //Must have enough buffer for having header if (Buffer_Size<4) return false; //Must wait for more data if (Buffer[0]!=0x46 //"FRM8" || Buffer[1]!=0x52 || Buffer[2]!=0x4D || Buffer[3]!=0x38) { Reject(); return false; } Accept(); return true; } //*************************************************************************** // Buffer - Per element //*************************************************************************** //--------------------------------------------------------------------------- void File_Dsdiff::Header_Parse() { //Parsing int64u Size; int32u Name; Get_C4 (Name, "Name"); Get_B8 (Size, "Size"); //Coherency check if (File_Offset+Buffer_Offset+12+Size>File_Size) { if (Element_Level<=2) //Incoherencies info only at the top level chunk IsTruncated(File_Offset+Buffer_Offset+12+Size, false, "DSDIFF"); Size=File_Size-(File_Offset+Buffer_Offset+Element_Offset); } //Top level chunks if (Name==Elements::FRM8) Get_C4 (Name, "Real Name"); //Padding if (Size%2) { pad=true; Size++; } else pad=false; Header_Fill_Code(Name, Ztring().From_CC4(Name)); Header_Fill_Size(Element_Offset+Size); } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Dsdiff::Data_Parse() { if (pad) Element_Size--; //Parsing DATA_BEGIN LIST(DSD_) ATOM_BEGIN ATOM(DSD__COMT) LIST(DSD__DIIN) ATOM_BEGIN ATOM(DSD__DIIN_DIAR) ATOM(DSD__DIIN_DITI) ATOM(DSD__DIIN_EMID) ATOM(DSD__DIIN_MARK) ATOM_END ATOM_PARTIAL(DSD__DSD_) LIST(DSD__DST_) ATOM_BEGIN ATOM(DSD__DST__DSTC) ATOM(DSD__DST__DSTF) ATOM(DSD__DST__FRTE) ATOM_END ATOM_PARTIAL(DSD__DSTI) ATOM(DSD__FVER) ATOM(DSD__ID3_) LIST(DSD__PROP) ATOM_BEGIN ATOM(DSD__PROP_ABSS) ATOM(DSD__PROP_CHNL) ATOM(DSD__PROP_CMPR) ATOM(DSD__PROP_FS__) ATOM(DSD__PROP_LSCO) ATOM_END ATOM_END DATA_END if (pad) { Element_Size++; Skip_B1( "pad"); } } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Dsdiff::DSD_() { Element_Name("Form DSD"); } //--------------------------------------------------------------------------- void File_Dsdiff::DSD__COMT() { Element_Name("Comments"); //Parsing int16u numComments; Get_B2 (numComments, "numComments"); for (int16u i=0; i1) { int32u S=samples%Ratio; if (S || Start) { Abss+='0'+S; Start=true; } Ratio/=10; } Abss+='0'+samples/10; Abss+='0'+samples%10; Fill(Stream_Audio, 0, "TimeCode_FirstFrame", Abss); FILLING_END(); } //--------------------------------------------------------------------------- void File_Dsdiff::DSD__PROP_CHNL() { Element_Name("Channels"); //Parsing int16u numChannels; vector chIDs; Get_B2 (numChannels, "numChannels"); while (Element_Offset