Reading ID3 Tags using C#


I'm currently working on an application which will read through a directory full of MP3's downloaded from USENET and then sort them into sub-folders titled after the "Artists - Album" stored within the ID3 tag.

I currently only have code that can read ID3v1 tags but am working on updated code which will allow for ID3v2+ tags to be read as well.

I use a STRUCT to hold the ID3 data and then use a quick little routine to parse the raw byte[] array containing the ID3 data read from the file into my STRUCT.

The STRUCT:

C#:
  1. private struct ID3Tag
  2. {
  3. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  4. public byte[] bTagHeader; //0-2
  5. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
  6. public byte[] bTrackName; //3-32
  7. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
  8. public byte[] bArtistsName; //33-62
  9. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
  10. public byte[] bAlbumName; //63-92
  11. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  12. public byte[] bYear; //93-96
  13. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
  14. public byte[] bComment; //97-126
  15. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
  16. public byte[] bGenres; //127
  17. }

Reading the last 128 bytes of the MP3 file into a byte[] array:

C#:
  1. private byte[] ReadID3FromFileToByte(string sLocalFile)
  2. {
  3. using (FileStream oFS = new FileStream(sLocalFile, FileMode.Open, FileAccess.Read))
  4. {
  5. using (BinaryReader oBR = new BinaryReader(oFS))
  6. {
  7. oBR.BaseStream.Position = (oFS.Length - 128);
  8. return oBR.ReadBytes((int)oFS.Length);
  9. }
  10. }
  11. }

The routine used to convert by the byte[] array into the STRUCT:

C#:
  1. private ID3Tag ID3BytesToID3Struct(byte[] bRawID3)
  2. {
  3. GCHandle hRawID3 = GCHandle.Alloc(bRawID3, GCHandleType.Pinned);
  4. ID3Tag id3NewTag = (ID3Tag)Marshal.PtrToStructure((hRawID3.AddrOfPinnedObject()), typeof(ID3Tag));
  5. hRawID3.Free();
  6. return id3NewTag;
  7. }

And the code which brings it all together:

C#:
  1. byte[] bFileData = ReadID3FromFileToByte(sMyInputFile);
  2. ID3Tag myID3 = ID3BytesToID3Struct(bFileData);

I hope this is able to help someone else out in their efforts to read an ID3 tag using C#.

Cheers!

, , ,

  1. #1 by Dan Shechter on March 12, 2007 - 4:38 PM

    What about taglib-sharp?

  2. #2 by eric on March 12, 2007 - 4:56 PM

    I’m sure taglib-sharp handles ID3 tags as well or even better than my code snips above. I was only trying to provide actual C# code to accomplish the function so people need not rely on third party libraries. :-D

  3. #3 by Mike Tsouris on October 26, 2008 - 9:11 AM

    Good job man. Where did you learn that id3 tags were always stored in the last 128 bytes?

    I’m having a hard time finding how to get the PICTURE (album art) from the file. I know it’s stored in there somewhere.

    I want to….

    1. Get pic (album art) from mp3
    2. Use GDI to cut the pic into a circle with the outside of the circle transparent (PNG). So you can think of it as cutting the pic to look like it’s a vinyl record.
    3. Drop it on the WPF stage and rotate it like a record while the song plays.

    You can go a head and steal the idea, and it’s easy as heck….. just got to get the pic. Everything else is elementary (creating the circle PNG image with outer transparency is a little tricky, but doable). Rotating it when the song plays, using WPF is like 2 lines of code.

  4. #4 by Brendan on January 8, 2009 - 1:03 AM

    Great post. Thanks!

  5. #5 by Tim on May 13, 2009 - 8:32 AM

    I downloaded taglib-sharp and they supplied the source code as well. It’s worth the download even if you just want to understand the tag structures since the source code is well-structured and modulated. It’s for .NET 2.0 so that works out well too.

  6. #6 by Ed on August 30, 2010 - 7:53 AM

    Thank you for your post. I was looking for a solution that doesn’t “rely on third party libraries”.

(will not be published)

Powered by WP Hashcash