Where is the Tempo (BPM) stored in an MP3 file?

Stoli wrote on 12/29/2021, 7:03 PM

I've been using Acid since 2000, but I use it strictly for creating multi-track DJ mixes of existing tracks (I don't produce any original music)... so I only use mp3 since it's the universal format to acquire tracks. I know Acid stores the Beatmap information with the file, but I'd like to know where, specifically. I've tried a couple different ID3 tag editors, but the BPM is not listed anywhere. I know some apps create their own tag and store it within a file, so I'm wondering if that is what Acid does. If so, can this be read by any software? I searched the KB and the Internet for the Acid Pro option "Save Beatmapper information with file" option on the Bearmapper's final screen (see at bottom), but it returns absolutely nothing. There very little info out there. I did find that other DAWs offer options where the info is saved within the metadata, which would be nice if Acid had that option.

You're probably gonna ask "why" ... after recording thousands of vinyl records, ripping another thousand in CDs, Napster, and then 20+ years of downloading, I have a lot of mp3's. So, a manual solution of typing the BPM in the filename is not what I'm looking for. Finding tracks for a project using BPM has always been tedious, so now that Windows reads metadata, I'd like to use the stored BPM data if possible... I'd like to do a batch copy&paste of all the BPMs to an attribute that Windows explorer can read, search, and sort. I did something similar to all my jpegs, so I'm looking to do this for my music collection.

Comments

SP. wrote on 12/29/2021, 10:01 PM

@Stoli You can create ACID metadata with Sound Forge Pro.

Stoli wrote on 12/30/2021, 9:15 AM

I'll give it a try, but I'm not looking to create metadata. I'm looking for a way to batch read metadata. I don't think SoundForge does anything like that. I tried a trial version of Magix's MP3 Deluxe 19 which is an MP3 organizer that reads metadata. This would have been perfect! Sadly the TEMPO field is blank (see below). To truly integrate the 2 Magix software's, it would be nice if Acid put the beatmapped tempo into this field so that Deluxe could organize tracks by BPM. This would not be difficult to do and a selling point for DJ's.

SP. wrote on 12/30/2021, 10:13 AM

@Stoli Sound Forge can be programmed in C# to do batch automation of any kind, but I need to look up first, if it can read out or store ACID metadata.

You can also use a tool like https://www.adsrsounds.com/product/software/adsr-sample-manager/ to sort your files by BPM. If your music doesn't have a dynamic tempo the values should be relatively accurate. Depending on the music it can happen that the BPM value shown is halved or doubled from the correct value.

Stoli wrote on 12/30/2021, 11:51 AM

ADSR appears to only work for samples. It only provided BPMs for loops. If I forced it to analyze a track, it returned too many incorrect bpm's, halfed, doubled or otherwise. Plus this would be tedious as there was no way to force it to change all tracks to loops. Thanks for the information tho. I found a website getsongbpm.com that analyzes mp3 and then updates your ID3 tags with the BPM, which is promising, but it only does it a few mp3's at a time, and it returned some incorrect BPMs. No beatmapper can fully be trusted... even in Acid, I often have to manually use the beatmapper to get the correct tempo. Finding a way to use all of Acid's metadata is really what I hope to do.

SP. wrote on 12/30/2021, 12:46 PM

@Stoli

I made the following script that will show the filename and BPM stored in the ACID metadata of each file openend in Sound Forge in a MessageBox. Could you try it in your Sound Forge with some of your files? You open the Script Editor under the View menu. Just copy the script inside an run it. If your files have an ACID BPM value saved inside, it should be displayed in the MessageBox. If this works the script could be modified to write the ACID BPM value in an ID3 tag.

using System;
using System.Windows.Forms;
using SoundForge;

public class EntryPoint {
public void Begin(IScriptableApp app) {
    
       foreach (ISfFileHost file in app.Files)
       {
           string filename = "Filename: " + file.Filename;
           string BPM = "BPM: " + file.ACID.Tempo;  
           MessageBox.Show(filename + "\n" + BPM, "Info");  
       }
}

public void FromSoundForge(IScriptableApp app) {
   ForgeApp = app; //execution begins here
   app.SetStatusText(String.Format("Script '{0}' is running.", Script.Name));
   Begin(app);
   app.SetStatusText(String.Format("Script '{0}' is done.", Script.Name));
}
public static IScriptableApp ForgeApp = null;
public static void DPF(string sz) { ForgeApp.OutputText(sz); }
public static void DPF(string fmt, params object [] args) { ForgeApp.OutputText(String.Format(fmt, args)); }
} //EntryPoint
 

Stoli wrote on 12/30/2021, 12:50 PM

