⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3fileinfo.cpp

📁 mp3
💻 CPP
字号:
/*

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                        MP3FileInfo 1.0
                    -----------------------

  MP3FileInfo is a wrapper class for id3lib, a library capable
  of reading and writing ID3 Tags of MP3 Files. It has a
  simple interface and provides all data as public members.

  Written by Christian Richardt (cr@whizer.net).

  Release history:
    Mai 31, 2003: Version 1.0. First release.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/

/**
  \file    MP3FileInfo.cpp
  \brief   Reads Header and ID3 Tags of MP3 Files
  \date    2003-05-31
  \author  Christian Richardt (cr@whizer.net)
**/


  #include <MP3FileInfo.h>
  #include <assert.h>
  #include <stdio.h>



/* ----------------------- Init and Free ------------------------ */


    /**
      \brief   Initialize and parse all data

      Always Initalize this class by calling Init(). It returns
      false if an error occured.

      You can call Init() as often as you want. All data is being
      freed before extracting the data of the new file.
    **/
  bool MP3FileInfo::Init(const char* cszFilename)
   {
    Free();
    m_bOK = true;

      // copy filename
    szFilename = new char[strlen(cszFilename)+1];
    sprintf(szFilename, cszFilename);

    m_id3tag = new ID3_Tag;
    m_id3tag->Link(szFilename);

    /* Fileinfo */
    bHasLyrics = m_id3tag->HasLyrics();
    bHasV1Tag  = m_id3tag->HasV1Tag();
    bHasV2Tag  = m_id3tag->HasV2Tag();
    nFileSize  = (int)m_id3tag->GetFileSize();

    /* Headerinfo */
    m_parseHeader();
    if(!m_bOK) { Free(); return m_bOK; }

    /* V1 up */
    szAlbum   = m_getNewString(ID3FID_ALBUM);
    szArtist  = m_getNewString(ID3FID_LEADARTIST);
    szComment = m_getNewString(ID3FID_COMMENT);
    szTitle   = m_getNewString(ID3FID_TITLE);
    szTrack   = m_getNewString(ID3FID_TRACKNUM);
    szYear    = m_getNewString(ID3FID_YEAR);

    /* V2 */
    szComposer        = m_getNewString(ID3FID_COMPOSER);
    szCopyright       = m_getNewString(ID3FID_COPYRIGHT);
    szEncodedBy       = m_getNewString(ID3FID_ENCODEDBY);
    szOriginalArtist  = m_getNewString(ID3FID_ORIGARTIST);
    szURL             = m_getNewString(ID3FID_WWWUSER);

    m_parseGenre();
    if(szYear)  sscanf(szYear,  "%i", &nYear);
    if(szTrack) sscanf(szTrack, "%i", &nTrack);

    return m_bOK;
   }


    /**
      \brief   Free all allocated ressources

      You can call Free() as often as you want.
      No error is raised.
    **/
  void MP3FileInfo::Free(void)
   {
    if(m_bOK) // only free if OK
     {
      m_bOK = false;

      if(m_id3tag!=0)
       {
          // in rare cases (e.g. if file is corrupt)
          // "delete m_id3tag" fails ...
        try { delete m_id3tag; } catch(...) {}
        m_id3tag = 0;
       }

      /* fileinfo */
      delete[] szFilename; szFilename = 0; nFileSize = -1;
      bHasLyrics = false; bHasV1Tag = false; bHasV2Tag = false;

      /* headerinfo */
      m_mp3header = 0;
      nVbrBitRate = 0; nBitRate = 0; nCbrBitRate = 0;
      nSampleRate = 0; nLength  = 0;
      delete[] szBitRate;     szBitRate = 0;
      delete[] szMpegLayer;   szMpegLayer = 0;
      delete[] szMpegVersion; szMpegVersion = 0;
      delete[] szChannelMode; szChannelMode = 0;

      /* ID3V1 Tag elements */
      nTrack = 0; nYear = 0;
      delete[] szArtist;  szArtist  = 0;
      delete[] szTitle;   szTitle   = 0;
      delete[] szAlbum;   szAlbum   = 0;
      delete[] szComment; szComment = 0;
      delete[] szTrack;   szTrack   = 0;
      delete[] szYear;    szYear    = 0;
      delete[] szGenre;   szGenre   = 0;

      /* V2 up */
      delete[] szComposer;        szComposer= 0;
      delete[] szCopyright;       szCopyright= 0;
      delete[] szEncodedBy;       szEncodedBy= 0;
      delete[] szOriginalArtist;  szOriginalArtist= 0;
      delete[] szURL;             szURL= 0;
     }
   }


