Блог программатора

Our partner
Главная | Последние правки | Поиcк | Все страницы | Редактор | Админ | Печать

Чтение информации о файле в формате mp3

Формат очень простой. Для начала приведу таблицу с описанием заголовка (он идет сразу с сначала файла):

<TABLE cellSpacing=0 cellPadding=7 width=570 border=1>
<TR>
 <TD vAlign=top width="29%"><P><b>Name of Field</B></P></TD>
 <TD vAlign=top width="17%"><P><b>Bit Numbers</B></P></TD>
 <TD vAlign=top width="25%"><P><b>Code to Extract</B></P></TD>
 <TD vAlign=top width="29%"><P><b>Meaning</B></P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Frame Sync</P><P>A frame can, in principle, start at an arbitray byte offset into the  audio stream. The beginning of a frame header is indicated by 11 ones, starting at the beginning of a byte.</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 0 ] 0:7</P></TD>
 <TD vAlign=top width="25%"><P>InBuf[ 0 ]</P></TD>
 <TD vAlign=top width="29%"><P>Since the first 11 bits of a header are all 1s, inBuf[&nbsp;0&nbsp;] must have a decimal value of 255, which is eight ones in binary.</P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Frame Sync <I>continued</I></P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 1 ] 5:7</P></TD>
 <TD vAlign=top width="25%"><P>(InBuf[ 1 ] &gt;&gt; 5) &amp; 7</P></TD>
 <TD vAlign=top width="29%"><P>If inBuf[ 0 ] is 255, and if the first three bits of the next byte have the value 7 (three 1s in binary), the beginning of a valid MP3 header has been found.</P></TD></TR>
<TR>
 <TD vAlign=top width="29%"><P>Audio Version (phase)</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 1 ] 3:4</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 1 ] &gt;&gt;3) &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>The next two bits tell the MPEG version:</P><UL><LI>0 = MPEG-2.5 (a non-standard extension to MPEG-2)</LI><LI>1 = reserved</LI><LI>2 = MPEG-2</LI><LI>3 = MPEG-1</LI></UL></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Layer</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 1 ] 1:2</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 1 ] &gt;&gt; 1) &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>The next two bits tell the layer:</P><UL><LI>0 = reserved</LI><LI>1 = Layer III</LI><LI>2 = Layer II</LI><LI>3 = Layer I</LI></UL></TD>
</TR>
<TR>
   <TD vAlign=top width="29%"><P>Protection Bit</P></TD>
   <TD vAlign=top width="17%"><P>inBuf[ 1 ] 0</P></TD>
   <TD vAlign=top width="25%"><P>InBuf[ 1 ] &amp; 1</P></TD>
   <TD vAlign=top width="29%"><P>If this bit is 0, the header is followed by two bytes of error detection bits before the audio data starts.</P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Bit Rate Index</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 2 ] 4:7</P></TD>
 <TD vAlign=top width="25%"><P>(InBuf[ 2 ] &gt;&gt; 4) &amp; 15</P></TD>
 <TD vAlign=top width="29%"><P>The next four bits are a row index into a doubly subscripted arry of bit rates.</P><P>See note below.</P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Sampling Rate Index</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 2 ] 2:3</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 2 ] &gt;&gt;) &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>For MPEG-1, the values are as follows:</P><UL><LI>0 = 44,100 Hz</LI><LI>1 = 48,000 Hz</LI><LI>2 = 32,000 Hz</LI><LI>3 = reserved</LI></UL></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Padding Bit</P></TD>
 <TD vAlign=top width="17%"><P>InBuf[ 2 ] 1</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 2 ] &gt;&gt; 1) &amp; 1</P></TD>
 <TD vAlign=top width="29%"><P>If this bit is a 1 and the layer is III, the frame has an extra (unused) byte at the end. For layers I and II the padding amount, if present, is four bytes.</P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Private Bit</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 2 ] 0</P></TD>
 <TD vAlign=top width="25%"><P>InBuf[ 2 ] &amp; 1</P></TD>
 <TD vAlign=top width="29%"><P>Different programs can interpret this bit different ways.</P></TD></TR>
<TR>
 <TD vAlign=top width="29%"><P>Channel Mode</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 3 ] 6:7</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 3 ] &gt;&gt; 6) &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>This two bit code tells whether the information is in stereo or not:</P><UL><LI>0 = Stereo</LI><LI>1 = Joint Stereo</LI><LI>2 = Dual Channel</LI><LI>3 = Single Channel</LI></UL></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Mode Extension</P><P>(Only if Joint Stereo)</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 3 ] 4:5</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 3 ] &gt;&gt; 4) &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>Used internally by the decoding algorithm.</P></TD></TR>
<TR>
 <TD vAlign=top width="29%"><P>Copyright</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 3 ] 3</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 3 ] &gt;&gt; 3) &amp; 1</P></TD>
 <TD vAlign=top width="29%"><P>If this bit is set, the audio material is copyrighted.</P></TD></TR>