I'll give it a try... thanks!

SP. wrote on 12/30/2021, 12:55 PM

It is also possible to generate Markers and store them in the file or read them out. There is an example script called "Add Markers.cs". Is that something you want to do?

Stoli wrote on 12/30/2021, 1:11 PM

The script returned the correct BPM of each song.

I don't need the generate Markers. I'm just looking for the BPM.

Stoli wrote on 12/30/2021, 1:16 PM

If there's a way to add an ID3 tag update to the BPM field, that would definitely work. Not sure how many mp3's I can load into soundforge at one time. I've only ever had 1 or 2 at a time. But this is way better than manually updating everything.

Stoli wrote on 12/30/2021, 1:20 PM

The script also correctly inserts a 0 for any mp3 not yet beatmapped, which is nice.

SP. wrote on 12/30/2021, 2:32 PM

@Stoli

I modified the script. Now you can choose a folder where your files are located. Sound Forge will try to open each file in the folder and all its subfolders and try to read out the ACID BPM value and try write it in the FourCC BPM-Tag.

 

Be careful and do not use this script without a backup of your files, just to be on the save side. Do not select the wrong folder (for example your drive C or the script will try to run on all files on C. It should stop when it tries to open a file that SF cannot open) I added a MessageBox that asks you if you are sure you selected the correct folder.

using System;
using System.IO;
using System.Windows.Forms;
using SoundForge;

public class EntryPoint {
public void Begin(IScriptableApp app) {
    
    string folder = SfHelpers.ChooseDirectory("Choose a folder to process files from", @"C:\");

    DialogResult dialogResult = MessageBox.Show("Are you sure to process " + folder + " and all its subfolders?", "WARNING", MessageBoxButtons.YesNo);
    
    if(dialogResult == DialogResult.Yes)
    {
        DirectoryInfo di = new DirectoryInfo(folder);
        
        foreach (FileInfo file in di.GetFiles("*", SearchOption.AllDirectories))
        {
           ISfFileHost openedFile = app.OpenFile(file.FullName, false, true);
        
           if(null == openedFile)
           {
               DPF("Could not open {0}", file.FullName);
               MessageBox.Show("Could not open " + file.FullName + "\n\nThe script will now stop.", "Error", MessageBoxButtons.OK);
               return;
           }
        
           uint TBPM = SfSummaryInfo.MakeFourCC('T', 'B', 'P', 'M');
        
           ISfFileSummaryInfo sumy = openedFile.Summary;
        
           sumy[TBPM] = "" + openedFile.ACID.Tempo;
        
           openedFile.Close(CloseOptions.SaveChanges);
        
        }
    }

}

public void FromSoundForge(IScriptableApp app) {
   ForgeApp = app; //execution begins here
   app.SetStatusText(String.Format("Script '{0}' is running.", Script.Name));
   Begin(app);
   app.SetStatusText(String.Format("Script '{0}' is done.", Script.Name));
}
public static IScriptableApp ForgeApp = null;
public static void DPF(string sz) { ForgeApp.OutputText(sz); }
public static void DPF(string fmt, params object [] args) { ForgeApp.OutputText(String.Format(fmt, args)); }
} //EntryPoint
 

Stoli wrote on 12/30/2021, 2:55 PM

BOOM

That's awesome. Windows reads the data perfectly. Tested it in Acid, just to be sure everything is working. This was a great solution. I really appreciate it. You save me hours per project. If they add just your ID3 portion of your script to the beatmapper, Acid would be perfect. Thank you so much. Happy New Year!

sheppo wrote on 1/1/2022, 3:37 AM

your use case for acid is essentially the same as mine. I have a library of many many songs. I use https://rekordbox.com/ for managing the tracks, and finding tracks that would mix well. It's beat detection isn't perfect - no software is, but it's close enough, most of the time. When it's not, you can manually edit track data, and best of all you get a searchable database of tracks, i believe it can also write out analysis data to ID3 if you desire.

It also deals with BPM drift well, when using it as a mix platform, so if you have recorded vinyl it will deal with that much easier than manually beat mapping in Acid.

Also, it's free.

So, I use it because on top of the library functionality, it also has a great track suggestion engine. e.g., if i'm playing this song, in this genre, at this BPM and key... what tracks will mix well in to it. Audition the mix in Rekordbox, and then drag it in to acid to add it in to my mix.

Additionally, it's also fully fledged DJ software, and one that interfaces with lots actual DJ hardware.. so if you ever want to make the jump to mixing live with hardware you'll have a platform where you already have your library of analysed songs.

I've tried a few other similar tools. Mixed In Key is very good at BPM detection, probably the best at the moment. Still not perfect, but it's not free.