/* ---------------- public member functions ---------------- */


    /// prints all frames the file contains
  void MP3FileInfo::ShowAllFrames(void)
   {
    assert(m_bOK);

      // all FrameIDs
    ID3_FrameID fids[] = { ID3FID_NOFRAME,          ID3FID_AUDIOCRYPTO,     ID3FID_PICTURE,             ID3FID_AUDIOSEEKPOINT,  ID3FID_COMMENT,
                           ID3FID_COMMERCIAL,       ID3FID_CRYPTOREG,       ID3FID_EQUALIZATION2,       ID3FID_EQUALIZATION,    ID3FID_EVENTTIMING,
                           ID3FID_GENERALOBJECT,    ID3FID_GROUPINGREG,     ID3FID_INVOLVEDPEOPLE,      ID3FID_LINKEDINFO,      ID3FID_CDID,
                           ID3FID_MPEGLOOKUP,       ID3FID_OWNERSHIP,       ID3FID_PRIVATE,             ID3FID_PLAYCOUNTER,     ID3FID_POPULARIMETER,
                           ID3FID_POSITIONSYNC,     ID3FID_BUFFERSIZE,      ID3FID_VOLUMEADJ2,          ID3FID_VOLUMEADJ,       ID3FID_REVERB,
                           ID3FID_SEEKFRAME,        ID3FID_SIGNATURE,       ID3FID_SYNCEDLYRICS,        ID3FID_SYNCEDTEMPO,     ID3FID_ALBUM,
                           ID3FID_BPM,              ID3FID_COMPOSER,        ID3FID_CONTENTTYPE,         ID3FID_COPYRIGHT,       ID3FID_DATE,
                           ID3FID_ENCODINGTIME,     ID3FID_PLAYLISTDELAY,   ID3FID_ORIGRELEASETIME,     ID3FID_RECORDINGTIME,   ID3FID_RELEASETIME,
                           ID3FID_TAGGINGTIME,      ID3FID_INVOLVEDPEOPLE2, ID3FID_ENCODEDBY,           ID3FID_LYRICIST,        ID3FID_FILETYPE,
                           ID3FID_TIME,             ID3FID_CONTENTGROUP,    ID3FID_TITLE,               ID3FID_SUBTITLE,        ID3FID_INITIALKEY,
                           ID3FID_LANGUAGE,         ID3FID_SONGLEN,         ID3FID_MUSICIANCREDITLIST,  ID3FID_MEDIATYPE,       ID3FID_MOOD,
                           ID3FID_ORIGALBUM,        ID3FID_ORIGFILENAME,    ID3FID_ORIGLYRICIST,        ID3FID_ORIGARTIST,      ID3FID_ORIGYEAR,
                           ID3FID_FILEOWNER,        ID3FID_LEADARTIST,      ID3FID_BAND,                ID3FID_CONDUCTOR,       ID3FID_MIXARTIST,
                           ID3FID_PARTINSET,        ID3FID_PRODUCEDNOTICE,  ID3FID_PUBLISHER,           ID3FID_TRACKNUM,        ID3FID_RECORDINGDATES,
                           ID3FID_NETRADIOSTATION,  ID3FID_NETRADIOOWNER,   ID3FID_SIZE,                ID3FID_ALBUMSORTORDER,  ID3FID_PERFORMERSORTORDER,
                           ID3FID_TITLESORTORDER,   ID3FID_ISRC,            ID3FID_ENCODERSETTINGS,     ID3FID_SETSUBTITLE,     ID3FID_USERTEXT,
                           ID3FID_YEAR,             ID3FID_UNIQUEFILEID,    ID3FID_TERMSOFUSE,          ID3FID_UNSYNCEDLYRICS,  ID3FID_WWWCOMMERCIALINFO,
                           ID3FID_WWWCOPYRIGHT,     ID3FID_WWWAUDIOFILE,    ID3FID_WWWARTIST,           ID3FID_WWWAUDIOSOURCE,  ID3FID_WWWRADIOPAGE,
                           ID3FID_WWWPAYMENT,       ID3FID_WWWPUBLISHER,    ID3FID_WWWUSER,             ID3FID_METACRYPTO,      ID3FID_METACOMPRESSION,
                           ID3FID_LASTFRAMEID
                         };

      // a frame usually contains one field of the following fields:
    ID3_FieldID fiids[] = { ID3FN_NOFIELD, ID3FN_TEXTENC, ID3FN_TEXT, ID3FN_URL, ID3FN_DATA, ID3FN_DESCRIPTION, ID3FN_OWNER, ID3FN_EMAIL, ID3FN_RATING, ID3FN_FILENAME, ID3FN_LANGUAGE, ID3FN_PICTURETYPE, ID3FN_IMAGEFORMAT, ID3FN_MIMETYPE, ID3FN_COUNTER, ID3FN_ID, ID3FN_VOLUMEADJ, ID3FN_NUMBITS, ID3FN_VOLCHGRIGHT, ID3FN_VOLCHGLEFT, ID3FN_PEAKVOLRIGHT, ID3FN_PEAKVOLLEFT, ID3FN_TIMESTAMPFORMAT, ID3FN_CONTENTTYPE, ID3FN_LASTFIELDID};
    char*       idesc[] = { "No field.", "Text encoding (unicode or ASCII).", "Text field.", "A URL.", "Data field.", "Description field.", "Owner field.", "Email field.", "Rating field.", "Filename field.", "Language field.", "Picture type field.", "Image format field.", "Mimetype field.", "Counter field.", "Identifier/Symbol field.", "Volume adjustment field.", "Number of bits field.", "Volume chage on the right channel.", "Volume chage on the left channel.", "Peak volume on the right channel.", "Peak volume on the left channel.", "SYLT Timestamp Format.", "SYLT content type.", "Last field placeholder."};


    int i=0;
    char* buf = 0;
    ID3_Frame* frame = 0;
    ID3_Field* field = 0;
    while(i<96)
     {
      if(i==2 || i==10) // picture and encapsulated object often fail
       {
        printf("%2i. Skipping\n", i);
        i++; continue;
       }

      try { frame = m_id3tag->Find(fids[i]); }
      catch(...)
       {
        printf("ERROR: SKIPPING FILE (i=%i)\n", i);
        Free();
        return;
       }

      if(frame==0) { i++; continue; } // Frame not found
      printf("%2i. %-35s : ", i, frame->GetDescription());

      buf = m_getNewString(fids[i]);
      if(buf)
       {
        printf("\"%s\"\n", buf);
        delete[] buf;
        frame = 0;
        i++; continue;
       }

      printf("No Text found, but:\n", buf);

      for(int k=1; k<24; k++)
       {
        try
         {
          if(frame->Contains(fiids[k]))
           { printf("%-43s- %s\n", "", idesc[k]); }
         }
        catch(...)
         {
          printf("%-42sERROR: SKIPPING FILE (i=%i; k=%i)\n", "", i, k);
          Free();
          return;
         }
       }
      printf("\n");
      frame = 0;
      i++; continue;
     }
    printf("\n");
   }



