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

📄 clickremoval.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
字号:
/**********************************************************************  Audacity: A Digital Audio Editor  ClickRemoval.cpp  Craig DeForest  Clicks are identified as small regions of high amplitude compared  to the surrounding chunk of sound.  Anything sufficiently tall compared  to a large (2048 sample) window around it, and sufficiently narrow,  is considered to be a click.  The structure was largely stolen from Domonic Mazzoni's NoiseRemoval  module, and reworked for the new effect.  This file is intended to become part of Audacity.  You may modify  and/or distribute it under the same terms as Audacity itself.**********************************************************************/#include "../Audacity.h"#include <math.h>#if defined(__WXMSW__) && !defined(__CYGWIN__)#include <float.h>#define finite(x) _finite(x)#endif#ifdef __MACOSX__#include <math.h>#endif#ifdef __MACOS9__#include <fp.h>#define finite(x) isfinite(x)#endif#include <wx/msgdlg.h>#include <wx/textdlg.h>#include <wx/brush.h>#include <wx/image.h>#include <wx/dcmemory.h>#include <wx/statbox.h>#include <wx/intl.h>#include "ClickRemoval.h"#include "../Envelope.h"// #include "../FFT.h"#include "../WaveTrack.h"#include "../Prefs.h"EffectClickRemoval::EffectClickRemoval(){   windowSize = 8192;//   mThresholdLevel = 200;//   mClickWidth = 20;   sep=2049;   Init();}EffectClickRemoval::~EffectClickRemoval(){}#define MAX_THRESHOLD 900#define MAX_CLICK_WIDTH 40bool EffectClickRemoval::Init(){   mThresholdLevel = gPrefs->Read(wxT("/CsPresets/ClickThresholdLevel"), 200);   if ((mThresholdLevel < 0) || (mThresholdLevel > MAX_THRESHOLD)) {  // corrupted Prefs?      mThresholdLevel = 0;  //Off-skip      gPrefs->Write(wxT("/CsPresets/ClickThresholdLevel"), mThresholdLevel);   }   mClickWidth = gPrefs->Read(wxT("/CsPresets/ClickWidth"), 20);   if ((mClickWidth < 0) || (mClickWidth > MAX_CLICK_WIDTH)) {  // corrupted Prefs?      mClickWidth = 0;  //Off-skip      gPrefs->Write(wxT("/CsPresets/ClickWidth"), mClickWidth);   }   return true;}bool EffectClickRemoval::CheckWhetherSkipEffect(){   bool rc = ((mClickWidth == 0) || (mThresholdLevel == 0));   return rc;}bool EffectClickRemoval::PromptUser(){   ClickRemovalDialog dlog(this, mParent, -1, _("Click and Pop Removal"));   dlog.m_pSlider_threshold->SetValue(mThresholdLevel);   dlog.m_pSlider_width->SetValue(mClickWidth);   //   dlog.m_pSlider_sep->SetValue(sep);   dlog.m_pButton_RemoveClicks->SetDefault();   dlog.m_pButton_RemoveClicks->SetFocus();   dlog.CentreOnParent();   dlog.ShowModal();   if (dlog.GetReturnCode() == 0)      return false;   mThresholdLevel = dlog.m_pSlider_threshold->GetValue();   mClickWidth = dlog.m_pSlider_width->GetValue();   //   sep = dlog.m_pSlider_sep->GetValue();   gPrefs->Write(wxT("/CsPresets/ClickThresholdLevel"), mThresholdLevel);   gPrefs->Write(wxT("/CsPresets/ClickWidth"), mClickWidth);   return true;}bool EffectClickRemoval::TransferParameters( Shuttle & shuttle ){     shuttle.TransferInt(wxT("Threshold"),mThresholdLevel,0);   shuttle.TransferInt(wxT("Width"),mClickWidth,0);   return true;}bool EffectClickRemoval::Process(){   TrackListIterator iter(mWaveTracks);   WaveTrack *track = (WaveTrack *) iter.First();   int count = 0;   while (track) {      double trackStart = track->GetStartTime();      double trackEnd = track->GetEndTime();      double t0 = mT0 < trackStart? trackStart: mT0;      double t1 = mT1 > trackEnd? trackEnd: mT1;      if (t1 > t0) {         longSampleCount start = track->TimeToLongSamples(t0);         longSampleCount end = track->TimeToLongSamples(t1);         sampleCount len = (sampleCount)(end - start);         if (!ProcessOne(count, track, start, len))            return false;      }      track = (WaveTrack *) iter.Next();      count++;   }   return true;}bool EffectClickRemoval::ProcessOne(int count, WaveTrack * track,                                    longSampleCount start, sampleCount len){   bool rc = true;   sampleCount s = 0;   sampleCount idealBlockLen = track->GetMaxBlockSize() * 4;   if (idealBlockLen % windowSize != 0)      idealBlockLen += (windowSize - (idealBlockLen % windowSize));   float *buffer = new float[idealBlockLen];   float *datawindow = new float[windowSize];   int i;   while((s < len)&&((len-s)>(windowSize/2))) {      sampleCount block = idealBlockLen;      if (s + block > len)         block = len - s;      track->Get((samplePtr) buffer, floatSample, start + s, block);      for(i=0; i<(block-windowSize/2); i+=windowSize/2) {         int wcopy = windowSize;         if (i + wcopy > block)            wcopy = block - i;         int j;         for(j=0; j<wcopy; j++)            datawindow[j] = buffer[i+j];         for(j=wcopy; j<windowSize; j++)            datawindow[j] = 0;   RemoveClicks(windowSize, datawindow);   for(j=0; j<wcopy; j++)     buffer[i+j] = datawindow[j];      }      track->Set((samplePtr) buffer, floatSample, start + s, block);      s += block;      if (TrackProgress(count, s / (double) len)) {         rc = false;         break;      }   }   delete[] buffer;   delete[] datawindow;   return true;}void EffectClickRemoval::RemoveClicks(sampleCount len, float *buffer){   int i;   int j;   int left = 0;   float msw;   int ww;   int s2 = sep/2;   float *ms_seq = new float[len];   float *b2 = new float[len];   for( i=0; i<len; i++)      b2[i] = buffer[i]*buffer[i];   /* Shortcut for rms - multiple passes through b2, accumulating    * as we go.    */   for(i=0;i<len;i++)      ms_seq[i]=b2[i];   for(i=1; i < sep; i *= 2) {      for(j=0;j<len-i; j++)         ms_seq[j] += ms_seq[j+i];      }   /* Cheat by truncating sep to next-lower power of two... */      sep = i;      for( i=0; i<len-sep; i++ ) {         ms_seq[i] /= sep;      }      /* ww runs from about 4 to mClickWidth.  wrc is the reciprocal;       * chosen so that integer roundoff doesn't clobber us.       */      int wrc;      for(wrc=mClickWidth/4; wrc>=1; wrc /= 2) {         ww = mClickWidth/wrc;         for( i=0; i<len-sep; i++ ){            msw = 0;            for( j=0; j<ww; j++) {               msw += b2[i+s2+j];            }            msw /= ww;            if(msw >= mThresholdLevel * ms_seq[i]/10) {               if( left == 0 ) {                  left = i+s2;               }            } else {               if(left != 0 && i-left+s2 <= ww*2) {                  float lv = buffer[left];                  float rv = buffer[i+ww+s2];                  for(j=left; j<i+ww+s2; j++) {                     buffer[j]= (rv*(j-left) + lv*(i+ww+s2-j))/(float)(i+ww+s2-left);                     b2[j] = buffer[j]*buffer[j];                  }                  left=0;               } else if(left != 0) {               left = 0;            }         }      }   }   delete[] ms_seq;   delete[] b2;}// WDR: class implementations//----------------------------------------------------------------------------// ClickRemovalDialog//----------------------------------------------------------------------------// WDR: event table for ClickRemovalDialog//enum {//  ID_BUTTON_PREVIEW=10002//};BEGIN_EVENT_TABLE(ClickRemovalDialog,wxDialog)  EVT_BUTTON(wxID_OK, ClickRemovalDialog::OnRemoveClicks)  EVT_BUTTON(wxID_CANCEL, ClickRemovalDialog::OnCancel)//  EVT_BUTTON(ID_BUTTON_PREVIEW, ClickRemovalDialog::OnPreview)END_EVENT_TABLE()ClickRemovalDialog::ClickRemovalDialog(EffectClickRemoval * effect,                          wxWindow *parent, wxWindowID id,                          const wxString &title,                          const wxPoint &position,                          const wxSize& size,                          long style ) :   wxDialog( parent, id, title, position, size, style ){   m_pEffect = effect;   // NULL out the control members until the controls are created.   m_pButton_GetProfile = NULL;   m_pSlider_threshold = NULL;//   m_pButton_Preview = NULL;   m_pButton_RemoveClicks = NULL;   this->MakeClickRemovalDialog(true);}// WDR: handler implementations for NoiseRemovalDialog/*void ClickRemovalDialog::OnPreview(wxCommandEvent &event){  // Save & restore parameters around Preview, because we didn't do OK.  int oldLevel = m_pEffect->mThresholdLevel;  int oldWidth = m_pEffect->mClickWidth;  int oldSep = m_pEffect->sep;  m_pEffect->mThresholdLevel = m_pSlider->GetValue();  m_pEffect->mClickWidth = m_pSlider_width->GetValue();  //  m_pEffect->sep = m_pSlider_sep->GetValue();  m_pEffect->Preview();  m_pEffect->sep   = oldSep;  m_pEffect->mClickWidth = oldWidth;  m_pEffect->mThresholdLevel = oldLevel;}*/void ClickRemovalDialog::OnRemoveClicks( wxCommandEvent &event ){   EndModal(2);}void ClickRemovalDialog::OnCancel(wxCommandEvent &event){   EndModal(0);}wxSizer *ClickRemovalDialog::MakeClickRemovalDialog(bool call_fit /* = true */,                                   bool set_sizer /* = true */){   wxBoxSizer *mainSizer = new wxBoxSizer( wxVERTICAL );   wxStaticBoxSizer *group;   wxControl *item;   item = new wxStaticText(this, -1,                   _("Click and Pop Removal by Craig DeForest"), wxDefaultPosition,                   wxDefaultSize, wxALIGN_CENTRE );   mainSizer->Add(item, 0, wxALIGN_CENTRE|wxALL, 5);   group = new wxStaticBoxSizer(new wxStaticBox(this, -1,                                                _("Settings")), wxVERTICAL);   item = new wxStaticText(this, -1,                           _("\nSelect threshold (lower is more sensitive)"),                           wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );   group->Add(item, 0, wxALIGN_CENTRE|wxALL, 5 );   m_pSlider_threshold = new wxSlider(this, -1, 8, 0, MAX_THRESHOLD,  wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);   group->Add(m_pSlider_threshold, 1, wxEXPAND|wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxTOP, 5 );   wxBoxSizer *hSizer = new wxBoxSizer(wxHORIZONTAL);   item = new wxStaticText(this, -1, _("Off"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   hSizer->Add(10, 10, 1, wxALIGN_CENTRE | wxLEFT | wxRIGHT | wxBOTTOM, 5);   item = new wxStaticText(this, -1, _("Medium"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   hSizer->Add(10, 10, 1, wxALIGN_CENTRE | wxLEFT | wxRIGHT | wxBOTTOM, 5);   item = new wxStaticText(this, -1, _("Max"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   group->Add(hSizer, 1, wxEXPAND|wxALIGN_CENTRE|wxALL, 5 );   hSizer = new wxBoxSizer(wxHORIZONTAL);   item = new wxStaticText(this,-1,         _("\n\nMax spike width (higher is more sensitive)"),         wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);   group->Add(item,0,wxALIGN_CENTER|wxALL,5);   m_pSlider_width = new wxSlider(this, -1, 8, 0, MAX_CLICK_WIDTH, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);   group->Add(m_pSlider_width, 1, wxEXPAND|wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxTOP, 5 );   //   item = new wxStaticText(this,-1,   //        _("\nNeighborhood"),   //        wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);   //   group->Add(item,0,wxALIGN_CENTER|wxALL,5);   //   m_pSlider_sep = new wxSlider(this,-1,8,1,4100,wxDefaultPosition,wxDefaultSize,wxSL_HORIZONTAL);   //   group->Add(m_pSlider_sep, 1, wxEXPAND|wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxTOP, 5 );   hSizer = new wxBoxSizer(wxHORIZONTAL);   item = new wxStaticText(this, -1, _("Off"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   hSizer->Add(10, 10, 1, wxALIGN_CENTRE | wxLEFT | wxRIGHT | wxBOTTOM, 5);   item = new wxStaticText(this, -1, _("Medium"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   hSizer->Add(10, 10, 1, wxALIGN_CENTRE | wxLEFT | wxRIGHT | wxBOTTOM, 5);   item = new wxStaticText(this, -1, _("Max"));   hSizer->Add(item, 0, wxALIGN_CENTRE|wxLEFT | wxRIGHT | wxBOTTOM, 5 );   group->Add(hSizer, 1, wxEXPAND|wxALIGN_CENTRE|wxALL, 5 );   hSizer = new wxBoxSizer(wxHORIZONTAL);/*   m_pButton_Preview = new wxButton(this, ID_BUTTON_PREVIEW, m_pEffect->GetPreviewName());   hSizer->Add(m_pButton_Preview, 0, wxALIGN_LEFT | wxALL, 5);   hSizer->Add(25, 5); // horizontal spacer*/   m_pButton_RemoveClicks = new wxButton(this, wxID_OK, _("Remove clicks"), wxDefaultPosition, wxDefaultSize, 0 );   hSizer->Add(m_pButton_RemoveClicks, 0, wxALIGN_RIGHT | wxALL, 5 );   group->Add(hSizer, 0, wxALIGN_CENTER | wxALL, 5 );   mainSizer->Add( group, 0, wxALIGN_CENTRE|wxALL, 5 );   item = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );   mainSizer->Add(item, 0, wxALIGN_CENTRE|wxALL, 5 );   if (set_sizer) {      this->SetAutoLayout( TRUE );      this->SetSizer( mainSizer );      if (call_fit) {         mainSizer->Fit( this );         mainSizer->SetSizeHints( this );      }   }   return mainSizer;}

⌨️ 快捷键说明

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