Subject:Automating a Paste to Multiple Files
Posted by: Dane Scott
Date:1/18/2006 6:25:56 AM
Someone please help...I really need to find a way to do this! I want to be able to customize a bunch of time announcement files with the call letters of a radio station. There are 720 files, so I'd definitely prefer to automate the pasting of the call letters tag audio onto each of the time announcement files. Basically what I need to do is... Open File Go to end of file Paste Save file with same name Close File Open Next file etc The routine would paste-in whatever audio I have copied to memory...so I'd first copy the call letters audio, then run the script (or batch, whatever) on the time announcement files. Can someone advise me on this? Feel free to also contact me directly at dane at tunetrackersystems dot com Thanks much, Dane |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Keeba
Date:1/18/2006 7:58:45 AM
Dane - have faith, if you look under the listing Desperately Need Help, you will find a solution to your problem. If it makes no snese, wait patiently...there is a guru here named TJ, and he can help you make snes of it. Still, in the meantime - look at the posting just below this one, and you will find the answer in there....somewhere... Hope it helps... A. |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/18/2006 10:10:07 AM
(this is the original poster with some additional information) I should add that I have already tried hotkey based programs but they don't like SoundForge very well...it requires that all the files processed be preloaded into SoundForge, which is impossible when there are 720 of them. I just tried again with a major hotkey program, and it's kind of a mess. So I really do want to use the script approach if at all possible. The other thing I forgot to mention, that needs to happen, is the removal of a half second of silence from the end of each of the cuts prior to pasting-in the new audio. Thanks again, Dane |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/18/2006 7:39:10 PM
There a a couple of ways to do this. You can use app.DoMenu(), or you can manipulate the files using methods on the ISfFileHost object. In either case, you need to decide how the script is going to know what files to open before you can do anything else. There are two main ways to do this, 1) have the script ask you to select multiple files from a standard File Open dialog. or 2) have the script process all of the files in a specified folder. Once you have a file open, you process it, save, and then close, then loop back to open the next file and so on. For app.DoMenu, your processing for each file would look like this. app.DoMenu("Transport.GoToEnd", false); app.DoMenu("Edit.Paste", false); app.DoMenu("File.Save", false); app.DoMenu("File.Close", false); using methods on the ISfFileHost object is more flexible, it would look something like this. Open File string strFilename = @"c:\My Files\myfile.wav"; ISfFileHost file = app.OpenFile(strFilename, false, false); if (file != null) { file.WaitForDoneOrCancel(); } Go to end of file not needed, most script edit operations require you to pass arguments that tell the position and size of the edit. paste file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); You need to paste from a file rather than from "memory" (do you mean the clipboard?). Save file with same name file.Save(SaveOptions.PromptIfBusy); Close File file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); Open Next file ??? I can't answer this part unless you say how you know what 'next' means? Are you processing all of the files in a folder? all of the files in a list? tj |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/18/2006 7:44:28 PM
to remove 1/2 second from the end of a file. Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec), tj |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/19/2006 9:10:37 AM
Thanks for the info...looks promising! Regarding your question about "next file," yes, we'd be processing all the files in a folder. |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/19/2006 12:28:25 PM
So far, here's the code I have received, kind of shoved together by me so we can look at it all at once. Being a total neophyte at this, I have to ask for your help in piecing it together into a final "thing" that I can run. Confirming your one question, yes, we'll need to process everything in the folder. Specifying a file to paste from is just fine, no problem there. My big problem is time now, since I have to get this working by Friday. What needs to come out of or change in what's below...and then, to run it, do I paste it into a window in Sound Forge? Thanks much! Dane Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec), app.DoMenu("Transport.GoToEnd", false); app.DoMenu("Edit.Paste", false); app.DoMenu("File.Save", false); app.DoMenu("File.Close", false); string strFilename = @"c:\My Files\myfile.wav"; ISfFileHost file = app.OpenFile(strFilename, false, false); if (file != null) { file.WaitForDoneOrCancel(); file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); file.Save(SaveOptions.PromptIfBusy); file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/19/2006 12:44:47 PM
I'm trying to "rapidly deploy here," so while waiting for a reply, I'm doing some fiddling of my own...though it's clear I don't know what I'm doing. I get a parse error as follows: Compiler error 0x80004005 on Line 9 : A namespace does not directly contain members such as fields or methods That occurs even if I remove the item in line 9. -- using System; using System.IO; using System.Windows.Forms; using SoundForge; //BEHAVIOR: Remove .5 sec silence from end of file, paste in contents from c:\capure\tag.wav //BEHAVIOR: then save and close file. Perform on all files in a given folder. Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec), string strFilename = @"c:\capture\tag.wav"; ISfFileHost file = app.OpenFile(strFilename, false, false); if (file != null) { file.WaitForDoneOrCancel(); file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); file.Save(SaveOptions.PromptIfBusy); file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/19/2006 1:30:01 PM
You need to declare a class that you code goes into. The easy way to do this is to open up the script editor, then hit the toobar button for 'new script' (its the scroll with a blue plus sign in front of it.). Choose your language from the dropdown menu. The default is C#, which is the preferred language because it gives better compile time error messages. This will generate a 'blank' script template with the correct class name and entry point name. then you just add your code inside the Begin() method where the /* begin here */ comment is. |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/19/2006 2:34:55 PM
Thanks TJ...I'll add that! Please also see the previous message above, in which I ask what the script body needs, in final form, to do the task. I cobbled together bits and pieces from what you had sent, but I don't think it has any provision in it to parse a folderful of files, for example. |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/19/2006 2:45:21 PM
Hi again, Ok, as we race against the clock, here's the latest version with the additional information provided by selecting "New Template." I get a compile error on line 23, and so far that's all that happens. Please help a poor codeless fool bring this baby to fruition! :-) Dane -- using System; using System.Windows.Forms; using SoundForge; public class EntryPoint { public void Begin(IScriptableApp app) { Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec), string strFilename = @"c:\capture\tag.wav"; ISfFileHost file = app.OpenFile(strFilename, false, false); if (file != null) { file.WaitForDoneOrCancel(); file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); file.Save(SaveOptions.PromptIfBusy); file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); } 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)); } } //EntryPoint |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/19/2006 5:24:45 PM
Ok, on line 23 you try to use the file object (calling it's SecondsToPosition() method) before you have created, or even declared it, so this is a syntax error. You have to OPEN the file first, so, the call to app.OpenFile(...) has to happen before you can make any call on the file oject. (i.e. any call that begins file.). Also, you never close the if (file != null) { code block. Which is also a syntax error. In this code it looks like you need close brace just after the file.Close(..) call. Finally, you never open any file to paste from. so fileToPasteFrom is an undeclared variable. so, putting your code in a more reasonable order, we have using System; using System.Windows.Forms; using SoundForge; public class EntryPoint { public void Begin(IScriptableApp app) { string strPaste = @"c:\capture\paste.wav"; ISfFileHost fileToPasteFrom = app.OpenFile(strPaste, false, false); if (fileToPasteFrom == null) return; // just quit if we can't open the paste file. string strFilename = @"c:\capture\tag.wav"; ISfFileHost file = app.OpenFile(strFilename, false, false); if (file != null) { file.WaitForDoneOrCancel(); Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec); file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); file.Save(SaveOptions.PromptIfBusy); file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); } } 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)); } } //EntryPoint which compiles, but probably doesn't do what you need yet. by the way, you should have a look at my recent post Generic Script to process files in a folder tj |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/20/2006 6:12:28 AM
You're right, we're definitely getting there! I think it's successfully pulling the half-second off the end of the "tag" file now, though it stops short of adding the "paste" file to the end of the "tag" file. A "message missing" error with details is below. I looked at your folder-parsing script example...thanks. I wish I had more of an aptitude for this stuff! How do we incorporate it into what we have so far? /me crosses his fingers...today's the deadline for the project! :-) -- System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: The parameter is incorrect. at SoundForge.ISfFileHost.OverwriteAudio(Int64 ccDst, UInt32 fuChanMaskDst, ISfFileHost fileSrc, SfAudioSelection aselSrc) at EntryPoint.Begin(IScriptableApp app) at EntryPoint.FromSoundForge(IScriptableApp app) --- End of inner exception stack trace --- at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at SoundForge.ScriptManager.Run(Assembly asm, String className, String methodName) at SoundForge.CodeDomScriptManager.Run(Assembly assy) at SoundForge.ScriptHost.RunScript(String szFile, String szSourceText, EngineType eType, Boolean fCompileOnly, Boolean fDebug) |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/20/2006 3:16:48 PM
The parameter is incorrect. at SoundForge.ISfFileHost.OverwriteAudio(Int64 ccDst, UInt32 fuChanMaskDst, ISfFileHost fileSrc, SfAudioSelection aselSrc) at EntryPoint.Begin(IScriptableApp app) Means what it says. One of the parameters to the OverwriteAudio call is incorrect. Unfortunately the error message doesn't say which parameter, but there are only 4 possibilities. file.OverwriteAudio( file.Length, // can be 'incorrect' if < 0 or > the length of the file.. 0, // 0 is always valid, for stereo files, 1 or 2 would also be OK fileToPasteFrom, // this is the most likely source of the problem. There are LOTS of ways this could be incorrect. new SfAudioSelection(fileToPasteFrom)); // will most likely be valid if param 3 is valid So the question is: did fileToPasteFrom succeed the open call? Is the the correct file? does it have the same number of channels (i.e. mono or stereo) as the file we are pasting into? tj Message last edited on1/20/2006 3:20:08 PM by_TJ. |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/20/2006 3:23:26 PM
I looked at your folder-parsing script example...thanks. I wish I had more of an aptitude for this stuff! How do we incorporate it into what we have so far? Well, basically you use that script instead of the blank script template that you got from the 'new script' toolbar button. Then you put your code to process a single file were the comment // TODO: do your file processing here. is. tj |
Subject:RE: Automating a Paste to Multiple Files
Reply by: _TJ
Date:1/20/2006 3:46:08 PM
So, for instance, your script might look like this. Note that since you are haveing trouble with OverwriteAudio(), I used app.DoMenu("Edit.Paste", false) instead in this example. OverwriteAudio() would be a better choice in a production script, since filling the clipboard with the correct audio before running the script would be an easy thing to overlook. Note also, that this script overwrites the original files, which is also probably a bad idea in a production script. It's safer to always preserve your source files so that you can re-run the script if something goes wrong. using System; using System.IO; using System.Windows.Forms; using SoundForge; public class EntryPoint { public void Begin(IScriptableApp app) { string strFolder = SfHelpers.ChooseDirectory("Choose a folder to process files from", @"c:\"); foreach (string strFilename in Directory.GetFiles(strFolder, "*.wav")) { SfStatus status = ProcessFile(app, strFilename); if (status != SfStatus.Success) { DPF("{0} : {1}", strFilename, status.ToString()); // quit if processing or save failed. break; } } } public bool bEnableProcessingLog = true; public SfStatus ProcessFile(IScriptableApp app, string strFilename) { if (bEnableProcessingLog) DPF("processing {0}", strFilename); ISfFileHost file = app.OpenFile(strFilename, false, true); if (null == file) return SfStatus.Fail; file.WaitForDoneOrCancel(); // remove the last 1/2 second of the file. Int64 ccHalfSec = file.SecondsToPosition(0.5); file.DeleteAudio(file.Length - ccHalfSec, ccHalfSec); // paste whatever audio is in the clipboard to the end of the current file. // since DoMenu always operates on the active Data Window, we need to make // sure that the file we want edited is active before using DoMenu(). file.Window.Active = true; file.Window.Cursor = file.Length; app.DoMenu("Edit.Paste", false); // the other way to paste is OverwriteAudio(), but it requires a pasteFrom file.. // file.OverwriteAudio(file.Length, 0, fileToPasteFrom, new SfAudioSelection(fileToPasteFrom)); // wait for processing to complete, and if it succeeds, save the file SfStatus status = file.WaitForDoneOrCancel(); if (status == SfStatus.Success) { file.Save(SaveOptions.PromptIfNoFilename); status = file.WaitForDoneOrCancel(); } file.Close(CloseOptions.DiscardChanges); return status; } 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)); } } //EntryPoint |
Subject:RE: Automating a Paste to Multiple Files
Reply by: Dane Scott
Date:1/24/2006 11:44:28 AM
That is absolute MAGIC!!! You nailed it right to the floor, TJ. Thanks so much for your help, you're a lifesaver. Dane |