<TR>
 <TD vAlign=top width="29%"><P>Original</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 3 ] 2</P></TD>
 <TD vAlign=top width="25%"><P>(inBuf[ 3 ] &gt;&gt; 2) &amp; 1</P></TD>
 <TD vAlign=top width="29%"><P>If this bit is set, this file is the orginal media used to hold the audio information.</P></TD>
</TR>
<TR>
 <TD vAlign=top width="29%"><P>Emphasis</P></TD>
 <TD vAlign=top width="17%"><P>inBuf[ 3 ] 0:1</P></TD>
 <TD vAlign=top width="25%"><P>InBuf[ 3 ] &amp; 3</P></TD>
 <TD vAlign=top width="29%"><P>Used internally by the decoding  algorithm.</P></TD>
</TR>
</TABLE>
<BR>
<TABLE cellSpacing=0 cellPadding=7 width=409 border=1>
<TR>
 <TD vAlign=top><I><P align=center>Notes on the Bit Rate Table:</I></P></TD>
</TR>
<TR>
 <TD vAlign=top height=232><P>The column index for the Bit Rate table is derived from the combination of the phase and layer as follows:</P><DIR><DIR><P>0 Phase 1, Layer I</P><P>1 Phase 1, Later II</P><P>2 Phase 1, Layer III</P><P>3 Phase 2 or 2.5, Layer I</P><P>4 Phase 2 or 2.5, Layer II or III</P></DIR></DIR></TD>
</TR>
<TR>
 <TD vAlign=top><P>The row index should never equal fifteen.</P></TD>
</TR>
<TR>
 <TD vAlign=top><P>The Bit Rate Table is avalable as a public array of <I>int</I> named <FONT face=Arial>bitRateTable</FONT> in class MP3header.</P></TD>
</TR>
</TABLE>

Информация о исполнителе, альбоме, годе, жанре храниться в последних 128 байтах файла. Следующая таблица описывает формат к котором она храниться:

<TABLE cellSpacing=0 cellPadding=7 width=216 border=1>
<TR>
 <TD vAlign=top width="31%"><P align=center><B>Bytes</B></P></TD>
 <TD vAlign=top width="69%"><P align=center><B>Meaning</B></P></TD>
</TR>
<TR>
 <TD vAlign=top width="31%"><P>0:2</P></TD>
 <TD vAlign=top width="69%"><P>Must be "TAG".<BR>If not, there is no ID3 tag in this file</P></TD>
</TR>
<TR>
 <TD vAlign=top width="31%"><P>3:32</P></TD>
 <TD vAlign=top width="69%"><P>Song Title</P></TD>
</TR>
<TR>
 <TD vAlign=top width="31%"><P>33:62</P></TD>
 <TD vAlign=top width="69%"><P>Performer's Name</P></TD></TR>
<TR>
 <TD vAlign=top width="31%"><P>63:92</P></TD>
 <TD vAlign=top width="69%"><P>Name of the Album</P></TD>
</TR>
<TR>
 <TD vAlign=top width="31%"><P>93:96</P></TD>
 <TD vAlign=top width="69%"><P>Year</P></TD></TR>
<TR>
 <TD vAlign=top width="31%"><P>97:126</P></TD>
 <TD vAlign=top width="69%"><P>Comment</P></TD>
</TR>
<TR>
 <TD vAlign=top width="31%"><P>127</P></TD>
 <TD vAlign=top width="69%"><P>Genre</P></TD>
</TR>
</TABLE>

Пример класса, вычитывающий информацию из ID3V1 TAGS:

import java.io.*;

public class MP3header {
 private String Artist="";
 private String Album="";
 private String Song="";
 private String fname="";
 private long bitrate=0;
 private long year=0;
 private long stereo=0;
 private long fsize=0;

 static private int[][] bitRateTable  =
   {
   //  Ph 1L-I   Ph1 L-II    Ph1 L-III  Ph2 L-I    Ph2 L-II&III
     { 0,        0,          0,         0,         0       },
     { 32000,    32000,      32000,     32000,     8000    },
     { 64000,    48000,      40000,     48000,     16000   },
     { 96000,    56000,      48000,     56000,     24000   },
     { 128000,   64000,      56000,     64000,     32000   },
     { 160000,   80000,      64000,     80000,     40000   },
     { 192000,   96000,      80000,     96000,     48000   },
     { 224000,   112000,     96000,     112000,    56000   },
     { 256000,   128000,     112000,    128000,    64000   },
     { 288000,   160000,     128000,    144000,    80000   },
     { 320000,   192000,     160000,    160000,    96000   },
     { 352000,   224000,     192000,    176000,    112000  },
     { 384000,   256000,     224000,    192000,    128000  },
     { 416000,   320000,     256000,    224000,    144000  },
     { 448000,   384000,     320000,    256000,    160000  },
     { -1,       -1,         -1,        -1,        -1      },
   };

 public void setArtist(String s)
 { Artist=s.trim();
 }

 public String getArtist()
 { return(Artist.trim());
 }

