📄 repeat.cpp
字号:
/********************************************************************** Audacity: A Digital Audio Editor Repeat.cpp Dominic Mazzoni Vaughan Johnson**********************************************************************/#include "Repeat.h"#include "../Audacity.h"#include "../WaveTrack.h"#include <wx/button.h>#include <wx/defs.h>#include <wx/intl.h>#include <wx/msgdlg.h>#include <wx/sizer.h>#include <wx/stattext.h>#include <wx/textctrl.h>#include <wx/validate.h>#include <wx/valtext.h>#include <math.h>EffectRepeat::EffectRepeat(){ repeatCount = 10;}wxString EffectRepeat::GetEffectDescription() { // Note: This is useful only after values have been set. return wxString::Format(_("Repeated %d times"), repeatCount);} bool EffectRepeat::PromptUser(){ // // Figure out the maximum number of times the selection // could be repeated without overflowing any track // int maxCount = -1; TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); while (track) { sampleCount trackLen = (sampleCount)((track->GetEndTime() - track->GetStartTime()) * track->GetRate()); sampleCount selectionLen = (sampleCount)((mT1 - mT0) * track->GetRate()); int availSamples = 2147483647 - trackLen; int count = availSamples / selectionLen; if (maxCount == -1 || count < maxCount) maxCount = count; track = (WaveTrack *) iter.Next(); } if (maxCount <= 1) { wxMessageBox(_("Tracks are too long to repeat the selection."), _("Repeat"), wxOK | wxCENTRE, mParent); return false; } RepeatDialog dlog(mParent, -1, _("Repeat")); dlog.repeatCount = repeatCount; dlog.selectionTimeSecs = mT1 - mT0; dlog.maxCount = maxCount; dlog.TransferDataToWindow(); dlog.CentreOnParent(); dlog.ShowModal(); if (!dlog.GetReturnCode()) return false; repeatCount = dlog.repeatCount; if (repeatCount > maxCount) repeatCount = maxCount; if (repeatCount < 1) repeatCount = 1; return true;}bool EffectRepeat::TransferParameters( Shuttle & shuttle ){ shuttle.TransferInt(wxT("Count"),repeatCount,1); return true;}bool EffectRepeat::Process(){ TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); int count = 0; double maxDestLen = 0.0; // used to change selection to original plus generated double newDestLen = 0.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) continue; longSampleCount start = track->TimeToLongSamples(t0); longSampleCount end = track->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (len <= 0) continue; // // Create a track that contains 1 or more copies of the // selection, cleverly arranged so that every BlockFile // is within the minimum and maxmimum lengths of a normal // BlockFile. That allows us to repeat the same sequence // of identical BlockFiles, saving lots of disk space. // sampleFormat format = track->GetSampleFormat(); WaveTrack *unitTrack = mFactory->NewWaveTrack(format); WaveTrack *dest = mFactory->NewWaveTrack(format); sampleCount maxBlockSize = unitTrack->GetMaxBlockSize(); sampleCount minBlockSize = maxBlockSize / 2; samplePtr buffer = NewSamples(maxBlockSize, format); int numCopies = 1; int chunkSize = len; int j; while (chunkSize * numCopies < minBlockSize) numCopies++; if (chunkSize > maxBlockSize) { j=2; while(chunkSize/j >= maxBlockSize) j++; chunkSize = (chunkSize + (j-1)) / j; } sampleCount totalSamples = 0; while(totalSamples < len * numCopies) { sampleCount blockLen = chunkSize; sampleCount blockStart = (totalSamples % len); if (totalSamples + blockLen > len * numCopies) blockLen = len * numCopies - totalSamples; if (!track->Get(buffer, format, start+blockStart, blockLen)) { delete unitTrack; return false; } unitTrack->Append(buffer, format, blockLen); if (numCopies == 1) unitTrack->Flush(); totalSamples += blockLen; } if (numCopies != 1) unitTrack->Flush(); // // Repeat the unit track enough times, possible creating a few // more than desired // int desiredCopies = repeatCount+1; int desiredUnitTracks = (desiredCopies + (numCopies-1)) / numCopies; for(j=0; j<desiredUnitTracks; j++) dest->Paste(dest->GetEndTime(), unitTrack); // // If necessary, delete a few copies from the end // int actualCopies = desiredUnitTracks * numCopies; if (actualCopies > desiredCopies) { double oneLen = unitTrack->GetEndTime() / numCopies; double clearLen = oneLen * (actualCopies - desiredCopies); double oldDestLen = dest->GetEndTime(); newDestLen = oldDestLen - clearLen; dest->Clear(newDestLen, oldDestLen); } else { newDestLen = dest->GetEndTime(); } if (newDestLen > maxDestLen) maxDestLen = newDestLen; track->Clear(t0, t1); track->Paste(t0, dest); delete unitTrack; delete dest; track = (WaveTrack *) iter.Next(); count++; } mT1 = mT0 + maxDestLen; // Change selection to original plus generated. return true;}//----------------------------------------------------------------------------// RepeatDialog//----------------------------------------------------------------------------#define ID_REPEAT_TEXT 7000BEGIN_EVENT_TABLE(RepeatDialog, wxDialog) EVT_BUTTON(wxID_OK, RepeatDialog::OnOk) EVT_BUTTON(wxID_CANCEL, RepeatDialog::OnCancel) EVT_TEXT(ID_REPEAT_TEXT, RepeatDialog::OnRepeatTextChange)END_EVENT_TABLE()RepeatDialog::RepeatDialog(wxWindow *parent, wxWindowID id, const wxString &title): wxDialog(parent, id, title){ wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); wxStaticText *statText = new wxStaticText(this, -1, _("Repeat by Dominic Mazzoni && Vaughan Johnson")); mainSizer->Add(statText, 0, wxALIGN_CENTRE | wxALL, 5); wxBoxSizer *hSizer = new wxBoxSizer(wxHORIZONTAL); statText = new wxStaticText(this, -1, _("Number of times to repeat: ")); hSizer->Add(statText, 0, wxALIGN_CENTRE | wxALL, 5); mRepeatCount = new wxTextCtrl(this, ID_REPEAT_TEXT, wxT("10"), wxDefaultPosition, wxSize(60, -1), 0, wxTextValidator(wxFILTER_NUMERIC)); hSizer->Add(mRepeatCount, 0, wxALL, 5); mainSizer->Add(hSizer, 0, wxALIGN_CENTRE | wxALL, 5); hSizer = new wxBoxSizer(wxHORIZONTAL); mTotalTime = new wxStaticText(this, -1, wxString(_("New selection length: ")) + wxT("XX minutes, XX seconds")); hSizer->Add(mTotalTime, 1, wxALL | wxEXPAND, 5); 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);}void RepeatDialog::OnRepeatTextChange(wxCommandEvent & event){ // We may even get called during the constructor. // This test saves us from calling unsafe functions. if( !IsShown() ) return; TransferDataFromWindow(); DisplayNewTime();}void RepeatDialog::DisplayNewTime(){ int newTime = (int)(selectionTimeSecs * (repeatCount + 1)); wxString str; str = _("New selection length: "); if (newTime >= 120) str += wxString::Format(_("%d minutes, %d seconds"), newTime/60, newTime%60); else str += wxString::Format(_("%d seconds"), newTime); mTotalTime->SetLabel(str);}bool RepeatDialog::Validate(){ return TRUE;}bool RepeatDialog::TransferDataToWindow(){ mRepeatCount->SetValue(wxString::Format(wxT("%d"), repeatCount)); DisplayNewTime(); return true;}bool RepeatDialog::TransferDataFromWindow(){ long l; mRepeatCount->GetValue().ToLong(&l); repeatCount = l; if (repeatCount < 1) repeatCount = 1; if (repeatCount > maxCount) repeatCount = maxCount; return true;}void RepeatDialog::OnOk(wxCommandEvent & event){ TransferDataFromWindow(); EndModal(true);}void RepeatDialog::OnCancel(wxCommandEvent & event){ EndModal(false);}// Indentation settings for Vim and Emacs and unique identifier for Arch, a// version control system. Please do not modify past this point.//// Local Variables:// c-basic-offset: 3// indent-tabs-mode: nil// End://// vim: et sts=3 sw=3// arch-tag: 65c3dad7-00c2-48bf-a253-c973e626b9ac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -