mirror of
https://github.com/cookiengineer/audacity
synced 2026-04-22 14:10:24 +02:00
Locate and position the current Audacity source code, and clear a variety of old junk out of the way into junk-branches
This commit is contained in:
288
src/effects/Echo.cpp
Normal file
288
src/effects/Echo.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
Echo.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
Vaughan Johnson (dialog)
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class EffectEcho
|
||||
\brief An Effect that causes an echo, variable delay and volume.
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class EchoDialog
|
||||
\brief EchoDialog used with EffectEcho
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
#include "../Audacity.h"
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/validate.h>
|
||||
#include <wx/valtext.h>
|
||||
|
||||
#include <wx/generic/textdlgg.h>
|
||||
#include <wx/intl.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Echo.h"
|
||||
#include "../WaveTrack.h"
|
||||
|
||||
EffectEcho::EffectEcho()
|
||||
{
|
||||
delay = float(1.0);
|
||||
decay = float(0.5);
|
||||
}
|
||||
|
||||
wxString EffectEcho::GetEffectDescription() {
|
||||
// Note: This is useful only after values have been set.
|
||||
return wxString::Format(_("Applied effect: %s delay = %f seconds, decay factor = %f"),
|
||||
this->GetEffectName().c_str(), delay, decay);
|
||||
}
|
||||
|
||||
bool EffectEcho::PromptUser()
|
||||
{
|
||||
EchoDialog dlog(this, mParent);
|
||||
dlog.delay = delay;
|
||||
dlog.decay = decay;
|
||||
dlog.CentreOnParent();
|
||||
dlog.ShowModal();
|
||||
|
||||
if (dlog.GetReturnCode() == wxID_CANCEL)
|
||||
return false;
|
||||
|
||||
delay = dlog.delay;
|
||||
decay = dlog.decay;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EffectEcho::TransferParameters( Shuttle & shuttle )
|
||||
{
|
||||
shuttle.TransferFloat(wxT("Delay"),delay,1.0);
|
||||
shuttle.TransferFloat(wxT("Decay"),decay,0.5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EffectEcho::Process()
|
||||
{
|
||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||
bool bGoodResult = true;
|
||||
|
||||
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks);
|
||||
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) {
|
||||
sampleCount start = track->TimeToLongSamples(t0);
|
||||
sampleCount end = track->TimeToLongSamples(t1);
|
||||
sampleCount len = (sampleCount)(end - start);
|
||||
|
||||
if (!ProcessOne(count, track, start, len))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
track = (WaveTrack *) iter.Next();
|
||||
count++;
|
||||
}
|
||||
|
||||
this->ReplaceProcessedTracks(bGoodResult);
|
||||
return bGoodResult;
|
||||
}
|
||||
|
||||
bool EffectEcho::ProcessOne(int count, WaveTrack * track,
|
||||
sampleCount start, sampleCount len)
|
||||
{
|
||||
sampleCount s = 0;
|
||||
sampleCount blockSize = (sampleCount) (track->GetRate() * delay);
|
||||
|
||||
//do nothing if the delay is less than 1 sample or greater than
|
||||
//the length of the selection
|
||||
if (blockSize < 1 || blockSize > len)
|
||||
return true;
|
||||
|
||||
float *buffer0 = new float[blockSize];
|
||||
float *buffer1 = new float[blockSize];
|
||||
|
||||
float *ptr0 = buffer0;
|
||||
float *ptr1 = buffer1;
|
||||
|
||||
bool first = true;
|
||||
|
||||
while (s < len) {
|
||||
sampleCount block = blockSize;
|
||||
if (s + block > len)
|
||||
block = len - s;
|
||||
|
||||
track->Get((samplePtr)ptr0, floatSample, start + s, block);
|
||||
if (!first) {
|
||||
for (sampleCount i = 0; i < block; i++)
|
||||
ptr0[i] += ptr1[i] * decay;
|
||||
track->Set((samplePtr)ptr0, floatSample, start + s, block);
|
||||
}
|
||||
|
||||
float *ptrtemp = ptr0;
|
||||
ptr0 = ptr1;
|
||||
ptr1 = ptrtemp;
|
||||
|
||||
first = false;
|
||||
|
||||
s += block;
|
||||
|
||||
if (TrackProgress(count, s / (double) len)) {
|
||||
delete[]buffer0;
|
||||
delete[]buffer1;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete[]buffer0;
|
||||
delete[]buffer1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// EchoDialog
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// event table for EchoDialog
|
||||
|
||||
BEGIN_EVENT_TABLE(EchoDialog, EffectDialog)
|
||||
EVT_BUTTON(ID_EFFECT_PREVIEW, EchoDialog::OnPreview)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
EchoDialog::EchoDialog(EffectEcho * effect, wxWindow * parent)
|
||||
: EffectDialog(parent, _("Echo"))
|
||||
{
|
||||
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_Delay = NULL;
|
||||
m_pTextCtrl_Decay = NULL;
|
||||
|
||||
// effect parameters
|
||||
delay = float(1.0);
|
||||
decay = float(0.5);
|
||||
|
||||
// Initialize dialog
|
||||
Init();
|
||||
}
|
||||
|
||||
void EchoDialog::PopulateOrExchange(ShuttleGui & S)
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
/* i18n-hint: && in here is an escape character to get a single & on
|
||||
* screen, so keep it as is */
|
||||
S.AddTitle(_("by Dominic Mazzoni && Vaughan Johnson"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
// Add a little space
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartMultiColumn(2, wxALIGN_CENTER);
|
||||
{
|
||||
m_pTextCtrl_Delay = S.AddTextBox(_("Delay time (seconds):"),
|
||||
wxT("1.0"),
|
||||
10);
|
||||
m_pTextCtrl_Delay->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
|
||||
m_pTextCtrl_Decay = S.AddTextBox(_("Decay factor:"),
|
||||
wxT("0.5"),
|
||||
10);
|
||||
m_pTextCtrl_Decay->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
|
||||
bool EchoDialog::TransferDataToWindow()
|
||||
{
|
||||
m_bLoopDetect = true;
|
||||
|
||||
wxString str;
|
||||
if (m_pTextCtrl_Delay) {
|
||||
str.Printf(wxT("%g"), delay);
|
||||
m_pTextCtrl_Delay->SetValue(str);
|
||||
}
|
||||
if (m_pTextCtrl_Decay) {
|
||||
str.Printf(wxT("%g"), decay);
|
||||
m_pTextCtrl_Decay->SetValue(str);
|
||||
}
|
||||
|
||||
m_bLoopDetect = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EchoDialog::TransferDataFromWindow()
|
||||
{
|
||||
double newValue;
|
||||
wxString str;
|
||||
if (m_pTextCtrl_Delay) {
|
||||
str = m_pTextCtrl_Delay->GetValue();
|
||||
str.ToDouble(&newValue);
|
||||
delay = (float)(newValue);
|
||||
}
|
||||
if (m_pTextCtrl_Decay) {
|
||||
str = m_pTextCtrl_Decay->GetValue();
|
||||
str.ToDouble(&newValue);
|
||||
decay = (float)(newValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// handler implementations for EchoDialog
|
||||
|
||||
void EchoDialog::OnPreview(wxCommandEvent &event)
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
// Save & restore parameters around Preview, because we didn't do OK.
|
||||
float oldDelay = m_pEffect->delay;
|
||||
float oldDecay = m_pEffect->decay;
|
||||
|
||||
m_pEffect->delay = delay;
|
||||
m_pEffect->decay = decay;
|
||||
|
||||
m_pEffect->Preview();
|
||||
|
||||
m_pEffect->delay = oldDelay;
|
||||
m_pEffect->decay = oldDecay;
|
||||
}
|
||||
|
||||
// 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: 1c174e3a-7748-4045-8066-b394189a7ba7
|
||||
|
||||
Reference in New Issue
Block a user