Adding uniform silence between sentences in many spoken word files

Dan-Evans wrote on 2/20/2019, 3:32 PM

Hello! I'm using Sound Forge Pro v10.0c, and have been very successfully using the batch converter to process thousands of files to create uniform normalization, noise gate, and silence at the beginning and end of tracks.

My files are all spoken word tracks (they are audio tracks that support a reading program).

My current project includes about 700 files, each with roughly 10-15 sentences in them. I need to change the amount of silence between all sentences in my files to make them uniform. Most of the files currently have between .5 sec and 1.5 sec between each of them. I need to make it a uniform 1 second between each. I can easily use the Auto Trim feature to TRIM the space down to a uniform amount of silence. But I can't find a way to ADD silence in an automated way, except for wherever the cursor is, or at the start or end of the file.

One of the Auto Trim features creates regions, and I thought I could maybe automatically add silence at the start or end of all regions of a file, but I can't find a way to do this. I'm sure there must be a method, I just can't figure it out.

I'm stumped. Any suggestions for how I can automate this? Does SF Pro 11 or 12 offer any additional functionality that might accommodate this need?

Thank you for any ideas!!

Comments

rraud wrote on 2/20/2019, 5:15 PM

If you can find a script or someone to write one... that could be run through the SF batch utility to trim down head and tail silence. Check out the Sound Forge scripting archives. Some of those folks are still around. For instance, Ed at JETDV Scripts does scripting for Vegas and may be able to help or offer a recommendation.

"Does SF Pro 11 or 12 offer any additional functionality that might accommodate this need?"
- Not that I'm aware of.

Dan-Evans wrote on 2/21/2019, 9:20 AM

Thanks! I did some digging through the scripting archives and saw some examples of similar scripts. I'm working on building one for my needs. My plan at this point is to find anywhere there's at least .25 seconds of silence (indicating a space between sentences), and ADD an extra second of silence at that point -- then loop through the files again to auto-trim them down to an even second of silence. If I'm successful, I'll post the resulting script here!

shaun-toole wrote on 1/21/2020, 4:44 PM

If I'm successful, I'll post the resulting script here!

I hope your lack of a follow-up post doesn't mean you weren't successful. I could use the same functionality.

Dan-Evans wrote on 1/27/2020, 5:42 PM

My bad! I certainly intended to follow up. I did end up cobbling together a script that did what I needed. This code scans through a file, finds areas <-40db rms, and inserts additional silence. Depending on the length of the original pauses, it can add quite a lot of silence. But then I used a trim function to remove the extra silence, making the pauses uniform. And actually, Shaun, I think some of this script was taken from things that you posted long ago. Thanks!! 😄

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

public class EntryPoint {
public void Begin(IScriptableApp app) {
ISfDataWnd wnd = app.ActiveWindow;

   if (wnd == null)

   {
            MessageBox.Show("Open a file before running this script.");
            return;
   }

   ISfFileHost file = wnd.File;
   SfAudioStatistics[] stat = new SfAudioStatistics[file.Channels];

   Int64 ccStart    = file.SecondsToPosition(0.0);
   Int64 ccStep     = file.SecondsToPosition(0.2);
   Int64 ccLength   = file.Length;
   double minus40db = SfHelpers.dBToRatio(-40.0);
   bool LastWasSilent = false;

   SfAudioSelection aSelection = new SfAudioSelection(wnd);
   SfAudioMarker    aRegion    = new SfAudioMarker(ccStart, ccStep);

   int idUndo = file.BeginUndo("Insert Silence");

   // Step through open file 0.2 seconds at a time.
   // If the selected area is RMS < -40db then
   // Create a 0.2 second region centered in the selection

   for (Int64 ccPos = ccLength; ccPos - ccStep > 0; ccPos -= ccStep)
   {

       // Select area (ccPos, ccStep)

       aSelection.Start  = ccPos-ccStep;
       aSelection.Length = ccStep;

       // Update statistics for this selection

       file.UpdateStatistics(aSelection);
       file.WaitForDoneOrCancel();

       if ( ! file.StatisticsAreUpToDate)
       {
     MessageBox.Show("Something went wrong.");
            return;
       }

       for (uint ii = 0; ii < file.Channels; ++ii)
       {
          stat[ii] = file.GetStatistics(ii);
       }

       // If RMS of all channels < -40db then

       if (file.Channels==1 && stat[0].RMSLevel < minus40db)

       {
      // If this is the second or more silent region then
      // Add a second longer

      if (LastWasSilent)
      {
        long secToInsert = app.CurrentFile.SecondsToPosition(1.0);
        app.CurrentFile.InsertSilence(ccPos, secToInsert);
      }

      LastWasSilent = true;
       }

       else
       {
      LastWasSilent = false;
       }
   }

   file.EndUndo(idUndo, false);

}

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

 

shaun-toole wrote on 2/2/2020, 8:48 AM

Thanks for posting your script! Hell, I may have written what I was looking for and then forgotten it. 🤓

rraud wrote on 2/2/2020, 2:31 PM

SCS used to have a Sound Forge Script forum, I think it may be variable in the archives but I do not think anything can can be further posted.

Thanks for your contribution to the Sound Forge community, I'm sure the script will come handy for other members.