The Roberts Family

C# Audio File Metadata Library

What Is JAudioTags?

A .Net dll written in C# to programmatically manipulate the metadata inside music files.


What File Formats are Supported?
.

95% of my audio collection is FLAC. The remaining 5% is MP3. Consequently these are the only two formats my code supports.

Before I could start coding I had to learn how metadata is stored inside these files. FLAC proved relatively straightforward. The standard is well defined and the on-line documentation is good. Start here. And here are some diagrams I created myself to help my understanding.

MP3 was a whole ‘nother ball game! The first thing I learned is that MP3 uses ‘ID3’ tags and there are multiple different ‘ID3’ tagging standards. Version 1 is simple but obsolete – it just uses the last 128 bytes of the file. Version 2 currently has four sub-versions 2,1, 2.2, 2.3 and 2.4, and stores metadata at the front of the file. Experiment showed that all of my MP3 files use version 2.3 whilst still retaining version 1 data at the end of the file - presumably for backwards compatibility. This may be because I use the excellent Mp3Tag for tagging and this program defaults to using ID3 v 2.3. Because of this I decided that my code would support only V 2.3 and v 1.

.

So I then went to the ID3 website (Which seems to no longer be online) to learn how version 2.3 tags are implemented - and, I confess, I found it difficult to understand. There are many options and alternative ways of doing things, which, I gather, are virtually never used in the real world. Various arcane encodings are used. SyncSafe integers, for example. So my code uses a ‘vanilla’ interpretation of ID3 v 2.3. Here are some diagrams I drew to help me understand the tag structure.

If you are reading this because you are thinking of writing your own MP3 tag manipulation code, my advice is DON’T. Use my code or one of the other libraries out there.

The only other music files I have on my music server are M3U playlists. These are just text files with paths pointing to other ‘real’ audio files or URLs pointing to Internet radio streams. So I added code to validate these – checking that the paths point to something real.


Quality
.

I have never worked as a professional programmer. This is amateur code. But, to the extent of my testing, it works. I have included a Test() method that takes a bunch of files, makes numerous modifications, saves and re-reads, then checks that the basic parameters of the file remain as they were at the beginning. I have also run third party validation tools against the files after modification and they all passed. I have now modified roughly 20,000 of my audio files using my code, and of the subset I have played, none were broken.

.

Obviously, no guarantee is offered, and you are strongly encouraged to BACKUP YOUR FILES prior to making changes. Should you find any bugs, contact me and I will either fix them or take the code down.

If you are nervous of running unknown code on your system, do not just use my dll. Instead download the source code, spend a week reading though it, then, when you are sure it is not malicious, fire up Visual Studio and compile a dll yourself.


Support
.

(This paragaraph was added in June 2018, eighteen months after this code was written and a year after it was uploaded to web.)

Since writing this code, my life has changed, and I no longer code. Life moves on, I guess! Consequently my C# sharp skills have faded as has my familiarity with this code.

.

As you may have figured, this is a roundabout way of saying that I DO NOT OFFER SUPPORT! Sorry folks. I lived this stuff two years ago. But today it makes my brain hurt. So please don't e-mail me asking for help.

Sorry. I'm an old guy. Cut me some slack!


Example Code

Here is some example code to show how the library is used:


using System;
using System.Collections.Generic;
using JAudioTags;

namespace chck02
{
class Program
{
static string Root = @"o:\testdata\testfolder2";
static string Log = @"D:\results.txt";
static string Errors = @"d:\Errors.txt";
static string OldName = "Prince";
static string NewName = "The artist formerly known as Prince";
static int Count = 1;

// This method matches the signature required by FileWalk.
// Its name is passed to the FileWalk constructor.
// It is called for every FLAC or MP3 file encountered.
static int ChangeArtistName(string Filename, LazySW SW)
{
AudioFile AFile = null;

// Open with ReadOnly as false - we are changing the files
if (Helpers.JGetExtension(Filename) == "FLAC")
{
AFile = new FLACFile(Filename, false);
}
if (Helpers.JGetExtension(Filename) == "MP3")
{
AFile = new MP3File(Filename, false);
}

if (AFile.ARTIST == OldName)
{
string Msg = string.Format("{0,3} - Changing {1}", Count++, AFile.AudioPath);
Console.WriteLine(Msg);
SW.WriteLine(Msg);
AFile.ARTIST = NewName;
AFile.Save(true);
return 1;
}
return 0;
}

static void Main(string[] args)
{
// Call the FileWalk method to visit all files in tree
AudioFile.FileWalk(Root, ChangeArtistName, new List<string>() { "MP3", "FLAC" }, Log, Errors);
Helpers.PressAnyKeyToContinue();
}
}
}


Downloads

Click here to download the dll.

Click here to download the source code to compile it yourself.

Click here for a document explaining how to use it.