DevTrain

Autor: Bernhard Elbl

File Functions Teil 2 - MP3 ID3v2

Im ersten Teil haben wir besprochen, wie man die MP3Info einer MP3 ausliest. Allerdings funktioniert dies nur mit der ID3 Version 1. Hier stellt das MP3Info die letzten 255 Zeichen dar. In der ID3v2 ist es jetzt gänzlich anders. Das Info hat keine feste Länge und kann bis zu 255 MB gross sein! Ausserdem befinden sich die Info-Tags irgendwo im Info und nicht an einer bestimmten Stelle! Das MP3Info beginnnt hier am Anfang der MP3 gleich nach dem Header. Es ist auch möglich, dass die Tags der 2 verschiendenen Versionen nebeneinandern existieren! Das verursacht keine Probleme. Nun gut, aber, Wie komme ich also in der ID3v2 an das MP3Info ran?

Was ist der Header der ID3v2?
In der ID3v2 beginnt jedes MP3-File mit den Tags "ID3". Das ist der sogenannte ID-TAG. Danach folgen 2 Bytes, die die Versionnummer darstellen. Dann kommt noch ein Byte für Flags und 4 Byte für die Grösse der Info.
In VB6 könnte die Struktur also wie folgt aussehen!
Public Type MP3Head
    ID3 As String * 3
    MajorVersion As Byte
    RevisionNumber As Byte
    Flags As Byte
    Size As Long ' 4 Byte Sync-Integer!!!
End Type

Die Grösse ist ein 4 Byte Sync-Integer! oder sprichwörtlich ein 7 Bit-Integer. Er verwendet nur 7 Bits, um seine Wertigkeit auszudrücken.
Hier gibts Detailierte Infos...
http://www.id3.org/id3v2.4.0-structure.txt
Die Tags haben bestimmte Namen!
Zu mindest die am meist benötigten. Die MP3Info lässt sich nähmlich beliebig erweitern.
Hier habe ich einige Konstanten definiert, die die Namen der bekanntesten Tags beiinhalten.
Public Const TAG_IDTAGv2 As String = "ID3" ' Einleitende Tag für MP3 mit ID3v2
Public Const TAGTITLE As String = "TIT2"
Public Const TAGALBUM As String = "TALB"
Public Const TAGKUENSTLER As String = "TPE1"
Public Const TAGKOMMENTAR As String = "TCON"
Public Const TAGJAHR As String = "TYER"

Am besten Sie laden sich für binäre Daten irgendeinen Hexeditor runter. Und schauen sich das MP3-File mal darin an.

Das ist die ersten Bytes eines MP3 mit ID3v2.
Die Tags stehen also wild irgendwo im Info!
Allerdings haben die Tags selbst auch eine gewisste Struktur.
Public Type MP3TAG
    TAG As String * 4 ' Die Tagdefinition ist 4 Byte lang
    Size As Long      ' Die Grösse des Wertes ist ein Long, 4 Bytes
    Flags As String * 3' Flags, 3 Bytes
End Type
und danach kommt dann endlich der Wert, den wir haben wollen. z.B. Album-Name, Titel-Name usw.
Sample: ID3v2 auslesen mit VB6
hier nur die wichtigsten Code-Schnibbels, der komplette Source-Code ist im Download enthalten.
Private m_byteMP3Info(512) As Byte
....
public sub ....
    Open sFileName For Binary Access Read As #iFile
    Get #iFile, , tMP3Head
   
    ' wenn es eine ID3 der Version 1 ist, dann
    If tMP3Head.ID3 <> TAG_IDTAGv2 Then
        ' Code für ID3v1 hier...
    Else
        Get #iFile, , m_byteMP3Info ' die ersten 512 Bytes in das ByteArray einlesen.
        m_sAlbum = GetValueFromTag(TAGALBUM)
        m_sKuenstler = GetValueFromTag(TAGKUENSTLER)
        m_sTitel = GetValueFromTag(TAGTITLE)
        m_sKommentar = GetValueFromTag(TAGKOMMENTAR)
        m_sJahr = GetValueFromTag(TAGJAHR)
    End If
  
    Close #iFile
End Sub

- Jetzt haben wir die ID3v2 im modulglobalen ByteArray zwischengespeichert.
- GetValueFromTag(TAGALBUM) = ruft die Funktion auf und übergibt den Tag-Namen der ausgelesen werden soll. Die Funktion liefert als Rückgabewert den Wert eines MP3Info-Tags.
Hier die eigentliche Funktion, die die Tag-Value´s filtert.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Function GetValueFromTag(ByVal sTag As String) As String
    Dim tMP3TAG As MP3TAG
    Dim lTagBegin As Long
   
    ' Tag-Position ermitteln
    lTagBegin = InStrB(1, m_byteMP3Info, StrConv(sTag, vbFromUnicode))
    If lTagBegin <> 0 Then
        With tMP3TAG
            '.TAG = StrConv(MidB(m_byteMP3Info, lTagBegin, 4), vbUnicode) ' Orginal-Tag-ID auslesen
           
            On Error GoTo Fehler
            ' Tag-Value grösse mit CopyMemory in VB-Long kopieren
            CopyMemory ByVal VarPtr(.Size), ByVal VarPtr(m_byteMP3Info(lTagBegin + 6)), 4
           
            ' Tag-Value auslesen und in BSTR konvertieren
            GetValueFromTag = StrConv(MidB(m_byteMP3Info, lTagBegin + 11, .Size - 1), vbUnicode)
        End With
    Else
        GetValueFromTag = ""
    End If
   
   
    Exit Function
Fehler:
    If Err.Number = 9 Then ' Überlauf, wenn byteArray zu klein ist.
        '---
    End If
    Err.Clear
End Function

StrConv = konvertiert den entsprechenden String in einen Unicode-String oder umgekehrt. Da die Info-Tags als VB-String-Konstanten deklariert sind, müssen diese in Unicode konvertiert werden.
VarPtr = liefert einen Long der einen Pointer auf eine Variable darstellt
CopyMemory = kopiert Speicherbereiche z.B.
00 00 00 0f
wenn man diesen Speicherbereich in einen Long kopiert, hat der Long den Wert 16.

Dieses MP3-Sample zeigt sich mit einer sehr guten Geschwindigkeit. 300 MP3´s in 1 Sekunde.
Warum funktioniert das so schnell?
Dafür gibt es mehrere Gründe.
Die Tags werden nicht Stück für Stück gesucht oder ausgelesen, sondern auf es werden auf 1-mal 512 Bytes ausgelesen, und die Tags mit dem "instrb"-Command gefunden.
Schleifen, Vergleiche brauchen viel Zeit und sind möglichst gering gehalten.
Es finden keine Stringverkettungen statt. Diese nehmen viel CPU-Power in Anspruch und sind allgemein inperformant.
 
Links:
http://www.id3.org/id3v2.4.0-structure.txt
http://substream.org/mp3-aufbau3.html


Alle Sources sind im Download enthalten. Viel Spass.
 

Erfasst am: 05.03.2002 - Artikel-URL: http://www.devtrain.de/news.aspx?artnr=722
© Copyright 2003 ppedv AG - http://www.ppedv.de