⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 truncsilence.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
字号:
/**********************************************************************  Audacity: A Digital Audio Editor  TruncSilence.cpp  Lynn Allan (from DM's Normalize)  ToDo: Only works on complete mono track for now  ToDo: mBlendFrameCount only retrieved from prefs ... not using dialog        Only way to change (for windows) is thru registry        The values should be figured dynamically ... too many frames could be invalid**********************************************************************/#include <wx/wx.h>#include <math.h>#include "../Prefs.h"#include "../Project.h"#include "TruncSilence.h"EffectTruncSilence::EffectTruncSilence() : mUserPrompted(false){   Init();}bool EffectTruncSilence::Init(){   mTruncLongestAllowedSilentMs = gPrefs->Read(wxT("/CsPresets/TruncLongestAllowedSilentMs"), 200L);   if ((mTruncLongestAllowedSilentMs < 0) || (mTruncLongestAllowedSilentMs >= 9999999)) {  // corrupted Prefs?      mTruncLongestAllowedSilentMs = SKIP_EFFECT_MILLISECOND;      gPrefs->Write(wxT("/CsPresets/TruncLongestAllowedSilentMs"), (int)mTruncLongestAllowedSilentMs);   }   mTruncDbChoiceIndex = gPrefs->Read(wxT("/CsPresets/TruncDbChoiceIndex"), 4L);   if ((mTruncDbChoiceIndex < 0) || (mTruncDbChoiceIndex >= Enums::NumDbChoices)) {  // corrupted Prefs?      mTruncDbChoiceIndex = Enums::NumDbChoices - 1;  // Off-Skip      gPrefs->Write(wxT("/CsPresets/TruncDbChoiceIndex"), mTruncDbChoiceIndex);      mTruncLongestAllowedSilentMs = SKIP_EFFECT_MILLISECOND;      gPrefs->Write(wxT("/CsPresets/TruncLongestAllowedSilentMs"), (int)mTruncLongestAllowedSilentMs);   }   mBlendFrameCount = gPrefs->Read(wxT("/CsPresets/BlendFrameCount"), 100L);   if ((mBlendFrameCount < 0) || (mBlendFrameCount >= 5000)) {  // corrupted Prefs?      mBlendFrameCount = 100;      gPrefs->Write(wxT("/CsPresets/BlendFrameCount"), 100);   }   TrackListIterator iter(mWaveTracks);   mTrack = (WaveTrack *) iter.First();   if (mTrack != 0) {      int numTracks = GetNumWaveTracks();      if (numTracks != 1) {          wxMessageBox(_("Sorry. Truncate Silence only valid with mono track"));          return false;      }   }   return true;}bool EffectTruncSilence::CheckWhetherSkipEffect(){   bool rc = ((mTruncDbChoiceIndex >= (Enums::NumDbChoices - 1))          ||  (mTruncLongestAllowedSilentMs >= SKIP_EFFECT_MILLISECOND));   return rc;}void EffectTruncSilence::End(){}bool EffectTruncSilence::PromptUser(){   TruncSilenceDialog dlog(mParent, -1, _("Truncate Silence"));   dlog.mTruncLongestAllowedSilentMs = mTruncLongestAllowedSilentMs;   dlog.mTruncDbChoiceIndex = mTruncDbChoiceIndex;   dlog.TransferDataToWindow();   dlog.CentreOnParent();   dlog.ShowModal();   if (!dlog.GetReturnCode()) {      return false;   }   mUserPrompted = true;   mTruncLongestAllowedSilentMs = dlog.mTruncLongestAllowedSilentMs;   gPrefs->Write(wxT("/CsPresets/TruncLongestAllowedSilentMs"), (long)mTruncLongestAllowedSilentMs);   mTruncDbChoiceIndex = dlog.mTruncDbChoiceIndex;   gPrefs->Write(wxT("/CsPresets/TruncDbChoiceIndex"), mTruncDbChoiceIndex);      return true;}bool EffectTruncSilence::TransferParameters( Shuttle & shuttle ){     shuttle.TransferEnum(wxT("Db"),mTruncDbChoiceIndex,Enums::NumDbChoices,Enums::GetDbChoices());   shuttle.TransferLongLong(wxT("Duration"),mTruncLongestAllowedSilentMs,200);   return true;}bool EffectTruncSilence::Process(){   ProcessOne();   mUserPrompted = false;   return true;}#define QUARTER_SECOND_MS 250bool EffectTruncSilence::ProcessOne(){   float  curFrame;   float  fabsCurFrame;   int    consecutiveSilentFrames = 0;   int    samplesCleared = 0;   int    truncIndex = 0;   double curRate = mTrack->GetRate();   int    quarterSecondFrames = (int)((curRate * QUARTER_SECOND_MS)/ 1000.0);   int    truncLongestAllowedSilentSamples = int((mTruncLongestAllowedSilentMs * curRate) / 1000.0);   double truncDbSilenceThreshold = Enums::Db2Signal[mTruncDbChoiceIndex];   bool   ignoringFrames = false;   double selectionEnd = mT1;   double trackEnd = mTrack->GetEndTime();   longSampleCount selectionStartLongSampleCount = mTrack->TimeToLongSamples(mT0);   longSampleCount selectionEndLongSampleCount = mTrack->TimeToLongSamples(mT1);   sampleCount selectionStartSampleCount = selectionStartLongSampleCount;   sampleCount selectionEndSampleCount = selectionEndLongSampleCount;   sampleCount idealBlockLen = mTrack->GetMaxBlockSize() * 8;   // bigger buffer reduces 'reset'   sampleCount index = selectionStartSampleCount;   sampleCount indexAtLoopStart = index;   sampleCount outTrackOffset = selectionStartSampleCount;   float *buffer = new float[idealBlockLen];   bool rc;   int rampInFrames = (truncLongestAllowedSilentSamples / 4);   if (rampInFrames > quarterSecondFrames) {      rampInFrames = quarterSecondFrames;   }   while (index < selectionEndSampleCount) {      rc = mTrack->Get((samplePtr)buffer, floatSample, index, idealBlockLen);      truncIndex = 0;      indexAtLoopStart = index;      ignoringFrames = false;       // may be unneccesary to reset, but safer      consecutiveSilentFrames = 0;  // may be unneccesary to reset, but safer      sampleCount limit = idealBlockLen;      if ((index + idealBlockLen) > selectionEndSampleCount) {         limit = selectionEndSampleCount - index;       }      for (sampleCount i = 0; i < limit; ++i) {         index++;         curFrame = buffer[i];         fabsCurFrame = (float)fabs(curFrame);         if (fabsCurFrame < truncDbSilenceThreshold) {            consecutiveSilentFrames++;            if (consecutiveSilentFrames > truncLongestAllowedSilentSamples) {               ignoringFrames = true;               continue;  // ignore this frame (equivalent to cutting it)            }             // otherwise, keep sample to be part of allowed silence         }         else {            if (ignoringFrames == true) {               sampleCount curOffset = i - rampInFrames;               truncIndex -= rampInFrames; // backup into ignored frames               wxASSERT((truncIndex < idealBlockLen) && (curOffset > 0) && ((curOffset + rampInFrames) < idealBlockLen));               for (int fr = 0; fr < rampInFrames; ++fr) {                  buffer[truncIndex] = buffer[curOffset + fr];                  truncIndex++;               }               BlendFrames(buffer, mBlendFrameCount,                          ((truncIndex - rampInFrames) - mBlendFrameCount),                           ((i - rampInFrames) - mBlendFrameCount));            }            consecutiveSilentFrames = 0;            ignoringFrames = false;         }         wxASSERT(truncIndex < idealBlockLen);         buffer[truncIndex] = curFrame;  // Can get here either because > dbThreshold         truncIndex++;                   // or silence duration isn't longer than allowed      }      samplesCleared += (limit - truncIndex);      rc = mTrack->Set((samplePtr)buffer, floatSample, outTrackOffset, truncIndex);      outTrackOffset += truncIndex;      bool cancellingFlag = TrackProgress(0, ((double)index / (double)selectionEndSampleCount));      if (cancellingFlag == true) {         delete [] buffer;         return false;      }   }   double lenToCut = (samplesCleared / curRate);   double middle =  selectionEnd - lenToCut;   mTrack->Cut(middle, selectionEnd, (Track**)&mTrack);   mT0 = 0.0;   mT1 = trackEnd - lenToCut;   if (mUserPrompted == true) {      AudacityProject *proj = GetActiveProject();      proj->OnZoomFit();   }   gPrefs->Write(wxT("/Validate/TruncSamplesCleared"), samplesCleared);   delete [] buffer;   return true;}void EffectTruncSilence::BlendFrames(float* buffer, int blendFrameCount, int leftIndex, int rightIndex){   float* bufOutput = &buffer[leftIndex];   float* bufBefore = &buffer[leftIndex];   float* bufAfter  = &buffer[rightIndex];   double beforeFactor = 1.0;   double afterFactor  = 0.0;   double adjFactor = 1.0 / (double)blendFrameCount;   for (int j = 0; j < blendFrameCount; ++j) {	  bufOutput[j] = (float)((bufBefore[j] * beforeFactor) + (bufAfter[j] * afterFactor));	  beforeFactor -= adjFactor;	  afterFactor  += adjFactor;   }}//----------------------------------------------------------------------------// TruncSilenceDialog//----------------------------------------------------------------------------#define ID_LONGEST_SILENCE_TEXT   7000#define ID_DB_SILENCE_THRESHOLD_CHOICE 7001BEGIN_EVENT_TABLE(TruncSilenceDialog,wxDialog)   EVT_BUTTON( wxID_OK, TruncSilenceDialog::OnOk )   EVT_BUTTON( wxID_CANCEL, TruncSilenceDialog::OnCancel )END_EVENT_TABLE()TruncSilenceDialog::TruncSilenceDialog(wxWindow *parent, wxWindowID id, const wxString &title) :   wxDialog( parent, id, title ){   wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);   wxStaticText *statText = new wxStaticText(this, -1,                           _("Truncate Silence by Lynn Allan"));   mainSizer->Add(statText, 0, wxALIGN_CENTRE | wxALL, 5);   wxBoxSizer *hSizer = new wxBoxSizer(wxHORIZONTAL);   statText = new wxStaticText(this, -1, _("Max Silent Duration (milliseconds): \n(99999 or greater is off)"));   hSizer->Add(statText, 0, wxALIGN_CENTRE | wxALL, 5);      wxString truncLongestAllowedSilentMsStr;   truncLongestAllowedSilentMsStr.Printf(wxT("%d"), mTruncLongestAllowedSilentMs);   mTruncLongestAllowedSilentMsText = new wxTextCtrl(this, ID_LONGEST_SILENCE_TEXT,                      truncLongestAllowedSilentMsStr, wxDefaultPosition,                     wxSize(60, -1), 0,                     wxTextValidator(wxFILTER_NUMERIC));   hSizer->Add(mTruncLongestAllowedSilentMsText, 0, wxALL, 5);   mainSizer->Add(hSizer, 0, wxALIGN_CENTRE | wxALL, 5);   hSizer = new wxBoxSizer(wxHORIZONTAL);   statText = new wxStaticText(this, -1, _("Theshold for silence: "));   hSizer->Add(statText, 0, wxALIGN_CENTRE | wxALL, 5);   mTruncDbSilenceThresholdChoice = new wxChoice(this, ID_DB_SILENCE_THRESHOLD_CHOICE,      wxDefaultPosition, wxSize(64, -1), Enums::NumDbChoices,Enums::GetDbChoices());   hSizer->Add(mTruncDbSilenceThresholdChoice, 0, wxALIGN_CENTER | wxALL, 4);   mainSizer->Add(hSizer, 0, wxALIGN_CENTRE | wxALL, 5);   hSizer = new wxBoxSizer(wxHORIZONTAL);   wxButton *cancel = new wxButton(this, wxID_CANCEL, _("Cancel"));   hSizer->Add(cancel, 0, wxALIGN_CENTRE|wxALL, 5);   wxButton *ok = new wxButton(this, wxID_OK, _("OK"));   ok->SetDefault();   ok->SetFocus();   hSizer->Add(ok, 0, wxALIGN_CENTRE|wxALL, 5);   mainSizer->Add(hSizer, 0, wxALIGN_CENTRE|wxALIGN_CENTER_VERTICAL|wxALL, 5);   SetAutoLayout(true);   SetSizer(mainSizer);   mainSizer->Fit(this);   mainSizer->SetSizeHints(this);}bool TruncSilenceDialog::TransferDataToWindow(){   mTruncLongestAllowedSilentMsText->SetValue(wxString::Format(wxT("%d"), mTruncLongestAllowedSilentMs));   mTruncDbSilenceThresholdChoice->SetSelection(mTruncDbChoiceIndex);   return true;}bool TruncSilenceDialog::TransferDataFromWindow(){   long ms;   mTruncLongestAllowedSilentMsText->GetValue().ToLong(&ms);   mTruncLongestAllowedSilentMs = ms;   mTruncDbChoiceIndex = mTruncDbSilenceThresholdChoice->GetSelection();   return true;}void TruncSilenceDialog::OnOk(wxCommandEvent &event){   TransferDataFromWindow();   EndModal(true);}void TruncSilenceDialog::OnCancel(wxCommandEvent &event){   EndModal(false);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -