Leer los tags id3v1 de un mp3

La mayoría de los archivos mp3s guardan en su interior una serie de etiquetas que informan de quien es el artista, el titulo, album, etc. mediante las etiquetas ID3. Existe 2 versiones principales de etiquetas, ID3V1 y ID3V2 que es bastante mas difícil y complicado extraer su información que en su primera versión. Leer los tags ID3V1 de los mp3s es muy fácil, solo tenemos que extraer los últimos 128 bytes del mp3.

En la versión 1.1 se añade información de numero de pista

De los ultimos 128 bytes, los 3 primeros deben de ser "TAG", sino la cancion no tiene este tipo de tags.
Title: 30 bytes (caracteres)
Artist: 30 bytes (caracteres)
Album: 30 bytes (caracteres)
Year: 4 bytes (caracteres 0-9)
Comment: 30 bytes (caracteres)
Genre: 1 byte representado como numero sin signo
Numero de pista: si el byte 28 de los comentarios es 0, no el caracter '0', entonces el byte 29 o ultimo (rango 0-29) sera un byte representado como numero sin signo que corresponde con el numero de pista.

Código de ejemplo

#include <iostream>
#include <fstream>

using namespace std;

struct id3v1
{
    1];
    char artist[31];
    char album[31];
    char year[5];
    char comment[29];
    char track;
    char genre;
};

char * genre[256] =
{
    "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", "Alt. Rock", "Bass",
    "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
    "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
    "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta Rap", "Top 40",
    "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave",
    "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk",
    "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
    "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival",
    "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
    "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus",
    "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera",
    "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove",
    "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad",
    "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Cappella",
    "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror",
    "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
    "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", "Christian Rock",
    "Merengue", "Salsa", "Trash Metal", "Anime", "JPop", "Synthpop",0
};

//genre[255] = (char*)("Unknown");

id3v1 getTags (char * file)
{
    char * buffer = new char[128];
    ifstream mp3("c:\\1.mp3");
    mp3.seekg(-128, ios::end);
    mp3.read (buffer,128);

    id3v1 tag;

    if (buffer[0] != 'T' || buffer[1] != 'A' || buffer[2] != 'G')
    {
        cout << "No tiene tags id3v1" << endl;
        return tag;
    }

    // copia a la estructura
    copy(buffer+3, buffer+33, tag.title);
    copy(buffer+33, buffer+63, tag.artist);
    copy(buffer+63, buffer+93, tag.album);
    copy(buffer+93, buffer+97, tag.year);
    copy(buffer+97, buffer+125, tag.comment);
    copy(buffer+126, buffer+127, &tag.track);
    copy(buffer+127, buffer+128, &tag.genre);

    // indico el final
    tag.title[30] = '\0';
    tag.artist[30] = '\0';
    tag.album[30] = '\0';
    tag.year[4] = '\0';
    tag.comment[28] = '\0';

    return tag;
}

int main()
{
    id3v1 tag = getTags ("c:\\1.mp3");
    cout << "Artist: " << tag.artist << endl;
    cout << "title: " << tag.title << endl;
    cout << "album: " << tag.album << endl;
    cout << "year: " << tag.year << endl;
    cout << "comment: " << tag.comment << endl;
    cout << "track: " << (unsigned int)tag.track << endl;
    cout << "genre id: " << (unsigned)(tag.genre) << endl;
    cout << "genre: " << ((unsigned)(tag.genre) > 147 ? "-" : genre[(unsigned)(tag.genre)]);
    cout << endl;

    return 0;
}

Comentarios