Update of /cvsroot/audacity/audacity-src/src/effects
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv368/src/effects

Modified Files:
        TruncSilence.cpp TruncSilence.h 
Log Message:
More options plus fix for boundaries (patch by Philip Van Baren)

Index: TruncSilence.h
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/effects/TruncSilence.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- TruncSilence.h      12 Jun 2008 12:41:31 -0000      1.8
+++ TruncSilence.h      30 Apr 2009 17:50:21 -0000      1.9
@@ -10,6 +10,7 @@
   //ToDo ... BlendFrames on "fade-out"
   //ToDo ... BlendFrameCount is a user-selectable parameter
   //ToDo ... Detect transient signals that are too short to interrupt the 
TruncatableSilence
+  Philip Van Baren (more options and boundary fixes)
 
 **********************************************************************/
 
@@ -55,8 +56,10 @@
 
  private:
    sampleCount mBlendFrameCount;
+   int mTruncInitialAllowedSilentMs;
    int mTruncLongestAllowedSilentMs;
    int mTruncDbChoiceIndex;
+   double mSilenceCompressRatio;
 
 friend class TruncSilenceDialog;
 };
@@ -80,6 +83,10 @@
    EffectTruncSilence *mEffect;
    wxStaticText * pWarning;
 
+   wxStaticText *mRatioLabel;
+   wxSlider *mRatioSlider;
+   wxStaticText *mRatioText;
+
 private:
    DECLARE_EVENT_TABLE()
 };

Index: TruncSilence.cpp
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/effects/TruncSilence.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- TruncSilence.cpp    23 Mar 2009 00:32:54 -0000      1.22
+++ TruncSilence.cpp    30 Apr 2009 17:50:21 -0000      1.23
@@ -5,6 +5,7 @@
   TruncSilence.cpp
 
   Lynn Allan (from DM's Normalize)
+  Philip Van Baren (more options and boundary fixes)
 
 *******************************************************************//**
 
@@ -38,11 +39,20 @@
 
 bool EffectTruncSilence::Init()
 {
-   mTruncLongestAllowedSilentMs = 
gPrefs->Read(wxT("/CsPresets/TruncLongestAllowedSilentMs"), 200L);
+   mTruncInitialAllowedSilentMs = 
gPrefs->Read(wxT("/CsPresets/TruncInitialAllowedSilentMs"), 200L);
+   if ((mTruncInitialAllowedSilentMs < 0) || (mTruncInitialAllowedSilentMs >= 
9999999)) {  // corrupted Prefs?
+      mTruncInitialAllowedSilentMs = 200L;
+      gPrefs->Write(wxT("/CsPresets/TruncInitialAllowedSilentMs"), 
mTruncInitialAllowedSilentMs);
+   }
+   mTruncLongestAllowedSilentMs = 
gPrefs->Read(wxT("/CsPresets/TruncLongestAllowedSilentMs"), 1000L);
    if ((mTruncLongestAllowedSilentMs < 0) || (mTruncLongestAllowedSilentMs >= 
9999999)) {  // corrupted Prefs?
-      mTruncLongestAllowedSilentMs = SKIP_EFFECT_MILLISECOND;
+      mTruncLongestAllowedSilentMs = 1000L;
       gPrefs->Write(wxT("/CsPresets/TruncLongestAllowedSilentMs"), 
mTruncLongestAllowedSilentMs);
    }
+   
+   if( mTruncLongestAllowedSilentMs < mTruncInitialAllowedSilentMs )
+      mTruncInitialAllowedSilentMs = mTruncLongestAllowedSilentMs;
+
    mTruncDbChoiceIndex = gPrefs->Read(wxT("/CsPresets/TruncDbChoiceIndex"), 
4L);
    if ((mTruncDbChoiceIndex < 0) || (mTruncDbChoiceIndex >= 
Enums::NumDbChoices)) {  // corrupted Prefs?
       mTruncDbChoiceIndex = Enums::NumDbChoices - 1;  // Off-Skip
@@ -55,6 +65,11 @@
       mBlendFrameCount = 100;
       gPrefs->Write(wxT("/CsPresets/BlendFrameCount"), 100);
    }
+   mSilenceCompressRatio = 
0.1*gPrefs->Read(wxT("/CsPresets/SilenceCompressRatio"), 40L);
+   if ((mSilenceCompressRatio < 1.0) || (mSilenceCompressRatio > 20.0)) {  // 
corrupted Prefs?
+      mSilenceCompressRatio = 4.0;
+      gPrefs->Write(wxT("/CsPresets/SilenceCompressRatio"), 40L);
+   }
    return true;
 }
 
@@ -78,16 +93,20 @@
    if (dlog.GetReturnCode() == wxID_CANCEL)
       return false;
 
+   gPrefs->Write(wxT("/CsPresets/TruncInitialAllowedSilentMs"), 
mTruncInitialAllowedSilentMs);
    gPrefs->Write(wxT("/CsPresets/TruncLongestAllowedSilentMs"), 
mTruncLongestAllowedSilentMs);
    gPrefs->Write(wxT("/CsPresets/TruncDbChoiceIndex"), mTruncDbChoiceIndex);
-   
+   gPrefs->Write(wxT("/CsPresets/SilenceCompressRatio"), 
(int)floor(10.0*mSilenceCompressRatio+0.5));
+
    return true;
 }
 
 bool EffectTruncSilence::TransferParameters( Shuttle & shuttle )
 {  
    shuttle.TransferEnum(wxT("Db"), mTruncDbChoiceIndex, Enums::NumDbChoices, 
Enums::GetDbChoices());
-   shuttle.TransferInt(wxT("Duration"), mTruncLongestAllowedSilentMs, 200);
+   shuttle.TransferInt(wxT("Minimum"), mTruncInitialAllowedSilentMs, 200);
+   shuttle.TransferInt(wxT("Duration"), mTruncLongestAllowedSilentMs, 1000);
+   shuttle.TransferDouble(wxT("Compress"), mSilenceCompressRatio, 4.0f);
    return true;
 }
 