 public void setAlbum(String s)
 { Album=s.trim();
 }

 public String getAlbum()
 { return(Album.trim());
 }

 public void setSong(String s)
 { Song=s.trim();
 }

 public String getSong()
 { return(Song.trim());
 }

 public String getFName()
 { return(fname.trim());
 }

 public long getFSize()
 { return(fsize);
 }

 public void setYear(long y)
 { year=y;
 }

 public long getYear()
 { return(year);
 }

 public void setBitrate(long b)
 { bitrate=b/1000;
 }

 public long getBitrate()
 { return(bitrate);
 }

 public void setStereo(long b)
 { stereo=b;
 }

 public long getStereo()
 { return(stereo);
 }

 public void loadInfo(String fname)
 { try{ this.fname=fname;
        File f = new File(fname);
        long len=f.length();
        fsize=len;
        byte[] buf=new byte[128];
        FileInputStream fis;

        fis = new FileInputStream(f);
        fis.read(buf,0,128);
        fis.close();
        int lay=(buf[ 1 ] >> 1) & 3;
        int mpeg=(buf[ 1 ] >> 3) & 3;

        switch(mpeg)
        {
// mpg-1.0
          case 3:
                  switch(lay)
                  { case 3: mpeg=0;
                            break;
                    case 2: mpeg=1;
                            break;
                    case 1: mpeg=2;
                            break;
                  }
                  break;
// mpg-2.0
          case 0:
          case 2:
                  switch(lay)
                  { case 3: mpeg=3;
                            break;
                    case 2: 
                    case 1: mpeg=4;
                            break;
                  }
                  break;
          
        }
        int btr=((buf[2]>>4) & 15);
        setBitrate(bitRateTable[btr][mpeg]);
        setStereo((buf[ 3 ] >> 6) & 3);

        fis = new FileInputStream(f);
        fis.skip(len-128);
        fis.read(buf,0,128);

        setSong(new String(buf,3,29));
        setArtist(new String(buf,33,30));
        setAlbum(new String(buf,63,30));
        try{ setYear(Long.parseLong(new String(buf,93,4)));
           } catch(Exception e) { setYear(2001);}
        fis.close();
      } catch(Exception e)
        { System.out.println(""+e);
        }
 }
}

Таблица жанров:

public final String[] genreNames = {
 "Blues",              "Classic Rock",     "Country",
 "Dance",              "Disco",            "Funk",
 "Grunge",             "Hip-Hop",          "Jazz",
 "Metal",              "New Age",          "Oldies",
 "Other",              "Pop",              "R&amp;B",
 "Rap",                "Reggae",           "Rock",
 "Techno",             "Industrial",       "Alternative",
 "Ska",                "Death Metal",      "Pranks",
 "Soundtrack",         "Euro-Techno",      "Ambient",
 "Trip-Hop",           "Vocal",            "Jazz+Funk",
 "Fusion",             "Trance",           "Classical",
 "Instrumental",       "Acid",             "House",
 "Game",               "Sound Clip",       "Gospel",
 "Noise",              "AlternRock",       "Bass",
 "Soul",               "Punk",             "Space",
 "Meditative",         "Instrumental Pop", "Instrumental Rock",
 "Ethnic",             "Gothic",           "Darkwave",
 "Techno-Industrial",  "Electronic",       "Pop-Folk",
 "Eurodance",          "Dream",            "Southern Rock",
 "Comedy",             "Cult",             "Gangsta",
 "Top 40",             "Christian Rap",    "Pop/Funk",
 "Jungle",             "Native American",  "Cabaret",
 "New Wave",           "Psychadelic",      "Rave",
 "Show Tune",          "Trailer",          "Lo-Fi",
 "Tribal",             "Acid Punk",        "Acid Jazz",
 "Polka",              "Retro",            "Musical",
 "Rock &amp; Roll",        "Hard Rock",
};


Главная
Софт
Хард
Политеги

SimpleWiki 

Почта 



Мой номер ICQ
 456824974 

Архив:

01.2010
02.2010
03.2010
04.2010
05.2010
06.2010
07.2010


Радио «Анонимус» 
Реклама java
Wed, 30 Jun 2010 13:56:00 -0400
Копипаста: История программных революций от Microsoft
Mon, 14 Jun 2010 04:19:00 -0400
Как восстановить grub2 и mbr
Thu, 10 Jun 2010 17:33:00 -0400
Установить/сменить пароль администратора на свежем postgresql'е
Sun, 23 May 2010 18:18:00 -0400
Президент Виктор Янукович получил по морде венком
Tue, 18 May 2010 09:31:00 -0400
Наконец-то ! Контакт с инопланетянами !
Thu, 18 Mar 2010 08:01:00 -0400
Панкота: группа Флiт
Sat, 13 Mar 2010 08:11:00 -0500

Blog

Add bookmark:
Bookmark and Share



© Komenda Viacheslav
Запрещается перепечатка материалов, без письменного разрешения автора.

Последнее обновление: Tue, 05 May 2009 11:09:13 -0400