Hallo,
ich hab einige klassen geschrieben (angefangen zu schreiben) um mit mp3´s arbeiten zu können, darunter eine klasse, id3v1 tags auslesen, die prima funktioniert und eine klasse zum auslesen des mp3 headers, diese funktioniert leider nicht so ganz, bei meinchen mp3´s wird alles richtig angezeigt, bei anderen sind nur einige werte falsch und bei manchen kommen irgendwelche Exceptions (meistens irgendwelche arraywerte die es net gibt, wie -1 oder so).
Es gibt sogar fälle, wo gar kein mp3-header gefunden wird.
Ich hab schon ein weilchen nach fehlern gesucht aber nix gefunden, könnte mir jemand helfen?
Klasse Header.java:
Klasse zum Testen (müsste selbst einen pfad zu ner mp3 datei einfügen, um direkt testen zu können):
Meine Informationsquellen waren:
MP3 File Format Specification
MP3 Grundlagen, Aufbau und Funktion
MP3 ? Wikipedia
(nur falls jemand nachschauen will, ob ich was völlig falsch verstanden hab oder so)
ich hab einige klassen geschrieben (angefangen zu schreiben) um mit mp3´s arbeiten zu können, darunter eine klasse, id3v1 tags auslesen, die prima funktioniert und eine klasse zum auslesen des mp3 headers, diese funktioniert leider nicht so ganz, bei meinchen mp3´s wird alles richtig angezeigt, bei anderen sind nur einige werte falsch und bei manchen kommen irgendwelche Exceptions (meistens irgendwelche arraywerte die es net gibt, wie -1 oder so).
Es gibt sogar fälle, wo gar kein mp3-header gefunden wird.
Ich hab schon ein weilchen nach fehlern gesucht aber nix gefunden, könnte mir jemand helfen?
Klasse Header.java:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
public class Header {
private boolean isMP3;
private long lPos = 0;
//Headerstruktur: 11111111.111aabbc.eeeeffgh.iijjklmm
/* aa : versionID => Version des MPEG (1; 2; inofiziel 2.5)
* bb : LayerID => Layer Version (1; 2; 3)
* c : protection => error protection bit, falls gesetzt kommt nach header 16bit prüfsumme (CRC)
* eeee : bitrate => bitrate der datei (abhängig vom Layer)
* ff : freqquence => Frequenz der datei (abhängig von der MPEG version
* g : padding => Paddingbit gibt an, ob Frame vollständig ausgefüllt ist oder nicht
* h : priv => Private-bit steht zur freien verfügung
* ii : mode => Stereomode (Stereo, joint Stereo, Zweikanal, Mono)
* jj : ------- => mode extension, nur interessant wenn joint stereo als modus gewählt ist
* k : ------- => copyright-bit, urheberrechtlich geschützt oder nicht
* l : ------- => original-/ copybit (1 für original)
* mm : ------- => emphasis gibt die verwendete Rauschunterdrückung an (nicht häufig benutzt)
*
* Für MP3 Format festgelegt:
* Magic Number (erkennungszahl) : 11111111.11111011.
* aa : 11 => Version MPEG 1
* bb : 01 => Layer 3 (MP3 ~ MPEG Layer 3)
* c : 1 => Prüfsumme ist meistens enthalten
* Struktur: 11111111.11111011.eeeeffgh.iijjklmm
*
* */
private float versionID;
private short layerID;
private boolean protection; //protection bit, geschützt oder nicht
private short bitrate; //Bitrate der Mp3 datei
private int frequence; //Frequence der Mp3 datei (meistens 44kHz)
private boolean padding;
private boolean priv;
private String mode;
Header(File fl, long pos){
lPos = pos;
if(lPos == -1){
isMP3 = false;
}else{
isMP3 = true;
readHeader(fl);
}
}
Header(String fl, long pos){
this(new File(fl), pos);
}
Header(URL fl, long pos){
this(new File(fl.getPath()), pos);
}
Header(File fl){
this(fl, (locate(fl)));
}
Header(String fl){
this(new File(fl));
}
Header(URL fl){
this(new File(fl.getPath()));
}
//anfang der mp3 datei feststellen (suche nach den muster das auf einen mp3 header hindeutet)
private static long locate(File file){
FileChannel fc = null;
FileInputStream fs = null;
long pos = 0;
byte[] buffer = new byte[4];
try {
fs = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
fc = fs.getChannel();
try {
fc.position(0);
} catch (IOException e1) {
e1.printStackTrace();
}
for(; pos < 12000; pos++){
try {
fs.read(buffer, 0, 4);
} catch (IOException e) {
e.printStackTrace();
}
if((buffer[0]& 0xFF) ==255 && ((buffer[1]&0xFF) == 251)&& (buffer[2] & 0xFF) >= 96 && (buffer[2] & 0xFF)< 250){
try {
fc.close();
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
return pos;
}
try {
fc.position(pos);
} catch (IOException e) {
e.printStackTrace();
}
}
return -1;
}
//auslesen des headers und speichern der werte in den header variablen
private void readHeader(File file){
FileChannel fc = null;
FileInputStream fs = null;
byte[] buffer = new byte[4];
long header;
try {
fs = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
fc = fs.getChannel();
try {
fc.position(lPos);
} catch (IOException e1) {
e1.printStackTrace();
}
//Auslesen der 4 byte
try {
fs.read(buffer, 0, 4);
} catch (IOException e) {
e.printStackTrace();
}
//header in long umwandeln
header = convertHeaderToLong(buffer);
//skip sync (11)
//Audioversion(2)
versionID = getVersionId(header);
//Layer(2)
layerID = getLayerId(header);
//Protection (1)
protection = getProtectionBit(header);
//Bitrate (4)
bitrate = getBitrate(header);
//Frequenc (2)
frequence = getFrequence(header);
//padding (1)
padding = getPaddingBit(header);
//private (1)
priv = getPrivatBit(header);
//Channelmode (Stereo, mono, ...) (2)
mode = getChannelmode(header);
//Mode Extension <nur bei joint stereo> (2)
//copyright (1)
//Original <1 bei origional, 0 bei kopie> (1)
//emphasis <veraltet> (2)
}
//für alle methoden gilt: tmp = header der zu einem long convertiert wurde;
private String getChannelmode(long tmp){
String[] table = {"Stereo", "Joint Stereo", "Zweikanal", "Mono"};
return table[getIntegerValue(6, (short)3, tmp)];
}
private boolean getPrivatBit(long tmp){
boolean[] table = {false, true};
return table[getIntegerValue(8, (short)1, tmp)];
}
private boolean getPaddingBit(long tmp){
boolean[] table = {false, true};
return table[getIntegerValue(9, (short)1, tmp)];
}
private int getFrequence(long tmp){
int[][] table = {
{11025, 12000, 8000, 0},
{0, 0, 0, 0},
{22050, 24000, 16000, 0},
{44100, 48000, 32000, 0},
};
return table[getIntegerValue(19, (short)3, tmp)][getIntegerValue(10, (short)3, tmp)];
}
private short getBitrate(long tmp){
short[][] table = {
//Layer 1
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
//Layer 2
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
//Layer 3
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
};
return table[layerID -1][getIntegerValue(12, (short)15, tmp)];
}
private boolean getProtectionBit(long tmp){
boolean[] table = {false, true};
return table[getIntegerValue(16, (short)1, tmp)];
}
private short getLayerId(long tmp){
short[] table = {0, 3, 2, 1};
return table[getIntegerValue(17, (short)3, tmp)];
}
private float getVersionId(long tmp){
float[] table = {2.5f, 0.0f, 2.0f, 1.0f};
return table[getIntegerValue(19, (short)3, tmp)];
}
private int getIntegerValue(int skipbit, short maskValue, long tmp){
return (int)((tmp>>skipbit) & maskValue);
}
private long convertHeaderToLong(byte[] bytHeader){
return (long)(((bytHeader[0] & 255) << 24) | ((bytHeader[1] & 255) << 16) | ((bytHeader[2] & 255) << 8) | ((bytHeader[3] & 255)));
}
protected boolean isValid(){
return isMP3;
}
//getter-methoden für die Headerklasse, zum übergeben der enthaltenen parameter an andere klassen
public float getMpegId(){
return versionID;
}
public short getLayer(){
return layerID;
}
public boolean isProtected(){
return protection;
}
public short getBitrate(){
return bitrate;
}
public int getFrequence(){
return frequence;
}
public boolean getPdding(){
return padding;
}
public boolean isPrivate(){
return priv;
}
public String getMode(){
return mode;
}
}
Klasse zum Testen (müsste selbst einen pfad zu ner mp3 datei einfügen, um direkt testen zu können):
Java:
public class TestMp3Classes {
TestMp3Classes(String path){
Header hd = new Header(path);
if(hd.isValid()){
/*
Id3v1 id3 = new Id3v1(path);
//Ausgaben
System.out.println("Ausgaben zu : "+id3.getTitel());
*/
System.out.println("\r\nHeader Informationen:");
System.out.println("Version MPEG: "+hd.getMpegId());
System.out.println("Layer : "+hd.getLayer());
System.out.println("Protected : "+hd.isProtected());
System.out.println("Bitrate: "+hd.getBitrate());
System.out.println("Freqenze: "+hd.getFrequence());
System.out.println("Modus: "+hd.getMode());
System.out.println();
/*
System.out.println("Tags: ");
System.out.println("Titel: "+ id3.getTitel());
System.out.println("Interpret: "+ id3.getInterpret());
System.out.println("Album: "+ id3.getAlbum());
System.out.println("Genre: "+ id3.getGenre());
System.out.println("Jahr: "+ id3.getYear());
System.out.println("Kommentar: "+ id3.getComment());
*/
}else{
System.out.println("Invalide MP3");
}
}
public static void main(String[] args) {
new TestMp3Classes("");
}
}
Meine Informationsquellen waren:
MP3 File Format Specification
MP3 Grundlagen, Aufbau und Funktion
MP3 ? Wikipedia
(nur falls jemand nachschauen will, ob ich was völlig falsch verstanden hab oder so)