Read mp3 tags id3_v1 C

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 1497 Views - Last Post: 03 August 2012 - 09:42 AM Rate Topic: -----

#1 RMCampos  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 02-August 12

Read mp3 tags id3_v1 C

Posted 02 August 2012 - 10:25 AM

Hello everyone!

I need to read mp3 tags. After a little search here, nothing especific found, then, post. The program is running, but the output has something wrong. Maybe some string length.


Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
   char tag[3];
   char title[30];
   char artist[30];
   char album[30];
   char year[4];
   char comment[30];
   unsigned char genre;
}mp3Tags;

int main()
{
   mp3Tags currentTags;
   char fileName[101];
   FILE *mp3File;

   printf("MP3 file name: "); fgets(nameFile, 100, stdin);

   fileName[strlen(fileName)-1] = '\0';

   // Open mp3 file
   mp3File = fopen(fileName, "rb");
   if (mp3File == NULL)
   {
      printf("\nUnable to open mp3 file!\n");
      exit(0);
   }

   // Puts the pointer to the end of file
   fseek(mp3File, 0, SEEK_END);

   // Get position
   long pos = ftell(mp3File);

   // Puts the pointer at the tag's read place
   fseek(mp3File, (pos - sizeof(mp3Tags)), SEEK_SET);

   // Read mp3 tags
   if(fread(&currentTags, sizeof(mp3Tags), 1, mp3File) != 1)
   {
      printf("\nUnable to read tags!\n");
      exit(0);
   }

   printf("\n\nTags:\n");
   printf("TAG: %s\n", currentTags.tag);
   printf("Title: %s\n", currentTags.title);
   printf("Artist: %s\n", currentTags.artist);
   printf("Album: %s\n", currentTags.album);
   printf("Year: %s\n", currentTags.year);
   printf("Comment: %s\n", currentTags.comment);
   printf("Genre: %c\n", currentTags.genre);

   printf("End! Closing mp3 file!\n");

   // Close mp3 file
   fclose(mp3File);

   return(0);
}



Ouput:
MP3 file name: Mozart.mp3


Tags:
TAG: TAGThe Miskolc Experience - 04 -
Title: The Miskolc Experience - 04 -
Artist: Therion
Album: The Miskolc Experience
Year: 2009
Comment:
Genre: ?
End! Closing mp3 file!



Thanks for the help.

PS: Linux here.

Is This A Good Question/Topic? 0
  • +

Replies To: Read mp3 tags id3_v1 C

#2 jimblumberg  Icon User is online

  • member icon

Reputation: 3055
  • View blog
  • Posts: 9,291
  • Joined: 25-December 09

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 10:29 AM

How many characters does your "Tag" contain? How many characters does your "year" contain? It looks like you are forgetting about the end of string character. If your year contains something like "1999" you need a size of 5 not 4.

Jim
Was This Post Helpful? 0
  • +
  • -

#3 RMCampos  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 02-August 12

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 10:53 AM

Jim, this is the question. I don't know exactly how many characters are needed. A piece of this code came from here: http://www.dreaminco...tags-from-mp3/. So, how can I know the length before read? And I need to set te right place (fseek) based on size of the struct, which is based on size of the arrays.
Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is online

  • member icon

Reputation: 3055
  • View blog
  • Posts: 9,291
  • Joined: 25-December 09

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 11:08 AM

That's one of the problems you face when you try to use code that has problems. I suggest you find another source for your program or better yet write your own code. You should start by Googling for the MP3 file structure. It appears to me that your structure is off by one, for all your character strings.

Quote

And I need to set te right place (fseek) based on size of the struct, which is based on size of the arrays.

That depends on whether this information is at the start of the MP3 stream or the end. You may also consider reading each member of your structure separately to avoid any possible structure padding issues.

Jim

This post has been edited by jimblumberg: 02 August 2012 - 11:11 AM

Was This Post Helpful? 0
  • +
  • -

#5 JackOfAllTrades  Icon User is online

  • Saucy!
  • member icon

Reputation: 5672
  • View blog
  • Posts: 22,524
  • Joined: 23-August 08

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 11:36 AM

I was feeling to urge to avoid yard work, so I spit this out for you.

The answer to your question is, that for ID3v1 files -- as per Wikipedia -- the tag appears at the very end of the file. So, you seek to the END of the file and back 128 bytes (the size of the TAG).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MP3_FILENAME "04 Sir Lancelot And Black Knight.mp3"

typedef struct{
   char tag[3];
   char title[30];
   char artist[30];
   char album[30];
   char year[4];
   char comment[30];
   unsigned char genre;
} mp3Tag;

int main()
{
	
	FILE *fp = fopen(MP3_FILENAME, "rb");
	if (!fp)
	{
		perror("File open failed");
		return EXIT_FAILURE;
	}

	mp3Tag tag;
	// Seek to 128 bytes before the end of the file
	if (fseek(fp, -1 * sizeof(mp3Tag), SEEK_END) == -1)
	{
		perror("fseek failed");
		return EXIT_FAILURE;
	}

	// Read the tag
	if (fread(&tag, sizeof(mp3Tag), 1, fp) != 1)
	{
		fprintf(stderr, "Failed reading tag\n");
		return EXIT_FAILURE;
	}

	// Make sure we've got what we expect.
	if (memcmp(tag.tag, "TAG", 3) == 0)
	{
		// Found the tag where we expected
		printf("Title: %.30s\n", tag.title);
		printf("Artist: %.30s\n", tag.artist);
		printf("Album: %.30s\n", tag.album);
		printf("Year: %.4s\n", tag.year);
		
		if (tag.comment[28] == '\0')
		{
			printf("Comment: %.28s\n", tag.comment);
			printf("Track: %d\n", tag.comment[29]);
		}
		else
		{
			printf("Comment: %.30s\n", tag.comment);
		}
		printf("Genre: %d\n", tag.genre);
	}
	else
	{
		fprintf(stderr, "Failed to find TAG\n");
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}


Output (first ID3v1 MP3 I could find):
Title: Sir Lancelot And Black Knight
Artist: Rick Wakeman
Album: Myths & Legends of King Arthur
Year: 1975
Comment: Lame 192 Stereo             
Track: 4
Genre: 94

Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is online

  • member icon

Reputation: 3055
  • View blog
  • Posts: 9,291
  • Joined: 25-December 09

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 11:43 AM

Just to remember to be careful, your character arrays don't have the end of string character.

Jim

This post has been edited by jimblumberg: 02 August 2012 - 11:46 AM

Was This Post Helpful? 0
  • +
  • -

#7 RMCampos  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 02-August 12

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 11:52 AM

JackOfAllTrades, jimblumberg, thanks!
Was This Post Helpful? 0
  • +
  • -

#8 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 1928
  • View blog
  • Posts: 5,737
  • Joined: 05-May 12

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 12:34 PM

Guys, remember to put the appropriate #pragma pack() instructions around the structure, just in case your compiler decides to put some extra padding around some of the members.

Okay, I'm confused. Why is the code above treating the strings in structure as C-strings?

First point of confusion: printing the year

All the code above is using printf("%s") to print out the strings from the TAGv1 structure, but the 4 character year doesn't have a null terminator. Are you playing the probabilities that after the 4 character year printf() will eventually run into a null terminator in the comment?.

Second point of confusion: maxed out strings
Similar issue to the year, but what if the song name, artist, etc. use all 30 characters? Won't printf() run on to the next adjacent bytes of data?

I haven't found the definitive source yet, but the links both JimBlumberg and JackOfAllTrades gave indicate that the "padding" can be a space or nul character. As far as I know, printf() prints spaces, so you won't know when the string ends.
Was This Post Helpful? 0
  • +
  • -

#9 jimblumberg  Icon User is online

  • member icon

Reputation: 3055
  • View blog
  • Posts: 9,291
  • Joined: 25-December 09

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 12:40 PM

Quote

Okay, I'm confused. Why is the code above treating the strings in structure as C-strings?

Yes, that can be confusing but since JackOfAllTrades used the size specifier things should still work even without the end of string character. Hence my caution about the character arrays not being actual C-strings (no end of string character).


Jim

This post has been edited by jimblumberg: 02 August 2012 - 12:41 PM

Was This Post Helpful? 0
  • +
  • -

#10 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 4888
  • View blog
  • Posts: 11,282
  • Joined: 16-October 07

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 01:08 PM

Actually, nothing in an MP3 tag has a null terminator. The tags are usually zero padded, but you do see spaces padding sometimes. In any case, they do to then end of their field size, where you'll get no terminator at all.

As tempting as slurping into a struct is, I'd probably avoid it. Rather, read the data segment into a char buffer and then copy it to a struct so you have your null terminators.
Was This Post Helpful? 1
  • +
  • -

#11 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 494
  • View blog
  • Posts: 1,543
  • Joined: 20-March 10

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 02:38 PM

Baavgai is correct ... +1


You should be reading this into a buffer of type char

This post has been edited by snoopy11: 02 August 2012 - 02:39 PM

Was This Post Helpful? 0
  • +
  • -

#12 JackOfAllTrades  Icon User is online

  • Saucy!
  • member icon

Reputation: 5672
  • View blog
  • Posts: 22,524
  • Joined: 23-August 08

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 04:01 PM

Man tough crowd! I just wrote that in like ten minutes having never done anything with MP3s before :)
Was This Post Helpful? 0
  • +
  • -

#13 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 1928
  • View blog
  • Posts: 5,737
  • Joined: 05-May 12

Re: Read mp3 tags id3_v1 C

Posted 02 August 2012 - 04:16 PM

Hey! It got you out of yard word for a little while, right? :lol:
Was This Post Helpful? 0
  • +
  • -

#14 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 4888
  • View blog
  • Posts: 11,282
  • Joined: 16-October 07

Re: Read mp3 tags id3_v1 C

Posted 03 August 2012 - 06:11 AM

This looked like too much fun.

So, um, I wrote a tag reader:
Spoiler


In the interests of full disclosure, I was surprised to find most of my tunes didn't have ID3v1 tags. So, I wrote a tagged file finder, too:
Spoiler

Was This Post Helpful? 1
  • +
  • -

#15 JackOfAllTrades  Icon User is online

  • Saucy!
  • member icon

Reputation: 5672
  • View blog
  • Posts: 22,524
  • Joined: 23-August 08

Re: Read mp3 tags id3_v1 C

Posted 03 August 2012 - 07:05 AM

baavgai, Spock's Beard? You fucking rock :)
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2