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:

[csharp]

private struct ID3Tag
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] bTagHeader; //0-2
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] bTrackName; //3-32
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] bArtistsName; //33-62
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] bAlbumName; //63-92
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] bYear; //93-96
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] bComment; //97-126
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] bGenres; //127
}

[/csharp]

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

[csharp]

private byte[] ReadID3FromFileToByte(string sLocalFile)
{
using (FileStream oFS = new FileStream(sLocalFile, FileMode.Open, FileAccess.Read))
{
using (BinaryReader oBR = new BinaryReader(oFS))
{
oBR.BaseStream.Position = (oFS.Length – 128);
return oBR.ReadBytes((int)oFS.Length);
}
}
}

[/csharp]

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

[csharp]

private ID3Tag ID3BytesToID3Struct(byte[] bRawID3)
{
GCHandle hRawID3 = GCHandle.Alloc(bRawID3, GCHandleType.Pinned);
ID3Tag id3NewTag = (ID3Tag)Marshal.PtrToStructure((hRawID3.AddrOfPinnedObject()), typeof(ID3Tag));
hRawID3.Free();
return id3NewTag;
}

[/csharp]

And the code which brings it all together:

[csharp]

byte[] bFileData = ReadID3FromFileToByte(sMyInputFile);
ID3Tag myID3 = ID3BytesToID3Struct(bFileData);

[/csharp]

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)