mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 22:28:57 +02:00
Add SBSMS option to Change Tempo effect
Thanks to Clayton Otey for his help and patience.
This commit is contained in:
parent
f4f077a1c6
commit
8e0089c552
@ -19,6 +19,11 @@
|
|||||||
|
|
||||||
#if USE_SOUNDTOUCH
|
#if USE_SOUNDTOUCH
|
||||||
|
|
||||||
|
#if USE_SBSMS
|
||||||
|
#include "sbsms.h"
|
||||||
|
#include <wx/valgen.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <wx/intl.h>
|
#include <wx/intl.h>
|
||||||
@ -44,6 +49,7 @@ enum
|
|||||||
//
|
//
|
||||||
// Name Type Key Def Min Max Scale
|
// Name Type Key Def Min Max Scale
|
||||||
Param( Percentage, double, XO("Percentage"), 0.0, -99.0, 3000.0, 1 );
|
Param( Percentage, double, XO("Percentage"), 0.0, -99.0, 3000.0, 1 );
|
||||||
|
Param( UseSBSMS, bool, XO("SBSMS"), false, false, true, 1 );
|
||||||
|
|
||||||
// We warp the slider to go up to 400%, but user can enter higher values.
|
// We warp the slider to go up to 400%, but user can enter higher values.
|
||||||
static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
|
static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
|
||||||
@ -71,6 +77,12 @@ EffectChangeTempo::EffectChangeTempo()
|
|||||||
|
|
||||||
m_bLoopDetect = false;
|
m_bLoopDetect = false;
|
||||||
|
|
||||||
|
#if USE_SBSMS
|
||||||
|
mUseSBSMS = DEF_UseSBSMS;
|
||||||
|
#else
|
||||||
|
mUseSBSMS = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
SetLinearEffectFlag(true);
|
SetLinearEffectFlag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +119,7 @@ bool EffectChangeTempo::SupportsAutomation()
|
|||||||
bool EffectChangeTempo::GetAutomationParameters(EffectAutomationParameters & parms)
|
bool EffectChangeTempo::GetAutomationParameters(EffectAutomationParameters & parms)
|
||||||
{
|
{
|
||||||
parms.Write(KEY_Percentage, m_PercentChange);
|
parms.Write(KEY_Percentage, m_PercentChange);
|
||||||
|
parms.Write(KEY_UseSBSMS, mUseSBSMS);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -114,9 +127,15 @@ bool EffectChangeTempo::GetAutomationParameters(EffectAutomationParameters & par
|
|||||||
bool EffectChangeTempo::SetAutomationParameters(EffectAutomationParameters & parms)
|
bool EffectChangeTempo::SetAutomationParameters(EffectAutomationParameters & parms)
|
||||||
{
|
{
|
||||||
ReadAndVerifyDouble(Percentage);
|
ReadAndVerifyDouble(Percentage);
|
||||||
|
|
||||||
m_PercentChange = Percentage;
|
m_PercentChange = Percentage;
|
||||||
|
|
||||||
|
#if USE_SBSMS
|
||||||
|
ReadAndVerifyBool(UseSBSMS);
|
||||||
|
mUseSBSMS = UseSBSMS;
|
||||||
|
#else
|
||||||
|
mUseSBSMS = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,14 +165,31 @@ bool EffectChangeTempo::Init()
|
|||||||
|
|
||||||
bool EffectChangeTempo::Process()
|
bool EffectChangeTempo::Process()
|
||||||
{
|
{
|
||||||
mSoundTouch = std::make_unique<SoundTouch>();
|
bool success = false;
|
||||||
mSoundTouch->setTempoChange(m_PercentChange);
|
|
||||||
double mT1Dashed = mT0 + (mT1 - mT0)/(m_PercentChange/100.0 + 1.0);
|
#if USE_SBSMS
|
||||||
SetTimeWarper(std::make_unique<RegionTimeWarper>(mT0, mT1,
|
if (mUseSBSMS)
|
||||||
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed )));
|
{
|
||||||
bool success = EffectSoundTouch::Process();
|
double tempoRatio = 1.0 + m_PercentChange / 100.0;
|
||||||
if( success )
|
SelectedRegion region(mT0, mT1);
|
||||||
|
EffectSBSMS proxy;
|
||||||
|
proxy.setParameters(tempoRatio, 1.0);
|
||||||
|
success = proxy.DoEffect(mUIParent, mProjectRate, mTracks, mFactory, ®ion, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
mSoundTouch = std::make_unique<SoundTouch>();
|
||||||
|
mSoundTouch->setTempoChange(m_PercentChange);
|
||||||
|
double mT1Dashed = mT0 + (mT1 - mT0)/(m_PercentChange/100.0 + 1.0);
|
||||||
|
SetTimeWarper(std::make_unique<RegionTimeWarper>(mT0, mT1,
|
||||||
|
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed )));
|
||||||
|
success = EffectSoundTouch::Process();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(success)
|
||||||
mT1 = mT0 + (mT1 - mT0)/(m_PercentChange/100 + 1.);
|
mT1 = mT0 + (mT1 - mT0)/(m_PercentChange/100 + 1.);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,50 +222,67 @@ void EffectChangeTempo::PopulateOrExchange(ShuttleGui & S)
|
|||||||
}
|
}
|
||||||
S.EndHorizontalLay();
|
S.EndHorizontalLay();
|
||||||
|
|
||||||
//
|
S.StartStatic(_("Beats per minute"));
|
||||||
S.StartMultiColumn(5, wxCENTER);
|
|
||||||
{
|
{
|
||||||
//
|
S.StartHorizontalLay(wxALIGN_CENTER);
|
||||||
S.AddUnits(_("Beats per minute:"));
|
{
|
||||||
|
FloatingPointValidator<double> vldFromBPM(3, &m_FromBPM, NUM_VAL_THREE_TRAILING_ZEROES | NUM_VAL_ZERO_AS_BLANK);
|
||||||
|
m_pTextCtrl_FromBPM = S.Id(ID_FromBPM)
|
||||||
|
.AddTextBox(_("from"), wxT(""), 12);
|
||||||
|
m_pTextCtrl_FromBPM->SetName(_("From beats per minute"));
|
||||||
|
m_pTextCtrl_FromBPM->SetValidator(vldFromBPM);
|
||||||
|
|
||||||
FloatingPointValidator<double> vldFromBPM(3, &m_FromBPM, NUM_VAL_THREE_TRAILING_ZEROES | NUM_VAL_ZERO_AS_BLANK);
|
FloatingPointValidator<double> vldToBPM(3, &m_ToBPM, NUM_VAL_THREE_TRAILING_ZEROES | NUM_VAL_ZERO_AS_BLANK);
|
||||||
m_pTextCtrl_FromBPM = S.Id(ID_FromBPM)
|
m_pTextCtrl_ToBPM = S.Id(ID_ToBPM)
|
||||||
.AddTextBox(_("from"), wxT(""), 12);
|
.AddTextBox(_("to"), wxT(""), 12);
|
||||||
m_pTextCtrl_FromBPM->SetName(_("From beats per minute"));
|
m_pTextCtrl_ToBPM->SetName(_("To beats per minute"));
|
||||||
m_pTextCtrl_FromBPM->SetValidator(vldFromBPM);
|
m_pTextCtrl_ToBPM->SetValidator(vldToBPM);
|
||||||
|
}
|
||||||
|
S.EndHorizontalLay();
|
||||||
|
}
|
||||||
|
S.EndStatic();
|
||||||
|
|
||||||
FloatingPointValidator<double> vldToBPM(3, &m_ToBPM, NUM_VAL_THREE_TRAILING_ZEROES | NUM_VAL_ZERO_AS_BLANK);
|
//
|
||||||
m_pTextCtrl_ToBPM = S.Id(ID_ToBPM)
|
S.StartStatic(_("Length (seconds)"));
|
||||||
.AddTextBox(_("to"), wxT(""), 12);
|
{
|
||||||
m_pTextCtrl_ToBPM->SetName(_("To beats per minute"));
|
S.StartHorizontalLay(wxALIGN_CENTER);
|
||||||
m_pTextCtrl_ToBPM->SetValidator(vldToBPM);
|
{
|
||||||
|
int precission = 2;
|
||||||
|
FloatingPointValidator<double> vldFromLength(precission, &m_FromLength, NUM_VAL_TWO_TRAILING_ZEROES);
|
||||||
|
m_pTextCtrl_FromLength = S.Id(ID_FromLength)
|
||||||
|
.AddTextBox(_("from"), wxT(""), 12);
|
||||||
|
m_pTextCtrl_FromLength->SetName(_("From length in seconds"));
|
||||||
|
m_pTextCtrl_FromLength->SetValidator(vldFromLength);
|
||||||
|
m_pTextCtrl_FromLength->Enable(false); // Disable because the value comes from the user selection.
|
||||||
|
|
||||||
//
|
FloatingPointValidator<double> vldToLength(2, &m_ToLength, NUM_VAL_TWO_TRAILING_ZEROES);
|
||||||
S.AddUnits(_("Length (seconds):"));
|
|
||||||
|
|
||||||
int precission = 2;
|
// min and max need same precision as what we're validating (bug 963)
|
||||||
FloatingPointValidator<double> vldFromLength(precission, &m_FromLength, NUM_VAL_TWO_TRAILING_ZEROES);
|
double minLength = (m_FromLength * 100.0) / (100.0 + MAX_Percentage);
|
||||||
m_pTextCtrl_FromLength = S.Id(ID_FromLength)
|
double maxLength = (m_FromLength * 100.0) / (100.0 + MIN_Percentage);
|
||||||
.AddTextBox(_("from"), wxT(""), 12);
|
minLength = Internat::CompatibleToDouble(Internat::ToString(minLength, precission));
|
||||||
m_pTextCtrl_FromLength->SetName(_("From length in seconds"));
|
maxLength = Internat::CompatibleToDouble(Internat::ToString(maxLength, precission));
|
||||||
m_pTextCtrl_FromLength->SetValidator(vldFromLength);
|
|
||||||
m_pTextCtrl_FromLength->Enable(false); // Disable because the value comes from the user selection.
|
|
||||||
|
|
||||||
FloatingPointValidator<double> vldToLength(2, &m_ToLength, NUM_VAL_TWO_TRAILING_ZEROES);
|
vldToLength.SetRange(minLength, maxLength);
|
||||||
|
m_pTextCtrl_ToLength = S.Id(ID_ToLength)
|
||||||
|
.AddTextBox(_("to"), wxT(""), 12);
|
||||||
|
m_pTextCtrl_ToLength->SetName(_("To length in seconds"));
|
||||||
|
m_pTextCtrl_ToLength->SetValidator(vldToLength);
|
||||||
|
}
|
||||||
|
S.EndHorizontalLay();
|
||||||
|
}
|
||||||
|
S.EndStatic();
|
||||||
|
|
||||||
// min and max need same precision as what we're validating (bug 963)
|
#if USE_SBSMS
|
||||||
double minLength = (m_FromLength * 100.0) / (100.0 + MAX_Percentage);
|
S.StartMultiColumn(2);
|
||||||
double maxLength = (m_FromLength * 100.0) / (100.0 + MIN_Percentage);
|
{
|
||||||
minLength = Internat::CompatibleToDouble(Internat::ToString(minLength, precission));
|
mUseSBSMSCheckBox = S.AddCheckBox(_("Use high quality stretching (slow)"),
|
||||||
maxLength = Internat::CompatibleToDouble(Internat::ToString(maxLength, precission));
|
mUseSBSMS? wxT("true") : wxT("false"));
|
||||||
|
mUseSBSMSCheckBox->SetValidator(wxGenericValidator(&mUseSBSMS));
|
||||||
vldToLength.SetRange(minLength, maxLength);
|
|
||||||
m_pTextCtrl_ToLength = S.Id(ID_ToLength)
|
|
||||||
.AddTextBox(_("to"), wxT(""), 12);
|
|
||||||
m_pTextCtrl_ToLength->SetName(_("To length in seconds"));
|
|
||||||
m_pTextCtrl_ToLength->SetValidator(vldToLength);
|
|
||||||
}
|
}
|
||||||
S.EndMultiColumn();
|
S.EndMultiColumn();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
S.EndVerticalLay();
|
S.EndVerticalLay();
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@
|
|||||||
#ifndef __AUDACITY_EFFECT_CHANGETEMPO__
|
#ifndef __AUDACITY_EFFECT_CHANGETEMPO__
|
||||||
#define __AUDACITY_EFFECT_CHANGETEMPO__
|
#define __AUDACITY_EFFECT_CHANGETEMPO__
|
||||||
|
|
||||||
|
#if USE_SBSMS
|
||||||
|
#include "SBSMSEffect.h"
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/slider.h>
|
#include <wx/slider.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
@ -75,6 +80,7 @@ private:
|
|||||||
void Update_Text_ToLength(); // Use m_FromLength & m_PercentChange to set NEW m_ToLength & control.
|
void Update_Text_ToLength(); // Use m_FromLength & m_PercentChange to set NEW m_ToLength & control.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool mUseSBSMS;
|
||||||
double m_PercentChange; // percent change to apply to tempo
|
double m_PercentChange; // percent change to apply to tempo
|
||||||
// -100% is meaningless, but sky's the upper limit
|
// -100% is meaningless, but sky's the upper limit
|
||||||
double m_FromBPM; // user-set beats-per-minute. Zero means not yet set.
|
double m_FromBPM; // user-set beats-per-minute. Zero means not yet set.
|
||||||
@ -92,6 +98,10 @@ private:
|
|||||||
wxTextCtrl * m_pTextCtrl_FromLength;
|
wxTextCtrl * m_pTextCtrl_FromLength;
|
||||||
wxTextCtrl * m_pTextCtrl_ToLength;
|
wxTextCtrl * m_pTextCtrl_ToLength;
|
||||||
|
|
||||||
|
#if USE_SBSMS
|
||||||
|
wxCheckBox * mUseSBSMSCheckBox;
|
||||||
|
#endif
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user