Auto-updating BWF Loudness Metadata / Calculate and Populate Loudness

Kyle-Raub wrote on 9/21/2022, 1:57 PM

Hello,

Wondering if anyone has written a script (or possibly something similar) to do this. I have a large number of files that I would like to update the Loudness metadata for and save. Seems to not be an option via Batch Processing and I can't find a way to do it through the UI. I've seen over scripts that commit changes to all open files, but nothing that can take a directory and affect all files in it accordingly (like Batch Processing/Conversion).

1) Does anyone know of a solution for this?

2) If not a solution, where can I find the library of parameters and variables so I can call this Update BWF Loudness Metadata function in a C# script of my own?

Cheers,

Kyle

Comments

SP. wrote on 9/21/2022, 3:59 PM

@Kyle-Raub 

The following script opens all files in a given folder and it's subfolders and then does nothing, just saves the files again and closes them. Since it opens all files, it will stop if Sound Forge tries to open a file it cannot read. That's the easy part.

 

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:\"); //The default folder is C:\, change it to something different if you want

    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;
           }
        

//do nothing with audio file here. Replace this part with your modifications.

           openedFile.Save(SaveOptions.WaitForDoneOrCancel);

           openedFile.Close(CloseOptions.SaveChanges);

           File.Delete(Path.ChangeExtension(file.FullName, ".sfk")); //This command deletes all the sfk-files created by Sound Forge          
        
        }
    }

}

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

What tool do you use to calculate the loudness with? This value needs to be saved somewhere first, either in RAM (the loudness gauge needs to return the value) or in a file (for example written to a text file). Writing metadata to all files in a folder is not a problem.

It looks like there are tools in python available that will calculate the loudness of a given audio file, for example pyloudnorm https://www.christiansteinmetz.com/projects-blog/pyloudnorm https://github.com/csteinmetz1/pyloudnorm

Here is a batch script that uses ffmpeg volumedetect to get the maximum volume of an audio file. But I'm not sure this will be the same as your loudness value. https://gist.github.com/44213/fcf779bc9f1faf0cacc585ae7d7b808a

 

Edit: I just found out that Sound Forge can generate a loudness log under the tools menu. I think this can be automated with scripts. So you don't need the other tools mentioned above. But it's good to know alternatives.

I will look into the details.

Kyle-Raub wrote on 9/23/2022, 4:27 PM

@SP. Thank you for the detailed reply. Yes, your edit is correct and is primarily what I was intending to try to call or operate with a method in a script. I'm just not sure where to look to find the method/function/parameter for calling those specific actions in SFP. I'm on the most recent build of SFP15, btw.

SP. wrote on 9/23/2022, 7:47 PM

@Kyle-Raub The DoMenu method can simulate menu clicks via script.

So, the idea would be to cycle trough all audio files in the folder, load a file, do a loudness analyses via DoMenu over the whole file which will create a text file in the same folder, open the text file and read out the values at the end, write the value into a metadata field, save and close the file and load the next one.

Are you experienced in programming in C#? All Sound Forge specific interfaces and methods are described in the help file.