/* ---------------- protected member functions ---------------- */

    /**
      \brief   parses the genre of the file

      In ID3V1 Tags, the genre is a simple byte and needs to be
      converted to a string first, but ID3V2 allows arbitrary
      genre descriptions.
    **/
  void MP3FileInfo::m_parseGenre(void)
   {
    if(bHasV2Tag) // Use V2 if present
     {
      szGenre = m_getNewString(ID3FID_CONTENTTYPE);
      return;
     }

    char buf[10];
    if(!m_getString(ID3FID_CONTENTTYPE, buf))
     {
      szGenre = 0;
      return;
     }

    int gid;
    sscanf(buf, "(%i)", &gid); // filter Genre ID

    if(gid >= ID3_NR_OF_V1_GENRES) // genre ID too large
     {
      szGenre = new char[strlen(buf)+1];
      sprintf(szGenre, buf);
      return;
     }

    szGenre = new char[strlen(ID3_V1GENRE2DESCRIPTION(gid))+1];
    sprintf(szGenre, ID3_V1GENRE2DESCRIPTION(gid));
   }

    /// parses header infomation
  void MP3FileInfo::m_parseHeader(void)
   {
    assert(m_bOK);

    m_mp3header = m_id3tag->GetMp3HeaderInfo();
    if(!m_mp3header)
     {
      //printf("\n[Error]:\nGetMp3HeaderInfo() failed!\n(file: %s)\n\n", szFilename);
      Free();
      return;
     }

    nCbrBitRate = m_mp3header->bitrate;
    nVbrBitRate = m_mp3header->vbr_bitrate;
    nSampleRate = m_mp3header->frequency;
    nLength     = m_mp3header->time;

    szBitRate = new char[20];
    if(nVbrBitRate>0)
     {
      sprintf(szBitRate, "%i kbit/s (VBR)", nVbrBitRate/1000);
      nBitRate = nVbrBitRate;
     }
    else
     {
      sprintf(szBitRate, "%i kbit/s", nCbrBitRate/1000);
      nBitRate = nCbrBitRate;
     }


      // MPEG Layer
    szMpegLayer = new char[10];
    switch(m_mp3header->layer)
     {
      case MPEGLAYER_UNDEFINED: sprintf(szMpegLayer, "UNDEFINED"); break;
      case MPEGLAYER_III:       sprintf(szMpegLayer, "Layer III"); break;
      case MPEGLAYER_II:        sprintf(szMpegLayer, "Layer II");  break;
      case MPEGLAYER_I:         sprintf(szMpegLayer, "Layer I");   break;
      default:                  szMpegLayer = 0;
     }

      // MPEG Version
    szMpegVersion = new char[10];
    switch(m_mp3header->version)
     {
      case MPEGVERSION_2_5: sprintf(szMpegVersion, "MPEG 2.5"); break;
      case MPEGVERSION_2:   sprintf(szMpegVersion, "MPEG 2");   break;
      case MPEGVERSION_1:   sprintf(szMpegVersion, "MPEG 1");   break;
      default:              szMpegVersion = 0;
     }

      // Channel Mode
    szChannelMode = new char[15];
    switch(m_mp3header->channelmode)
     {
      case MP3CHANNELMODE_STEREO:         sprintf(szChannelMode, "Stereo");         break;
      case MP3CHANNELMODE_JOINT_STEREO:   sprintf(szChannelMode, "Joint Stereo");   break;
      case MP3CHANNELMODE_DUAL_CHANNEL:   sprintf(szChannelMode, "Dual Channel");   break;
      case MP3CHANNELMODE_SINGLE_CHANNEL: sprintf(szChannelMode, "Single Channel"); break;
      default:                            szChannelMode = 0;
     }
   }


    /// extracts a string
  bool MP3FileInfo::m_getString(ID3_FrameID fid, char* szBuffer)
   {
    assert(m_bOK);

    ID3_Frame* frame = m_id3tag->Find(fid); // frame
    if(frame==0)
     {
      sprintf(szBuffer, "[Not Found]");
      return false;
     }

    if(!frame->Contains(ID3FN_TEXTENC))
     {
      sprintf(szBuffer, "[Contains No Text]");
      return false;
     }

    ID3_Field* field = 0;
    if(frame->Contains(ID3FN_TEXT))
     { field = frame->GetField(ID3FN_TEXT); }

      // String is an URL
    if(frame->Contains(ID3FN_URL) && (field==0))
     { field = frame->GetField(ID3FN_URL); }

    if(field==0)
     {
      delete frame;
      sprintf(szBuffer, "[Error]");
      return false;
     }

    field->SetEncoding(ID3TE_ISO8859_1);
    const char* res = field->GetRawText(); // GetRawUnicodeText
    if(res==0)
     {
      delete frame;
      sprintf(szBuffer, "[Empty]");
      return false;
     }

    sprintf(szBuffer, res);
    return true;
   }


    /// extracts a string
  char* MP3FileInfo::m_getNewString(ID3_FrameID fid)
   {
    assert(m_bOK);

    ID3_Frame* frame = m_id3tag->Find(fid); // find frame
    if(frame==0) { return 0; }

    if(!frame->Contains(ID3FN_TEXTENC))
     { delete frame; return 0; } // frame contains no text

      // look for field type
    ID3_Field* field = 0;
    if(frame->Contains(ID3FN_TEXT)) // Text field
     { field = frame->GetField(ID3FN_TEXT); }

    if(frame->Contains(ID3FN_URL) && (field==0)) // URL field
     { field = frame->GetField(ID3FN_URL); }

    if(field==0) { delete frame; return 0; } // no field found

    field->SetEncoding(ID3TE_ISO8859_1); // use Latin-1 charset

    const char* res = field->GetRawText(); // TODO: GetRawUnicodeText
    char* buf = new char[strlen(res)+1]; // new string
    sprintf(buf, res); // copy

    return buf;
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -