10

I am trying to get the BPM property from an MP3 file:

enter image description here

I can see how to do this in a Windows Store App as per this question:

How to read Beats-per-minute tag of mp3 file in windows store apps C#?

but can't see how to use Windows.Storage in a Windows Forms app. (If I understand it correctly it's because Windows.Storage is specific to UWP.)

How can I read this in a Forms app? Happy to use a (hopefully free) library if there is nothing native.

Ben
  • 4,281
  • 8
  • 62
  • 103
  • BPM isn't always recorded in the metadata. It will sometimes have to be calculated. Are you trying to 1) Calcuate the BPM from audio. 2) Read generic metadata for all file types. 3) Read ID3v2 tags on MP3 files. 4) Read the same metadata Windows Explorer is. – Brad Jan 14 '18 at 18:52
  • 4 - I’m not worried about calculating the bpm as the tunes will already have been analysed in commercial software (RekordBox or Serato DJ). I just need to be able to grab the value – Ben Jan 14 '18 at 19:26
  • I guess you are looking for this https://stackoverflow.com/questions/37869388/how-to-read-extended-file-properties-file-metadata? – Tarun Lalwani Jan 21 '18 at 09:35

2 Answers2

10

You can use Windows' Scriptable Shell Objects for that. The item object has an ShellFolderItem.ExtendedProperty method

The property you're after is an official Windows property named System.Music.BeatsPerMinute

So, here is how you can use it (you don't need to reference anything, thanks to the cool dynamic C# syntax for COM objects):

static void Main(string[] args)
{
    string path = @"C:\path\kilroy_was_here.mp3";

    // instantiate the Application object
    dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));

    // get the folder and the child
    var folder = shell.NameSpace(Path.GetDirectoryName(path));
    var item = folder.ParseName(Path.GetFileName(path));

    // get the item's property by it's canonical name. doc says it's a string
    string bpm = item.ExtendedProperty("System.Music.BeatsPerMinute");
    Console.WriteLine(bpm);
}
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
2

There is a version TagLib that was ported to a portable class library (PCL) version that can be referenced by a Windows Forms and used to extract that information.

I referenced the PCL version TagLib#.Portable which is available via Nuget at TagLib.Portable

From there is was a simple matter of opening the file and reading the desired information.

class Example {

    public void GetFile(string path) {
        var fileInfo = new FileInfo(path);
        Stream stream = fileInfo.Open(FileMode.Open);
        var abstraction = new TagLib.StreamFileAbstraction(fileInfo.Name, stream, stream);
        var file = TagLib.File.Create(abstraction);//used to extrack track metadata

        var tag = file.Tag;

        var beatsPerMinute = tag.BeatsPerMinute; //<--

        //get other metadata about file

        var title = tag.Title;
        var album = tag.Album;
        var genre = tag.JoinedGenres;
        var artists = tag.JoinedPerformers;
        var year = (int)tag.Year;
        var tagTypes = file.TagTypes;

        var properties = file.Properties;
        var pictures = tag.Pictures; //Album art
        var length = properties.Duration.TotalMilliseconds;
        var bitrate = properties.AudioBitrate;
        var samplerate = properties.AudioSampleRate;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472