Subject:crash after inserting regions
Posted by: Alastair MacGregor
Date:1/19/2007 11:31:45 AM
Hi, I'm attempting to implement a script that basically does the opposite of extract regions - it takes a list of files as a parameter and writes every file into a single master file with appropriate regions. The script seems to be working Ok, however if I add more than one region (so paste in more than 1 file) Sound Forge locks up when I zoom out (long after my script has finished). If I save the generated file to disk before attempting to zoom/scroll Sound Forge doesnt crash, if my script attempts to SaveAs() I get the crash. Any ideas what I might be doing wrong, or if this is a SoundForge bug? My code follows (this function is called directly from FromSoundForge() with an array of file names to process): public void Import(string[] files) { long cursor = 0; ISfFileHost fileHost = m_SoundForge.OpenFile(files[0], true, true); if(fileHost == null) { throw new Exception("Couldn't open file " + files[0]); } // we'll use the same wave format as the first file ISfFileHost masterFile = m_SoundForge.NewFile(fileHost.DataFormat, false); if(masterFile == null) { throw new Exception("Couldn't create master file"); } fileHost.Close(CloseOptions.DiscardChanges); long gap = masterFile.SecondsToPosition(GapLength); masterFile.InsertSilence(cursor, gap); cursor += gap; foreach(string file in files) { fileHost = m_SoundForge.OpenFile(file, true, true); if(fileHost == null) { MessageBox.Show("Couldn't open file " + file); continue; } SfAudioSelection selection = new SfAudioSelection(fileHost); // copy in wave data masterFile.OverwriteAudio(cursor, 0, fileHost, selection); long regionStart = cursor; long regionLength = selection.ccLength; // move cursor to the end of this data cursor += selection.ccLength; fileHost.Close(CloseOptions.DiscardChanges); // pad with silence masterFile.InsertSilence(cursor, gap); cursor += gap; // add the region masterFile.Markers.AddRegion(regionStart, regionLength, file); } } I was seeing strange behaviour if I called InsertSilence() before I added the region, so perhaps I need to build a list of regions and add them all once I'm finished to work around this. Thanks, Alastair Message last edited on1/19/2007 11:39:59 AM byAlastair MacGregor. |
Subject:RE: crash after inserting regions
Reply by: Alastair MacGregor
Date:1/19/2007 11:36:19 AM
some additional info - if I don't add the regions at all Sound Forge still crashes, so it must be more to do with my use of OverwriteAudio or InsertSilence...? Alastair |
Subject:RE: crash after inserting regions
Reply by: _TJ
Date:1/19/2007 11:37:07 AM
Would you please put <pre> </pre> tags around your code so that the indenting doesn't get lost? It's very hard to read without them. tj Message last edited on1/19/2007 11:37:36 AM by_TJ. |
Subject:RE: crash after inserting regions
Reply by: Alastair MacGregor
Date:1/19/2007 11:40:26 AM
done - sorry about that. one additional snippet of info - removing the calls to InsertSilence() don't help either. Ali |
Subject:RE: crash after inserting regions
Reply by: Alastair MacGregor
Date:1/19/2007 11:53:33 AM
A work around seems to be to open the files with fNoWindow = false - presumably SF doesn't deal with the case where peak data hasnt been generated, and it doesnt generate it during OverwriteAudio(). I also had to open all files and calculate a total length so that I only had one call to InsertSilence() - calls to AddRegion() followed by calls to InsertSilence() seems to screw up the regions... Ali |
Subject:RE: crash after inserting regions
Reply by: _TJ
Date:1/19/2007 11:57:58 AM
Ok. I can reproduce the hang. I'll get back to you. One thing you might try is opening the files m_SoundForge.OpenFile(file, true, false); Since the true in the second parameter defeats creating peak files, which Sound Forge is going to need when it tries to draw zoomed-out on the composite file. Anyway. I'll need to spend some time to see what's really going on with the hang. The above tip is just my guess at this time. tj Message last edited on1/19/2007 11:58:49 AM by_TJ. |
Subject:RE: crash after inserting regions
Reply by: _TJ
Date:1/20/2007 4:07:27 PM
Ok, so it looks like you are running into 2 bugs. One new and one known. First the known bug. ISfFileHost.Save(...) doesn't work for files created by a script with If IScriptableApp.NewFile(wfx, true). ISfFileHost.SaveAs() and ISfFileHost.RenderAs() do work, however, so this bug has a fairly simple workaround. Also if you use NewFile(wfx, true), you MUST close the new file in the script, because the user won't be able to save or close it. The other bug is one we didn't know about before. If you defeat peak file creation when you open files using ISfFileHost.OpenFile("name", fReadOnly, true), and then copy parts of the peakless files into other files. using ISfFileHost.OverwriteAudio() And then zoom out, Sound Forge will hang. The solution here is to SaveAs() or RenderAs() the output file in the script, and then close it before the user has a chance to try and do the zooming. Basically, if the peak file is missing for a section referenced in an Overwrite, then we will hang while trying to fetch peaks for drawing. So you need to avoid creating that situation using a script. Script is the only way to create that situtation, which is why we didn't notice it before. Here's the script I used for testing. It uses your code to append the files together, then SaveAs() to save the file as .mp3. tj using System; using System.IO; using System.Windows.Forms; using System.Runtime.InteropServices; using SoundForge; public class EntryPoint { public void Begin(IScriptableApp app) { // pick a set of files. OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Choose files to process."; ofd.FileName = @"E:\*.*"; ofd.Filter = "Wave (*.wav)|*.wav|Perfect Clarity Audio (*.pca)|*.pca|Mpeg Layer 3 (*.mp3)|*.mp3|All files (*.*)|*.*"; ofd.DefaultExt = "*.*"; ofd.Multiselect = true; if (DialogResult.OK != ofd.ShowDialog(app.Win32Window)) return; ISfFileHost file = Import(ofd.FileNames); //file.RenderAs(@"e:\media\henley2.mp3", ".mp3", "160 Kbps, CD Transparent Audio", null, RenderOptions.RenderOnly); file.SaveAs(@"e:\media\henley2.mp3", ".mp3", "160 Kbps, CD Transparent Audio", RenderOptions.RenderOnly); //file.Save(SaveOptions.AlwaysPromptForFilename); //file.Save(SaveOptions.PromptIfNoFilename); file.WaitForDoneOrCancel(); file.Close(CloseOptions.DiscardChanges); } public double GapLength { get { return 2.0; } } public ISfFileHost Import(string[] files) { long cursor = 0; ISfFileHost fileHost = ForgeApp.OpenFile(files[0], true, true); if (fileHost == null) { throw new Exception("Couldn't open file " + files[0]); } // we'll use the same wave format as the first file ISfFileHost masterFile = ForgeApp.NewFile(fileHost.DataFormat, false); if (masterFile == null) { throw new Exception("Couldn't create master file"); } fileHost.Close(CloseOptions.DiscardChanges); long gap = masterFile.SecondsToPosition(GapLength); masterFile.InsertSilence(cursor, gap); cursor += gap; foreach (string file in files) { fileHost = ForgeApp.OpenFile(file, true, true); if (fileHost == null) { MessageBox.Show("Couldn't open file " + file); continue; } SfAudioSelection selection = new SfAudioSelection(fileHost); // copy in wave data masterFile.OverwriteAudio(cursor, 0, fileHost, selection); long regionStart = cursor; long regionLength = selection.ccLength; // move cursor to the end of this data cursor += selection.ccLength; fileHost.Close(CloseOptions.DiscardChanges); // pad with silence masterFile.InsertSilence(cursor, gap); cursor += gap; // add the region masterFile.Markers.AddRegion(regionStart, regionLength, file); } return masterFile; } 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 Message last edited on1/20/2007 4:09:06 PM by_TJ. |
Subject:RE: crash after inserting regions
Reply by: _TJ
Date:1/20/2007 4:50:58 PM
calls to AddRegion() followed by calls to InsertSilence() seems to screw up the regions... Actually, this has nothing to do with insert silence. Anytime you insert or append or remove before (or exactly on top of) a marker or region, then the marker or region is moved to account for the added/removed time. It's the exactly-on-top-of case that's messing you up here. So if a marker is right at the end of the file, and you append to the file, we move the marker to the new end of the file. That's not what you want to have happen in this case, but the workaround is pretty easy. |
Subject:RE: crash after inserting regions
Reply by: Alastair MacGregor
Date:1/22/2007 6:05:44 AM
Thanks for your help |