mp3-tags lezen en schrijven Project status
De uitdaging van dit project is het willen lezen en schrijven van mp3-tags, de ID3 tag. Je weet wel, de informatie over de groep, track nummer, track titel en dergelijke. Voor zover ik heb kunnen vinden zijn er 2 major versies voor ID3 tags, ID3v1.1 en ID3v2. Meer informatie over de ID3 standaard vind je hier.

ID3v1.1 is het gemakkelijkst om te lezen, omdat deze steeds de laatste 128 bytes van het mp3-bestand zijn en voor elk tag-info een vaste grote is vastgelegd. Deze slaag ik dus even over.

ID3v2 is een ander paar mouwen. Deze is gecreëerd om zo flexibel mogelijk te zijn en kan een grote hebben van 256 MB. Er kunnen afbeeldingen, hele songteksten en meer in bewaard worden. Open maar eens een mp3-bestand in kladblok. Tip! Maak een klein bestand met de laagste bitrate. Dit laad sneller en het is enkel te doen om de tag.
Een mp3-bestand inlezen als tekst, met StreamReader, lukt niet. De spaties die je ziet in kladblok, zijn bytes met de waarde '0'. Bleikbaar leest een StreamReader object enkel tot de eerste 0 byte.
We 
kunnen volgens mij het bestand beter binaire inlezen en daarna omzetten naar strings. Dat binaire inlezen geeft me voorlopig nog enkele problemen. Zeker bij grotere bestanden duurt het enorm lang voordat het bestand is ingelezen. 'k Zal daar verder achter zoeken in het HexEditor project.
We kunnen het inlezen beperken door de grootte van de tag te bepalen, laten we daar dan maar beginnen.

1. Tag-size

De tag-size staat in de header van de tag, deze bestaat uit de eerste 10 bytes van de tag. Hexadecimaal weergegeven kan deze er uitzien als volgt,

49 44 33 03 00 00 00 00 0F 76

De eerste 3 bytes  zijn altijd "ID3"(49 44 33), om aan te geven dat het om een ID3v2 tag gaat, direkt gevolgd door 2 bytes die de versie aangeven, in dit geval "03 00" voor ID3v2.3. De volgende byte is een vlag, waarvan voorlopig nog maar de eerste 3 bits (bit 7, 6 en 5) gebruikt worden. De laatste 4 bytes worden gebruikt om de grootte van de tag weer te geven. En hier komt het moeilijke gedeelte. De 4 bytes zijn gecodeerd als volgt.
De 7de bit van elke byte wordt verwaarloosd, waardoor er 28 bits overblijven. Deze worden terug bijgevuld tot 32 bits (4 bytes), deze 4 bytes geven dan de echte grootte van de tag weer. Zonder de 10 bytes die de header vormen, die moet je er nog bijtellen. In ons voorbeeld wordt dit dan,

Pre-alpha (theorie dus)
v 0.0.0
Source code (so far)
     00             00            0F             76
00000000  00000000  00001111  01110110
00000000  00000000  00000111  11110110
     00             00            07             F6
Omgerekend naar decimaal geeft dit 2038. De tag is dus 2038+10 bytes groot.
Hieronder vind je de code die ik gebruikt heb om de grote te berekenen.
Public Function GetTagSize(ByVal strFileName As String)

        Dim strmFile As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
        Dim rdrReader As New BinaryReader(strmFile)

        Dim bytBuffer() As Byte
        Dim intSize As Integer = 0
        Dim intBit As Int16
        Dim intBitValue As Long = 0
        Dim i As Integer

        'Read the header, 10 bytes
        '-------------------------
        bytBuffer = rdrReader.ReadBytes(10)

        'only the last 4 bytes are needed
        '--------------------------------
        Dim bArray() As Byte = {bytBuffer(9), bytBuffer(8), bytBuffer(7), bytBuffer(6)}

        'Put the 4 bytes in an Array as single bits of 1's and 0's
        '---------------------------------------------------------
        Dim bits As New BitArray(bArray)

        For i = bits.Length - 1 To 0 Step -1
            'For the tag every first 0 of the byte is removed
            '(0)0000000 (0)0000000 (0)0000000 (0)0000000
            'then put back together with padding the beginning with 0's
            'The padded 0's we can ignore. So to read the bits back to a decimal value
            'we have to take a shift in acount and the array is read left to right,
            'so we have to start with the highest bit first.
            Select Case True

                Case i = 31, i = 23, i = 15, i = 7
                    'These are the bits that are removed
                    'Set the decimal value back to 0, so there not
                    'added to the final size
                    intBitValue = 0

                Case i >= 24

                    intBit = Convert.ToInt16(bits.Get(i))
                    intBitValue = intBit * 2 ^ (i - 3)

                Case i >= 16
                    intBit = Convert.ToInt16(bits.Get(i))
                    intBitValue = intBit * 2 ^ (i - 2)

                Case i >= 8
                    intBit = Convert.ToInt16(bits.Get(i))
                    intBitValue = intBit * 2 ^ (i - 1)

                Case i >= 0

                    intBit = Convert.ToInt16(bits.Get(i))
                    intBitValue = intBit * 2 ^ (i)

            End Select
            intSize = intSize + intBitValue
        Next

        'We need to add 10 bytes for the header wich are not taken in to acount
        'see www.ID3.org for details
        intSize = intSize + 10

        strmFile.Close()
        rdrReader.Close()
        Return (intSize)

    End Function