@@ -100,6 +119,7 @@
    double t1 = mT1;
    int tndx; 
    int tcount = 0;
+   int fr;
 
    // Init using first track
    t = (WaveTrack *) iter.First();
@@ -129,19 +149,19 @@
       t = (WaveTrack*) iter.Next();
    }
 
+   // Just a sanity check, really it should be much higher
+   if(blockLen < 4*mBlendFrameCount)
+      blockLen = 4*mBlendFrameCount;
+
    // Transform the marker timepoints to samples
    t = (WaveTrack *) iter.First();
    sampleCount start = t->TimeToLongSamples(t0);
    sampleCount end = t->TimeToLongSamples(t1);
 
    // Bigger buffers reduce 'reset'
-   blockLen *= 8;
-
-   // Allocate buffers
-   float **buffer = new float*[tcount];
-   for (tndx = 0; tndx < tcount; tndx++) {
-      buffer[tndx] = new float[blockLen];
-   }
+   //blockLen *= 8;
+   // Stress-test the logic for cutting samples through block endpoints
+   //blockLen /= 8;
 
    // Set thresholds
    // We have a lower bound on the amount of silence we chop out at a time
@@ -149,16 +169,40 @@
    // if we use 100ms.
    const float minTruncMs = 1.0f;
    double truncDbSilenceThreshold = Enums::Db2Signal[mTruncDbChoiceIndex];
+   int truncInitialAllowedSilentSamples = 
+      int((wxMax( mTruncInitialAllowedSilentMs, minTruncMs) * rate) / 1000.0);
    int truncLongestAllowedSilentSamples = 
       int((wxMax( mTruncLongestAllowedSilentMs, minTruncMs) * rate) / 1000.0);
 
