div.main {margin-left: 20pt; margin-right: 20pt}
Чтение файла в формате mp3
Developers.com.ua
Формат очень простой. Для начала приведу таблицу с описанием заголовка
(он идет сразу с сначала файла):
Name of Field |
Bit Numbers |
Code to Extract |
Meaning |
Frame Sync 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. |
inBuf[ 0 ] 0:7 |
InBuf[ 0 ] |
Since the first 11 bits of a header are all 1s, inBuf[ 0 ] must have a decimal value of 255, which is eight ones in binary. |
Frame Sync continued |
inBuf[ 1 ] 5:7 |
(InBuf[ 1 ] >> 5) & 7 |
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. |
Audio Version (phase) |
inBuf[ 1 ] 3:4 |
(inBuf[ 1 ] >>3) & 3 |
The next two bits tell the MPEG version: 0 = MPEG-2.5 (a non-standard extension to MPEG-2)1 = reserved2 = MPEG-23 = MPEG-1 |
Layer |
inBuf[ 1 ] 1:2 |
(inBuf[ 1 ] >> 1) & 3 |
The next two bits tell the layer: 0 = reserved1 = Layer III2 = Layer II3 = Layer I |
Protection Bit |
inBuf[ 1 ] 0 |
InBuf[ 1 ] & 1 |
If this bit is 0, the header is followed by two bytes of error detection bits before the audio data starts. |
Bit Rate Index |
inBuf[ 2 ] 4:7 |
(InBuf[ 2 ] >> 4) & 15 |
The next four bits are a row index into a doubly subscripted arry of bit rates. See note below. |
Sampling Rate Index |
inBuf[ 2 ] 2:3 |
(inBuf[ 2 ] >>) & 3 |
For MPEG-1, the values are as follows: 0 = 44,100 Hz1 = 48,000 Hz2 = 32,000 Hz3 = reserved |
Padding Bit |
InBuf[ 2 ] 1 |
(inBuf[ 2 ] >> 1) & 1 |
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. |
Private Bit |
inBuf[ 2 ] 0 |
InBuf[ 2 ] & 1 |
Different programs can interpret this bit different ways. |
Channel Mode |
inBuf[ 3 ] 6:7 |
(inBuf[ 3 ] >> 6) & 3 |
This two bit code tells whether the information is in stereo or not: 0 = Stereo1 = Joint Stereo2 = Dual Channel3 = Single Channel |
Mode Extension (Only if Joint Stereo) |
inBuf[ 3 ] 4:5 |
(inBuf[ 3 ] >> 4) & 3 |
Used internally by the decoding algorithm. |
Copyright |
inBuf[ 3 ] 3 |
(inBuf[ 3 ] >> 3) & 1 |
If this bit is set, the audio material is copyrighted. |
Original |
inBuf[ 3 ] 2 |
(inBuf[ 3 ] >> 2) & 1 |
If this bit is set, this file is the orginal media used to hold the audio information. |
Emphasis |
inBuf[ 3 ] 0:1 |
InBuf[ 3 ] & 3 |
Used internally by the decoding algorithm. |
Notes on the Bit Rate Table: |
The column index for the Bit Rate table is derived from the combination of the phase and layer as follows: 0 Phase 1, Layer I 1 Phase 1, Later II 2 Phase 1, Layer III 3 Phase 2 or 2.5, Layer I 4 Phase 2 or 2.5, Layer II or III |
The row index should never equal fifteen. |
The Bit Rate Table is avalable as a public array of int named bitRateTable in class MP3header. |
Информация о исполнителе, альбоме, годе, жанре храниться в последних 128 байтах файла. Следующая таблица описывает формат к котором она храниться:
Bytes |
Meaning |
0:2 |
Must be "TAG". If not, there is no ID3 tag in this file |
3:32 |
Song Title |
33:62 |
Performer's Name |
63:92 |
Name of the Album |
93:96 |
Year |
97:126 |
Comment |
127 |
Genre |
Пример класса, вычитывающий информацию из 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&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 & Roll", "Hard Rock",
};
|