Sign in to follow this  
00dave

trouble with opening and loading a file

Recommended Posts

I'm trying to make a program that loads the IDv3 tag of an Mp3 file, but I can't find any information regarding the offsets and bytes of the information (name, artist, etc) If I did find it, would the best way to go about changing the name be to find the offset where the name begins, go to that point, load in however many bytes the name is, change it, then write it from the same place I loaded it? Thanks

Share this post


Link to post
Share on other sites
Here's a link on wotsit for the .mp3 format.

The approach would depend on the method used in the file. If they used NULL terminated strings, you would need to insert the characters of the new name followed by the null terminator. If they use pascal-style strings, you'll have to find where they store the string length, which will tell you how many bytes to load.

Once you know the offset, you can load it in like you said. Don't just overwrite it though, unless it's the same number of characters.

It will be easy to find if you use a hex editor. Just search the ASCII output until you find the text. If it's NULL terminated, you know what to do. If it's not, I'd look to see if there's a 32-bit variable directly before it that happens to contain a value which is the same number of bytes as the string. If it's not, you'll have to use that file format info to find the offset to the string length.

Share this post


Link to post
Share on other sites
Click on the one that says: "Mpeg 1.0/2.0 LayersI, II and III header and trailer formats [Laurent Clevy]"

It has all the information you need.

Oh, and it's easier than I thought. Here's the info on the artist, etc.


* TRAILER

at end of file - 128 bytes

offset type len name
--------------------------------------------
0 char 3 "TAG"
3 char 30 title
33 char 30 artist
63 char 30 album
93 char 4 year
97 char 30 comments
127 byte 1 genre
--------------------------------------------

- genre :

0 "Blues"
1 "Classic Rock"
2 "Country"
3 "Dance"
4 "Disco"
5 "Funk"
6 "Grunge"
7 "Hip-Hop"
8 "Jazz"
9 "Metal"
10 "New Age"
11 "Oldies"
12 "Other"
13 "Pop"
14 "R&B"
15 "Rap"
16 "Reggae"
17 "Rock"
18 "Techno"
19 "Industrial"
20 "Alternative"
21 "Ska"
22 "Death Metal"
23 "Pranks"
24 "Soundtrack"
25 "Euro-Techno"
26 "Ambient"
27 "Trip-Hop"
28 "Vocal"
29 "Jazz+Funk"
30 "Fusion"
31 "Trance"
32 "Classical"
33 "Instrumental"
34 "Acid"
35 "House"
36 "Game"
37 "Sound Clip"
38 "Gospel"
39 "Noise"
40 "AlternRock"
41 "Bass"
42 "Soul"
43 "Punk"
44 "Space"
45 "Meditative"
46 "Instrumental Pop"
47 "Instrumental Rock"
48 "Ethnic"
49 "Gothic"
50 "Darkwave"
51 "Techno-Industrial"
52 "Electronic"
53 "Pop-Folk"
54 "Eurodance"
55 "Dream"
56 "Southern Rock"
57 "Comedy"
58 "Cult"
59 "Gangsta"
60 "Top 40"
61 "Christian Rap"
62 "Pop/Funk"
63 "Jungle"
64 "Native American"
65 "Cabaret"
66 "New Wave"
67 "Psychadelic"
68 "Rave"
69 "Showtunes"
70 "Trailer"
71 "Lo-Fi"
72 "Tribal"
73 "Acid Punk"
74 "Acid Jazz"
75 "Polka"
76 "Retro"
77 "Musical"
78 "Rock & Roll"
79 "Hard Rock"
80 "Unknown"







So you CAN just overwrite it, since the sizes are fixed. How odd that genre is actually a number instead of a string. Guess they were really fixed on getting it into 128 bytes.

Note: The offsets are from the end of the file.

Share this post


Link to post
Share on other sites
Actually, how can the offset be 0 from the end? and 3 and 30 and so on? I tested them and they return garbage too. :/ Would the way to seek 128 bytes from the end of the file be

Well, I read the information correctly, one hurdle :)

But when I try to edit it and write it back... nothing changes, when I know that the char's in the array change, I tested that.


int main()
{
FILE *file;
int r;
char c[128];

file = fopen("song.mp3","rb");

fseek (file,0,SEEK_END);

long place = ftell(file);

place = place - 128;

fseek (file, place, SEEK_SET);

for(int x = 0; x < 128; x++)
{
fread (&c[x],sizeof(char),1,file);
if(c[x] == '_')
c[x] = ' ';
}
fseek (file, place, SEEK_SET);

fwrite (c,sizeof(char),128,file);

fflush(file); //
fclose (file);// not sure which of these is neccessary, or both

}



[Edited by - 00dave on March 14, 2006 6:43:17 PM]

Share this post


Link to post
Share on other sites
Okay, looking at an ascii output, the file resembles nothing like that file format said. It shouldn't be too hard to get it though looking at it now. If you look at the strings from the first 128 bytes of the file, you can see the title and auther, so that's where you would change them. Just count the offset from the beginning to one of those strings.

[Edited by - Drakkcon on March 14, 2006 9:45:08 PM]

Share this post


Link to post
Share on other sites
Thats what I did originally, but it was different in most of my mp3 music files... At the end it is all the same, and doing what I did in that snippet I get all of the information about artist title etc into that char array, I printed it out in consol to test, that isn't the problem, its just writing it back to the mp3 that is not working, I tested by adding some code to print out everything in the array right before I have the writing code above, and it is different than what is in the file... but after I run it the file is unchanged.

Share this post


Link to post
Share on other sites
In the mp3 files that I looked at, the ends are all completely blank. I don't think that the offset is from the end, which is why the file is unchanged after you edit it. I meant to look at the beginning with a hex editor, within the first 128 bytes. I successfully edited the .mp3's name by overwriting this data.

I'll post code in a sec.

PS: It turns out that they use pascal style strings. There's actually an int in the data that shows how long the title is. It's right before the title text.


[Edited by - Drakkcon on March 14, 2006 11:08:19 PM]

Share this post


Link to post
Share on other sites
I'm still working on making an ID3 tag editor, because I'm interested now.

It turns out, the reason that the dox on wotsit.org won't work is because they're out of date. Here's the spec that modern mp3s use.

Like I said, I'll post code in a while.

Never mind, it's 1:00 AM and I have to go to bed. Hope that that reference is enough man. Good luck.

Share this post


Link to post
Share on other sites
Hmm, maybe.. for me all of mine had 128 bytes at the end described exactly as that other doc said, but they also have info at the beginning with the name\artist\etc and this is what music players are using to get the information... It is just always different in most of my files, I can't find a way to load the correct information.

Share this post


Link to post
Share on other sites
If you want to change how it shows up in windows media player (or another modern player) use the ID3 v2 tags. If you want it to show up differently on a much older media player, use the 1D3 v1 tags.

Share this post


Link to post
Share on other sites
Yes, there are currently about 4 common versions: version 1.0, 1.1, 2.0, and 2.4.

If you look in that link I posted, it tells you how you can tell which to use (in part of the header). Also, be aware that new files will have both the "ID3" tag at the beginning, and the "TAG" tag at the end, whereas old files will just have "TAG". The 2.x versions are probably the ones you want to mess with.

Share this post


Link to post
Share on other sites
I'm getting kind of frustrated with myself... I read that doc, and it says that the tags will have an identifier, "TPE2" or "TIT1", and going through mp3's that I have, they all have this identifier followed by the title... but the sizes of spaces after the identifier is different in almost everyone, I just can't figure out how I would make a program to read these when they are all different, or most, some are the same... its really random I even noticed on some where the name was very long there was a ! character, which I'm guessing means it will be extended.. but I can't find a pattern or anything :/

Share this post


Link to post
Share on other sites
Can you post the hex and ascii output? It's possible that what shows up as space in the ascii output is actually some number without a corresponding 7-bit ascii character. I thought there were random gaps, but the gaps were actually numbers that specified how long the next string was.

Share this post


Link to post
Share on other sites
How exactly would I read a single byte? like 0C.. I have the stream right before it, but I can't figure out what to use to read it, int is too large, char is a char.. I need something 1 byte that I can use in a for loop :/

Share this post


Link to post
Share on other sites
Will it let me use that to allocate memory in a char *? and use it in a for loop?

for example...

unsigned char g;
fread(&g,1,1,file);
char name[g];
for(int x = 0; x &lt; g; x++)



[Edited by - 00dave on March 15, 2006 10:01:45 PM]

Share this post


Link to post
Share on other sites
Are you trying to read in the size of the string? Just so you know, that's an unsigned int, not a byte:

unsigned int sizeOfName;
fread(&sizeOfName, sizeof(unsigned int), 1, file);

char* nameBuffer = char[sizeOfName];
std::string name;

fread(nameBuffer, sizeOfName, 1, file);

name = nameBuffer; //now we have the name in a string.

delete[] nameBuffer;


Is this what you're trying to do? I'm not sure what the for loop's for.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this