-   
+   // Don't allow either value to be less than the cross-fade length
+   if(truncInitialAllowedSilentSamples < mBlendFrameCount)
+      truncInitialAllowedSilentSamples = mBlendFrameCount;
+   if(truncLongestAllowedSilentSamples < mBlendFrameCount)
+      truncLongestAllowedSilentSamples = mBlendFrameCount;
 
-   // Figure out number of frames for ramping
-   int quarterSecondFrames = int((rate * QUARTER_SECOND_MS) / 1000.0);
-   int rampInFrames = (truncLongestAllowedSilentSamples / 4);
-   if (rampInFrames > quarterSecondFrames) {
-      rampInFrames = quarterSecondFrames;
+   // For sake of efficiency, don't let blockLen be less than double the 
longest silent samples
+   // up until a sane limit of 1Meg samples
+   while((blockLen > 0) && (blockLen < truncLongestAllowedSilentSamples*2) && 
(blockLen < 1048576)) {
+      blockLen *= 2;
+   }
+    // Don't allow either value to be more than half of the block length
+   if(truncLongestAllowedSilentSamples > blockLen/2)
+      truncLongestAllowedSilentSamples = blockLen/2;
+   if(truncInitialAllowedSilentSamples > truncLongestAllowedSilentSamples)
+      truncInitialAllowedSilentSamples = truncLongestAllowedSilentSamples;
+
+   // We use the 'longest' variable as additive to the 'initial' variable
+   truncLongestAllowedSilentSamples -= truncInitialAllowedSilentSamples;
+
+   // Perform the crossfade half-way through the minimum removed silence 
duration
+   int rampInFrames = (truncInitialAllowedSilentSamples + mBlendFrameCount) / 
2;
+   if(rampInFrames > truncInitialAllowedSilentSamples)
+      rampInFrames = truncInitialAllowedSilentSamples;
+
+   // Allocate buffers
+   float **buffer = new float*[tcount];
+   for (tndx = 0; tndx < tcount; tndx++) {
+      buffer[tndx] = new float[blockLen];
    }
 
    // Start processing
@@ -168,29 +212,35 @@
    sampleCount index = start;
    sampleCount outTrackOffset = start;
    bool cancelled = false;
+   // Reset
+   bool ignoringFrames = false;
+   bool ignoringFirst = true;  // Ignore the initial samples until we get 
above the noise floor
+   sampleCount consecutiveSilentFrames = 0;
+   sampleCount truncIndex = 0;
+   sampleCount i = 0;
+   sampleCount keep;
+
    while (index < end) {
 
       // Limit size of current block if we've reached the end
-      sampleCount limit = blockLen;
-      if ((index + blockLen) > end) {
-         limit = end - index; 
+      sampleCount count = blockLen-i;
+      if ((index + count) > end) {
+         count = end - index; 
       }
 
       // Fill the buffers
       tndx = 0;
       t = (WaveTrack *) iter.First();
       while (t) {
-         t->Get((samplePtr)buffer[tndx++], floatSample, index, blockLen);
+         t->Get((samplePtr)(buffer[tndx++]+i), floatSample, index, count);
          t = (WaveTrack *) iter.Next();
       }
 
-      // Reset
-      bool ignoringFrames = false;
-      sampleCount consecutiveSilentFrames = 0;
-      sampleCount truncIndex = 0;
+      // Shift over to account for samples remaining from prior block
+      sampleCount limit = count+i;
 
       // Look for silences in current block
-      for (sampleCount i = 0; i < limit; i++) {
+      for ( ; i < limit; i++) {
 
          // Is current frame in all tracks below threshold
          bool below = true;
@@ -207,31 +257,60 @@
 
             // Ignore this frame (equivalent to cutting it)
             // otherwise, keep sample to be part of allowed silence
-            if (consecutiveSilentFrames > truncLongestAllowedSilentSamples) {
+            if (consecutiveSilentFrames > truncInitialAllowedSilentSamples) {
                ignoringFrames = true;
                continue;
             }
          }
          else {
             if (ignoringFrames == true) {
-               sampleCount curOffset = i - rampInFrames;
-               truncIndex -= rampInFrames; // backup into ignored frames
+               // Scale the consectiveSilentFrames so we keep a silence 
duration
+               // which is proportional to the original silence up to the limit
+               keep = consecutiveSilentFrames - 
truncInitialAllowedSilentSamples;
+               keep /= mSilenceCompressRatio;
+
+               // The first samples always get truncated to the minimum amount
+               if(ignoringFirst == true)
+                  keep = 0;
+               if(keep > truncLongestAllowedSilentSamples)
+                  keep = truncLongestAllowedSilentSamples;
+               if(keep < 0)
+                  keep = 0;
+
+               //. Include the cross-fade samples in the count to make the 
loop logic easier
+               keep += rampInFrames;
+               truncIndex -= rampInFrames;
+
+               // back up for cross-fade
+               sampleCount curOffset = i - keep;
+
+               if(curOffset < 0) {
+                  // This should never happen, but just in case...
+                  keep += curOffset - rampInFrames;
+                  if(keep < mBlendFrameCount)
+                     keep = mBlendFrameCount;
+                  curOffset = 0;
+               }
+               if(truncIndex < 0) {
+                  // This should never happen, but just in case...
+                  truncIndex = 0;
+               }
 
                for (tndx = 0; tndx < tcount; tndx++) {
-                  sampleCount trunci = truncIndex;
-                  for (int fr = 0; fr < rampInFrames; fr++) {
-                     buffer[tndx][trunci++] = buffer[tndx][curOffset + fr];
+                  // Cross fade the cut point
+                  for (fr = 0; fr < mBlendFrameCount; fr++) {
+                     buffer[tndx][truncIndex+fr] = 
((mBlendFrameCount-fr)*buffer[tndx][truncIndex+fr] + fr*buffer[tndx][curOffset 
+ fr]) / mBlendFrameCount;
                   }
-                  if(((trunci - rampInFrames) - mBlendFrameCount) >= 0) {
-                     BlendFrames(buffer[tndx], mBlendFrameCount,
-                             ((trunci - rampInFrames) - mBlendFrameCount), 
-                             ((i - rampInFrames) - mBlendFrameCount));
+                  // Append the 'keep' samples, if any
+                  for ( ; fr < keep; fr++) {
+                     buffer[tndx][truncIndex+fr] = buffer[tndx][curOffset + 
fr];
                   }
                }
-               truncIndex += rampInFrames;
+               truncIndex += keep;
             }
             consecutiveSilentFrames = 0;
             ignoringFrames = false;
+            ignoringFirst = false;
          }
 
          // Can get here either because > dbThreshold
@@ -253,8 +332,32 @@
          }
       }
 
-      // Maintain output index
-      outTrackOffset += truncIndex;
+      // If currently in a silent section, retain samples for the next pass
+      if(ignoringFrames) {
+         keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples;
+         if(keep > (truncLongestAllowedSilentSamples+mBlendFrameCount))
+            keep = truncLongestAllowedSilentSamples+mBlendFrameCount;
+         for (tndx = 0; tndx < tcount; tndx++) {
+            for(fr = 0; fr < truncInitialAllowedSilentSamples; fr++) {
+               buffer[tndx][fr] = 
buffer[tndx][truncIndex-truncInitialAllowedSilentSamples+fr];
+            }
+            for(fr = 0; fr < keep; fr++) {
+               buffer[tndx][truncInitialAllowedSilentSamples+fr] = 
buffer[tndx][i-keep+fr];
+            }
+         }
+         // Update the output index, less what we are retaining for next time
+         outTrackOffset += truncIndex - truncInitialAllowedSilentSamples;
+         // Append the following buffer to the existing data
+         i = consecutiveSilentFrames = truncInitialAllowedSilentSamples + keep;
+         truncIndex = truncInitialAllowedSilentSamples;
+      } else {
+         // Maintain output index
+         outTrackOffset += truncIndex;
+         // Reset the buffer pointers to the beginning
+         i = 0;
+         truncIndex = 0;
+         consecutiveSilentFrames = 0;
+      }
 
       // Update progress and bail if user cancelled
       cancelled = TrackProgress(0, ((double)index / (double)end));
@@ -263,7 +366,7 @@
       }
 
       // Bump to next block
-      index += limit;
+      index += count;
    }
 
    // Remove stale data at end of output tracks.
@@ -308,12 +411,16 @@
 // TruncSilenceDialog
 //----------------------------------------------------------------------------
 
-#define ID_LONGEST_SILENCE_TEXT   7000
-#define ID_DB_SILENCE_THRESHOLD_CHOICE 7001
+#define ID_SHORTEST_SILENCE_TEXT   7000
+#define ID_LONGEST_SILENCE_TEXT   7001
+#define ID_COMPRESS_FACTOR   7002
+#define ID_DB_SILENCE_THRESHOLD_CHOICE 7003
 
 BEGIN_EVENT_TABLE(TruncSilenceDialog, EffectDialog)
     EVT_BUTTON(ID_EFFECT_PREVIEW, TruncSilenceDialog::OnPreview)
+    EVT_TEXT( ID_SHORTEST_SILENCE_TEXT, TruncSilenceDialog::OnDurationChange )
     EVT_TEXT( ID_LONGEST_SILENCE_TEXT, TruncSilenceDialog::OnDurationChange )
+    EVT_TEXT( ID_COMPRESS_FACTOR, TruncSilenceDialog::OnDurationChange )
 END_EVENT_TABLE()
 
 TruncSilenceDialog::TruncSilenceDialog(EffectTruncSilence * effect,
@@ -328,7 +435,7 @@
 {
    S.StartHorizontalLay(wxCENTER, false);
    {
-      S.AddTitle(_("by Lynn Allan"));
+      S.AddTitle(_("by Lynn Allan && Philip Van Baren"));
    }
    S.EndHorizontalLay();
 
@@ -342,10 +449,18 @@
    {
       wxArrayString choices(Enums::NumDbChoices, Enums::GetDbChoices());
 
+      S.Id( ID_SHORTEST_SILENCE_TEXT ).TieTextBox(_("Min silence duration:"),
+                   mEffect->mTruncInitialAllowedSilentMs,
+                   10);
+      S.AddUnits( _("milliseconds") );
       S.Id( ID_LONGEST_SILENCE_TEXT ).TieTextBox(_("Max silence duration:"),
                    mEffect->mTruncLongestAllowedSilentMs,
                    10);
       S.AddUnits( _("milliseconds") );
+      S.Id( ID_COMPRESS_FACTOR ).TieTextBox(_("Silence compression:"),
+                   mEffect->mSilenceCompressRatio,
+                   10);
+      S.AddUnits( _(":1") );
       //S.AddUnits(_("(9999999 or greater is off)"));
       S.TieChoice(_("Threshold for silence:"),
                   mEffect->mTruncDbChoiceIndex,
@@ -368,10 +483,12 @@
    if( !IsShown() )
       return;
    TransferDataFromWindow();
-   bool bOk =  mEffect->mTruncLongestAllowedSilentMs > 0.9f ;
+   bool bOk =  (mEffect->mTruncInitialAllowedSilentMs > 0.9f) 
+            && (mEffect->mTruncLongestAllowedSilentMs > 0.9f)
+            && (mEffect->mSilenceCompressRatio >= 1.0f);
    pWarning->SetLabel( bOk ? 
       wxT("") : 
-      _("   Duration must be at least 1 millisecond")
+   _("   Duration must be at least 1 millisecond\n   Compress ratio must be at 
least 1:1")
          );
    wxWindow *pWnd;
    pWnd = FindWindowById( wxID_OK, this );


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations 
Conference from O'Reilly Media. Velocity features a full day of 
expert-led, hands-on workshops and two days of sessions from industry 
leaders in dedicated Performance & Operations tracks. Use code vel09scf 
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to