How to get track names from ID3 data?

Hi all, I am making a music player with a simple 16,2 LCD screen. I am using the Music Maker shield from Adafruit. I have the music player and screen finished, but it is currently displaying the filename (track1.mp3) and not the track name from the ID3 tag metadata, which is what I want. The Music Maker library does not contain any way to reference or retrieve the ID3 data, annoyingly. I am surprised this is so hard to come by!

I am a simple guy. I am good at Excel. I imagined this would be much the same. I would use a VLOOKUP in excel, with a list of all the filenames and track names, and the formula would return the track name. So this is what I have done. I have put together a .txt and a .csv of all the filenames and track titles. These are both on my SD card. I am desperate to find a way to look up the data and return the following 16 characters.

All the filenames end ".mp3" and in the CSV they are, obviously, comma-separated. All the track titles are 16 characters long, including spaces which I have used to add up to the end. I have done this to make it easier, to return always the next 16 characters. This will then display on the first line of the LCD and the 2nd line is blank.

I currently have no code for this, although if you want to see the unrelated music player code I am happy to share. Please can someone help? Either getting data from a .txt or .csv, or getting data directly from the .mp3 (although that'll probably be harder).

The tracks.txt looks like this:

track1.mp3 Welcome Horizons
track2.mp3 6:00 a.m.
track3.mp3 7:00 a.m.
track4.mp3 8:00 a.m.
track5.mp3 9:00 a.m.
track6.mp3 10:00 a.m.
track7.mp3 11:00 a.m.
track8.mp3 12:00 p.m.
track9.mp3 1:00 p.m.
track10.mp3 2:00 p.m.
track11.mp3 3:00 p.m.
track12.mp3 4:00 p.m.
track13.mp3 5:00 p.m.
track14.mp3 6:00 p.m.
track15.mp3 7:00 p.m.
track16.mp3 8:00 p.m.
track17.mp3 9:00 p.m.
track18.mp3 10:00 p.m.
track19.mp3 11:00 p.m.
track20.mp3 12:00 p.m.
track21.mp3 1:00 a.m.
track22.mp3 2:00 a.m.
track23.mp3 3:00 a.m.
track24.mp3 4:00 a.m.

etc

This is copied and pasted directly from the .txt - the | aren't in the text file. The values are separated by a tabkey press indent thingy - I am happy to remove that if it is easier, and have it literally just say "track1.mp3Welcome Horizons" if that will be easier to read from.

I have tried to be as detailed as possible and also tried to find the answer myself - asking for help is really a last resort, so please be nice!

Do a search for "Arduino read file line by line" or similar. You'll find multiple examples here and on stack exchange. Once you have that working, it will be fairly simple to split the track name out using strstr or strtok, but to start with, just read a line and print it.

if you know what ID3 Version your files are using, it's not super difficult to extract the metadata from the file

for example the ID3v1 tag is 128 bytes long and stored at the end of the mp3. The first 3 bytes of this tailer are 'T' 'A' and 'G' and then you have 30 bytes reserved for the title of the song.

So programmatically, it's just opening the file, seeking to filelength - 128 + 3 and read what's there, up to 30 bytes and then close the file.

1 Like

Ok that's helpful thank you! These files I have opened in Notepad and they do have TAG with the track name at the end as you describe. I shall try to give it a go! I must say, I am surprised to find so little about this online. I can't find anyone that has attempted it with an arduino. It doesn't feel something unique enough that I am the first person on the internet to try it with the Adafruit board!

if you google "arduino read MP3 tag" you probably will find many hits, including some in this forum

I think that since you're talking about an MP3 file, it really doesn't matter what device is reading the file. Open, seek, read and close are going be the same C++ commands whatever hardware you're using, so you can find examples for a PC and still use them on your Arduino.

@J-M-L I actually tried googling, in so much detail, but I really could find precious little apart from custom libraries that people had made which seemed so overly-complex and I was sure there was an easier way.

Your suggestion of reading backwards 125 bytes, for 30 bytes has WORKED, I am looking at it now gleefully thank you SO MUCH this has been bothering me for days!! Here is my code, for any future readers:

File myFile;

void setup() {
myFile = SD.open(filechar, FILE_READ);
    unsigned long tagdata = myFile.size();
    myFile.seek(tagdata - 125);
    String tracktitle = "";
    int j = 0;
    for(j = 0; j < 16; j++){
      tracktitle += (char)myFile.read();

    }
    myFile.close();
    lcd.begin(16, 2);
    lcd.print(tracktitle);
}

In my code, the variable filechar is assembled from multiple other variables that combine to make a filename. So that is where your filename would go.

EDIT: However, the trackname is like TracknameNULLNULLNULL etc, with the remainder of the 30 characters as NULL characters. Arduino displays a weird symbol on the screen to represent these NULL characters. I am confident that I could code it to stop reading when it reaches a NULL, but I went with the easier way of editing all the ID3 tags to be spaces instead of NULLs. Works perfectly!!

Great

Thanks for posting your code

Yes, you could test if the char is not null before adding it but your hack works too :wink: