Community Forums Archive

Go Back

Subject:help with scripting
Posted by: regex_jedi
Date:10/28/2005 11:45:28 PM

OK, looks like no one knows enough about this language adn application to write for hire.. so its up to me..

Here is what I am trying to get done.. the following things
a- extract and encode contents of all tracks on a CD (I realize there is already a script like this, so this will be my starting point)
b- create regions in the file based on a Auto Region preset. I created a auto-region preset (using Tools/Auto Region, and made a preset doing what I want). I want my script to apply this auto-region to each file/track at this point.
c- specify a clip & trim to a single region (region #4 in my case) from the file. Right now, I manually do this by selecting Process/Auto Trim, then I select region 4 (selection button),and use my own preset.
d- once this is done, I then have the track as I want it. Now I just want it saved per the CDNAME-track#.
e- now go back and do each track on this CD as per all the above steps.

as I say, I can do this perfectly with the tool.. now I am trying to figure out how to make a script that basically does this action across all the tracks of a given CD. All I should have to enter is the CD name.. it should append a track# to each output file / track.

help help
regex_jedi

Subject:RE: help with scripting
Reply by: _TJ
Date:10/29/2005 2:26:54 PM

Well, first of all, If I understand you correctly, you want to rip tracks from a CD, then crop them, and then save them off to some format (mp3?).

Since you intend to edit after you crop, it would be better to rip to some non-compressed format such as .wav. Not only would this be faster, but it would also result in less degradation of the audio since if you rip to MP3 and then crop, you would be forced to re-encode the data to MP3 again when you save the cropped file.

So the basic script is

1) Ask the user where to put the files and what to name them.
2) Locate the CD Drive that has an Audio CD in it (or alternatively ask the User what drive to rip from).
3) Rip all of the tracks on the CD to .wav
4) Do AutoRegion on each file. ( is this necessary? what is the purpose here?)
5) Crop each file to region #4 (this step doesn't make any sense to me...)
6) Save each file to the desired format (MP3?, or do we need to ASK the user each time the script runs?)

In later posts, I will show code that will do the steps above, although at this point I'm not certain that I understand the task well enough to do this for all steps.

tj


Subject:RE: help with scripting
Reply by: _TJ
Date:10/29/2005 3:16:11 PM

Ok, so open the Script Editor window in Sound Forge and create new Script of type C#
(that's the toolbar button with a blue + on it).

That should give you this:

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

public class EntryPoint {
public void Begin(IScriptableApp app) {

/*begin here*/


}

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, object o) { ForgeApp.OutputText(String.Format(fmt,o)); }
public static void DPF(string fmt, object o, object o2) { ForgeApp.OutputText(String.Format(fmt,o,o2)); }
public static void DPF(string fmt, object o, object o2, object o3) { ForgeApp.OutputText(String.Format(fmt,o,o2,o3)); }
public static string GETARG(string k, string d) { string val = Script.Args.ValueOf(k); if (val == null || val.Length == 0) val = d; return val; }
public static int GETARG(string k, int d) { string s = Script.Args.ValueOf(k); if (s == null || s.Length == 0) return d; else return Script.Args.AsInt(k); }
public static bool GETARG(string k, bool d) { string s = Script.Args.ValueOf(k); if (s == null || s.Length == 0) return d; else return Script.Args.AsBool(k); }
} //EntryPoint


Now replace the text /*begin here*/ with this


// ask the user to choose a filename & directory,
// (we will add track# automatically)
//
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "MPEG Layer 3 (*.mp3)|*.mp3";
dlg.InitialDirectory = @"d:\temp";
dlg.Title = "Choose a Folder and Base Filename";
dlg.CheckPathExists = true;
dlg.CheckFileExists = false;
dlg.DefaultExt = ".mp3";
if (DialogResult.OK != dlg.ShowDialog(null))
{
// no file chosen
return;
}
string strBaseFilename = dlg.FileName;

// ask the user to choose a MP3 template.
//
ISfRenderer rend = app.FindRenderer(null, ".mp3");
if (null == rend)
{
MessageBox.Show(app.Win32Window, "Could not find file format");
return;
}
ISfGenericPreset tpl = rend.ChooseTemplate(IntPtr.Zero, "192 Kbps, CD Transparent Audio");

// locate a CD Drive that has an Audio CD in it.
//
ISfCDDrive drvToRip = null;
foreach (ISfCDDrive drv in app.CDDrives)
{
DPF("checking {0} for an audio cd", drv.Letter);
if ((drv.DiscType & DiscType.Audio) == DiscType.Audio)
{
// found an audio cd.
drvToRip = drv;
break;
}
}
if (null == drvToRip)
{
MessageBox.Show(app.Win32Window, "Can't find an Audio CD to Rip.");
return;
}

/* add code to rip here */


Now Save this script as RipTest.cs and run it.

You should see first a dialog that asks you what filename to save as, then
a dialog that asks you what MP3 settings to use, and then and error message
telling you that no Audio CD could be found. (unless you have an audio CD in the drive).

Thats step 1 and step 2. More in the next post.

tj





Subject:RE: help with scripting
Reply by: _TJ
Date:10/29/2005 3:24:47 PM

Ok, for step 3) we have to add the code that rips a CD to one file per track.
To do that , replace /* add code to rip here */ in our test script
with the following.


// Now rip each track in the Audio CD to a separate file,
// and store the file objects in an array so we can use them for processing later.
//
System.Collections.ArrayList files = new System.Collections.ArrayList();

foreach (SfAudioMarker mk in drvToRip.DiscTOC.MarkerList())
{
ISfFileHost file = drvToRip.ExtractAudio(mk.Name,mk.Start,mk.Length,0);
if (null == file)
break;

if (SfStatus.Cancel == file.WaitForDoneOrCancel())
break;

file.Summary.Title = mk.Name;
file.Summary.TrackNo = mk.Ident.ToString();

files.Add(file);
break;
}

/* add code here to process the files. */


This block of code will create a list of Markers from the Table of Contents (TOC) of the Audio Disc. We can then walk through the list of markers and extract audio from the CD into a set of files. Each marker in the TOC corresponds to a track.

After we create each new file, we want to set it's TrackNo property to match the track we got the data from, and save the ISfFileHost object into an array for later use.

tj


Message last edited on10/29/2005 4:17:03 PM by_TJ.
Subject:RE: help with scripting
Reply by: _TJ
Date:10/29/2005 3:38:00 PM

In step 4) we need to process the files. This is the part that I don't really think I understand well enough to code, but assuming that I do. Basically we want to run Auto Region on each file and the crop it to the 4th region.

so we need to replace /* add code here to process the files. */ with


foreach (ISfFileHost file in files)
{
file.DoEffect("Auto Region", "My Preset", SfAudioSelection.All, EffectOptions.EffectOnly);
if (SfStatus.Cancel == file.WaitForDoneOrCancel())
break;

SfAudioMarker mk = file.Markers[3]; // get the 4th marker or region.
file.CropAudio(mk.Start, mk.Length);
}

/* add code here to save the files */


Subject:RE: help with scripting
Reply by: _TJ
Date:10/29/2005 4:12:44 PM

And finally in step 6) we want to save our (newly cropped) files to the locaton and format that the user chose in step 2).

so we replace /* add code here to save the files. */ with


foreach (ISfFileHost file in files)
{
// pull the filename apart, so that we can add the Track #
string strDir = Path.GetDirectoryName(strBaseFilename);
string strBase = Path.GetFileNameWithoutExtension(strBaseFilename);
string strExt = Path.GetExtension(strBaseFilename);

// build a new filename from the basic filename + the track #
string strFilename = Path.Combine(strDir, strBase + " " + file.Summary.TrackNo + strExt);

// Save to that filename
file.SaveAs(strFilename, rend.Guid, tpl, RenderOptions.RenderOnly);
file.WaitForDoneOrCancel();

// uncomment this if you want to close the files after they have been saved.
// file.Close(CloseOptions.FailIfChanged);
}



The only trick here is that we want to add the track number to the filename, There are a number of ways to do this, You could just strip off the file extension, append the track number, then put the file extension back. I chose a slightly more flexible method, we break the filename in to directory, file and extension, then put the parts back together along with the track number.

then we just SaveAs() the file and Close() it.

tj

Subject:RE: help with scripting
Reply by: regex_jedi
Date:10/30/2005 1:10:28 AM

wow.. thanks alot .. just getting an idea of how this all fits together is really apprecaited..

I tried to use the code as is, but I got an error on the last posted section of code (it says "Compiler error 0x80004005 on Line 84,24 : The type or namespace name 'Path' could not be found (are you missing a using directive or an assembly reference?")...

I will look around the other posts for use of Path. I expect it is just a system declaration that should be made or something.. if you get a chance to post a correct, it would be appreciated..

even if you don't.. thanks very much for the help.. truly appreciated..

regex_jedi

Subject:RE: help with scripting
Reply by: regex_jedi
Date:10/30/2005 1:19:21 AM

cool beans.. i figured out the "using System.IO;" declare was missing.. it compiles now... I will work the customizations out tomorrow (after I get some sleep :) )..

thanks alot TJ!

regex_jedi

Subject:RE: help with scripting
Reply by: _TJ
Date:10/30/2005 4:53:12 PM

Oops, sorry about that. I figured that breaking the script up into pieces
would make it a bit more clear. I'm glad that worked out.

I should note, however, that It might be better to do the processing and saving all in one loop.

Or even to do the rip/process/save in one big loop, although that might end up being slower if the CD drive has time to spin down. On the other hand, having only one file open at a time will make the script less of a memory hog.

tj

Subject:RE: help with scripting
Reply by: regex_jedi
Date:10/30/2005 4:58:41 PM

TJ..

thanks.. everything is working now.. except the thing is crashing upon completion (even though it did all the functions fine).. I posted it to another post as a question thinking maybe others have had that problem too... i must be overlooking something obvious to get a crash at the end of a script that does everything else right..

regex_jedi

Go Back