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

📄 changespeed.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************  Audacity: A Digital Audio Editor  ChangeSpeed.cpp  Vaughan Johnson, Dominic Mazzoni    Change Speed effect, that affects both pitch & tempo.**********************************************************************/#include "ChangeSpeed.h"#include "../Audacity.h" // for USE_LIBSAMPLERATE#include "../Envelope.h"#include "../Prefs.h"#include <math.h>#include <wx/button.h>#include <wx/msgdlg.h> // for wxMessageBox#include <wx/sizer.h>#include <wx/stattext.h>#include <wx/valtext.h>//// EffectChangeSpeed//EffectChangeSpeed::EffectChangeSpeed(){	// control values	m_PercentChange = 0.0;	m_FromVinyl = 0; 	m_ToVinyl = 0; }wxString EffectChangeSpeed::GetEffectDescription() {    // Note: This is useful only after change amount has been set.    return wxString::Format(_("Applied effect: %s %.1f%%"),                            this->GetEffectName().c_str(), 									m_PercentChange); } bool EffectChangeSpeed::PromptUser(){   ChangeSpeedDialog dlog(this, mParent, -1, _("Change Speed"));   dlog.m_PercentChange = m_PercentChange;   dlog.m_FromVinyl = m_FromVinyl;   dlog.m_ToVinyl = m_ToVinyl;	// Don't need to call TransferDataToWindow, although other 	//	Audacity dialogs (from which I derived this one) do it, because 	//	ShowModal calls stuff that eventually calls wxWindowBase::OnInitDialog, 	//	which calls dlog.TransferDataToWindow();   dlog.CentreOnParent();   dlog.ShowModal();   if (!dlog.GetReturnCode())      return false;   m_PercentChange = dlog.m_PercentChange;   m_FromVinyl = dlog.m_FromVinyl;   m_ToVinyl = dlog.m_ToVinyl;   return true;}bool EffectChangeSpeed::TransferParameters( Shuttle & shuttle ){     shuttle.TransferDouble(wxT("Percentage"),m_PercentChange,0.0);   return true;}bool EffectChangeSpeed::Process(){	// Similar to EffectSoundTouch::Process()   //Iterate over each track   TrackListIterator iter(mWaveTracks);   WaveTrack *track = (WaveTrack *) iter.First();   mCurTrackNum = 0;	m_maxNewLength = 0.0;	double curT0;	double curT1;   while (track) {      //Get start and end times from track      double trackStart = track->GetStartTime();      double trackEnd = track->GetEndTime();      //Set the current bounds to whichever left marker is      //greater and whichever right marker is less:      curT0 = mT0 < trackStart? trackStart: mT0;      curT1 = mT1 > trackEnd? trackEnd: mT1;      // Process only if the right marker is to the right of the left marker      if (curT1 > curT0) {         //Transform the marker timepoints to samples         longSampleCount start = track->TimeToLongSamples(curT0);         longSampleCount end = track->TimeToLongSamples(curT1);         //ProcessOne() (implemented below) processes a single track         if (!ProcessOne(track, start, end))            return false;      }            //Iterate to the next track      track = (WaveTrack *) iter.Next();      mCurTrackNum++;   }	mT1 = mT0 + m_maxNewLength; // Update selection.   return true;}// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,// and calls libsamplerate code on these blocks.bool EffectChangeSpeed::ProcessOne(WaveTrack * track,												longSampleCount start, longSampleCount end){	if (track == NULL)		return false;	// initialization, per examples of Mixer::Mixer and   // EffectSoundTouch::ProcessOne   WaveTrack * outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat());   //Get the length of the selection (as double). len is   //used simple to calculate a progress meter, so it is easier   //to make it a double now than it is to do it later    double len = (double)(end - start);   // Initiate processing buffers, most likely shorter than 	//	the length of the selection being processed.	sampleCount inBufferSize = track->GetMaxBlockSize();   float * inBuffer = new float[inBufferSize];   double factor = 100.0 / (100.0 + m_PercentChange);	sampleCount outBufferSize =       (sampleCount)((factor * inBufferSize) + 10);   float * outBuffer = new float[outBufferSize]; 	// Set up the resampling stuff for this track.   Resample resample(true, factor, factor);   //Go through the track one buffer at a time. samplePos counts which   //sample the current buffer starts at.	bool bLoopSuccess = true;   sampleCount blockSize;  	longSampleCount samplePos = start;   while (samplePos < end) {      //Get a blockSize of samples (smaller than the size of the buffer)      blockSize = track->GetBestBlockSize(samplePos);      //Adjust the block size if it is the final block in the track      if (samplePos + blockSize > end)         blockSize = end - samplePos;      //Get the samples from the track and put them in the buffer      track->Get((samplePtr) inBuffer, floatSample, samplePos, blockSize);      int inUsed;      int outgen = resample.Process(factor,                                    inBuffer,                                    blockSize,                                    ((samplePos + blockSize) >= end),                                    &inUsed,                                    outBuffer,                                    outBufferSize);      if (outgen < 0) {			bLoopSuccess = false;			break;		}      if (outgen > 0)         outputTrack->Append((samplePtr)outBuffer, floatSample,                              outgen);      // Increment samplePos      samplePos += inUsed;      // Update the Progress meter      if (TrackProgress(mCurTrackNum, (samplePos - start) / len)) {			bLoopSuccess = false;			break;		}   }	// Flush the output WaveTrack (since it's buffered, too)	outputTrack->Flush();   // Clean up the buffers   delete [] inBuffer;   delete [] outBuffer;   // Take the output track and insert it in place of the original   // sample data	if (bLoopSuccess) {		track->Clear(mT0, mT1);		track->Paste(mT0, outputTrack);	}	double newLength = outputTrack->GetEndTime(); 	if (newLength > m_maxNewLength) 		m_maxNewLength = newLength;    // Delete the outputTrack now that its data is inserted in place   delete outputTrack;   return bLoopSuccess;}//----------------------------------------------------------------------------// ChangeSpeedDialog//----------------------------------------------------------------------------// -99 for PERCENTCHANGE_MIN because -100% is nonsensical.#define PERCENTCHANGE_MIN -99#define PERCENTCHANGE_MAX 100 // warped above zero to actually go up to 400%#define PERCENTCHANGE_SLIDER_WARP 1.30105 // warp power takes max from 100 to 400.// the standard vinyl RPM choices// If the percent change is not one of these ratios, the choice control gets "n/a".#define CHOICE_33ANDATHIRD 0#define CHOICE_45 1#define CHOICE_78 2#define CHOICE_NA 3 enum {   ID_TEXT_PERCENTCHANGE = 10001,   ID_SLIDER_PERCENTCHANGE,   ID_CHOICE_FROMVINYL,   ID_CHOICE_TOVINYL,	ID_BUTTON_PREVIEW};// event table for ChangeSpeedDialogBEGIN_EVENT_TABLE(ChangeSpeedDialog, wxDialog)    EVT_BUTTON(wxID_OK, ChangeSpeedDialog::OnOk)    EVT_BUTTON(wxID_CANCEL, ChangeSpeedDialog::OnCancel)    EVT_TEXT(ID_TEXT_PERCENTCHANGE, ChangeSpeedDialog::OnText_PercentChange)    EVT_SLIDER(ID_SLIDER_PERCENTCHANGE, ChangeSpeedDialog::OnSlider_PercentChange)    EVT_CHOICE(ID_CHOICE_FROMVINYL, ChangeSpeedDialog::OnChoice_FromVinyl)    EVT_CHOICE(ID_CHOICE_TOVINYL, ChangeSpeedDialog::OnChoice_ToVinyl)    EVT_BUTTON(ID_BUTTON_PREVIEW, ChangeSpeedDialog::OnPreview)END_EVENT_TABLE()ChangeSpeedDialog::ChangeSpeedDialog(EffectChangeSpeed * effect,													wxWindow * parent, wxWindowID id,													const wxString & title, 													const wxPoint & position, 													const wxSize & size, 													long style): wxDialog(parent, id, title, position, size, style){   m_bLoopDetect = false;	m_pEffect = effect;	// NULL out these control members because there are some cases where the 	// event table handlers get called during this method, and those handlers that 	// can cause trouble check for NULL.   m_pTextCtrl_PercentChange = NULL;   m_pSlider_PercentChange = NULL;   m_pChoice_FromVinyl = NULL;   m_pChoice_ToVinyl = NULL;		// effect parameters	m_PercentChange = 0.0;	m_FromVinyl = 0; 	m_ToVinyl = 0; 		// CREATE THE CONTROLS PROGRAMMATICALLY.	wxStaticText * pStaticText;   wxBoxSizer * pBoxSizer_Dialog = new wxBoxSizer(wxVERTICAL);	// heading   pStaticText = new wxStaticText(this, -1, 												_("Change Speed, affecting both Tempo and Pitch"),												wxDefaultPosition, wxDefaultSize, 0);   pBoxSizer_Dialog->Add(pStaticText, 0, wxALIGN_CENTER | wxALL, 8);   pStaticText = new wxStaticText(this, -1, 												_("by Vaughan Johnson && Dominic Mazzoni"),												wxDefaultPosition, wxDefaultSize, 0);   pBoxSizer_Dialog->Add(pStaticText, 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 8);   pStaticText = new wxStaticText(this, -1, 												_("using SampleRate, by Erik de Castro Lopo"),												wxDefaultPosition, wxDefaultSize, 0);   pBoxSizer_Dialog->Add(pStaticText, 0, wxALIGN_CENTER | wxBOTTOM | wxLEFT | wxRIGHT, 8);	// percent change controls	// Group percent controls with spacers, 	// rather than static box, so they don't look isolated.   pBoxSizer_Dialog->Add(0, 8, 0); // spacer   wxBoxSizer * pBoxSizer_PercentChange = new wxBoxSizer(wxHORIZONTAL);

⌨️ 快捷键说明

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