mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-25 07:43:54 +02:00
Add SBSMS option to Change Pitch effect
This commit is contained in:
@@ -18,9 +18,13 @@ the pitch without changing the tempo.
|
||||
#include "../Audacity.h" // for USE_SOUNDTOUCH
|
||||
|
||||
#if USE_SOUNDTOUCH
|
||||
|
||||
#include "ChangePitch.h"
|
||||
|
||||
#if USE_SBSMS
|
||||
#include "sbsms.h"
|
||||
#include <wx/valgen.h>
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -51,6 +55,7 @@ enum {
|
||||
//
|
||||
// Name Type Key Def Min Max Scale
|
||||
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 up to 3000%
|
||||
static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
|
||||
@@ -80,6 +85,12 @@ EffectChangePitch::EffectChangePitch()
|
||||
m_dStartFrequency = 0.0; // 0.0 => uninitialized
|
||||
m_bLoopDetect = false;
|
||||
|
||||
#if USE_SBSMS
|
||||
mUseSBSMS = DEF_UseSBSMS;
|
||||
#else
|
||||
mUseSBSMS = false;
|
||||
#endif
|
||||
|
||||
// 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.
|
||||
@@ -127,6 +138,7 @@ EffectType EffectChangePitch::GetType()
|
||||
bool EffectChangePitch::GetAutomationParameters(EffectAutomationParameters & parms)
|
||||
{
|
||||
parms.Write(KEY_Percentage, m_dPercentChange);
|
||||
parms.Write(KEY_UseSBSMS, mUseSBSMS);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -140,6 +152,13 @@ bool EffectChangePitch::SetAutomationParameters(EffectAutomationParameters & par
|
||||
m_dPercentChange = Percentage;
|
||||
Calc_SemitonesChange_fromPercentChange();
|
||||
|
||||
#if USE_SBSMS
|
||||
ReadAndVerifyBool(UseSBSMS);
|
||||
mUseSBSMS = UseSBSMS;
|
||||
#else
|
||||
mUseSBSMS = false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,20 +179,37 @@ bool EffectChangePitch::Init()
|
||||
|
||||
bool EffectChangePitch::Process()
|
||||
{
|
||||
mSoundTouch = std::make_unique<SoundTouch>();
|
||||
SetTimeWarper(std::make_unique<IdentityTimeWarper>());
|
||||
mSoundTouch->setPitchSemiTones((float)(m_dSemitonesChange));
|
||||
#ifdef USE_MIDI
|
||||
// Note: m_dSemitonesChange is private to ChangePitch because it only
|
||||
// needs to pass it along to mSoundTouch (above). I added mSemitones
|
||||
// to SoundTouchEffect (the super class) to convey this value
|
||||
// to process Note tracks. This approach minimizes changes to existing
|
||||
// code, but it would be cleaner to change all m_dSemitonesChange to
|
||||
// mSemitones, make mSemitones exist with or without USE_MIDI, and
|
||||
// eliminate the next line:
|
||||
mSemitones = m_dSemitonesChange;
|
||||
#if USE_SBSMS
|
||||
if (mUseSBSMS)
|
||||
{
|
||||
double pitchRatio = 1.0 + m_dPercentChange / 100.0;
|
||||
SelectedRegion region(mT0, mT1);
|
||||
EffectSBSMS proxy;
|
||||
proxy.setParameters(1.0, pitchRatio);
|
||||
|
||||
return proxy.DoEffect(mUIParent, mProjectRate, mTracks, mFactory, ®ion, false);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return EffectSoundTouch::Process();
|
||||
{
|
||||
mSoundTouch = std::make_unique<SoundTouch>();
|
||||
SetTimeWarper(std::make_unique<IdentityTimeWarper>());
|
||||
mSoundTouch->setPitchSemiTones((float)(m_dSemitonesChange));
|
||||
#ifdef USE_MIDI
|
||||
// Pitch shifting note tracks is currently only supported by SoundTouchEffect
|
||||
// and non-real-time-preview effects require an audio track selection.
|
||||
//
|
||||
// Note: m_dSemitonesChange is private to ChangePitch because it only
|
||||
// needs to pass it along to mSoundTouch (above). I added mSemitones
|
||||
// to SoundTouchEffect (the super class) to convey this value
|
||||
// to process Note tracks. This approach minimizes changes to existing
|
||||
// code, but it would be cleaner to change all m_dSemitonesChange to
|
||||
// mSemitones, make mSemitones exist with or without USE_MIDI, and
|
||||
// eliminate the next line:
|
||||
mSemitones = m_dSemitonesChange;
|
||||
#endif
|
||||
return EffectSoundTouch::Process();
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectChangePitch::CheckWhetherSkipEffect()
|
||||
@@ -287,6 +323,17 @@ void EffectChangePitch::PopulateOrExchange(ShuttleGui & S)
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
#if USE_SBSMS
|
||||
S.StartMultiColumn(2);
|
||||
{
|
||||
mUseSBSMSCheckBox = S.AddCheckBox(_("Use high quality stretching (slow)"),
|
||||
mUseSBSMS? wxT("true") : wxT("false"));
|
||||
mUseSBSMSCheckBox->SetValidator(wxGenericValidator(&mUseSBSMS));
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
#endif
|
||||
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
@@ -460,7 +507,6 @@ void EffectChangePitch::Calc_PercentChange()
|
||||
|
||||
|
||||
// handlers
|
||||
|
||||
void EffectChangePitch::OnChoice_FromPitch(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
|
||||
@@ -20,6 +20,11 @@ the pitch without changing the tempo.
|
||||
#ifndef __AUDACITY_EFFECT_CHANGEPITCH__
|
||||
#define __AUDACITY_EFFECT_CHANGEPITCH__
|
||||
|
||||
#if USE_SBSMS
|
||||
#include "SBSMSEffect.h"
|
||||
#include <wx/checkbox.h>
|
||||
#endif
|
||||
|
||||
#include <wx/choice.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/slider.h>
|
||||
@@ -108,6 +113,7 @@ private:
|
||||
void Update_Slider_PercentChange(); // Update control per current m_dPercentChange.
|
||||
|
||||
private:
|
||||
bool mUseSBSMS;
|
||||
// effect parameters
|
||||
int m_nFromPitch; // per PitchIndex()
|
||||
int m_nFromOctave; // per PitchOctave()
|
||||
@@ -136,6 +142,10 @@ private:
|
||||
wxTextCtrl * m_pTextCtrl_PercentChange;
|
||||
wxSlider * m_pSlider_PercentChange;
|
||||
|
||||
#if USE_SBSMS
|
||||
wxCheckBox * mUseSBSMSCheckBox;
|
||||
#endif
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
|
||||
@@ -156,6 +156,12 @@ void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double pitch
|
||||
this->bPitchReferenceInput = bPitchReferenceInput;
|
||||
}
|
||||
|
||||
void EffectSBSMS::setParameters(double tempoRatio, double pitchRatio)
|
||||
{
|
||||
setParameters(tempoRatio, tempoRatio, pitchRatio, pitchRatio,
|
||||
SlideConstant, SlideConstant, false, false, false);
|
||||
}
|
||||
|
||||
std::unique_ptr<TimeWarper> createTimeWarper(double t0, double t1, double duration,
|
||||
double rateStart, double rateEnd, SlideType rateSlideType)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput);
|
||||
void setParameters(double tempoRatio, double pitchRatio); // Constant ratio (tempoRatio, pitchRatio)
|
||||
static double getInvertedStretchedTime(double rateStart, double rateEnd, SlideType slideType, double outputTime);
|
||||
static double getRate(double rateStart, double rateEnd, SlideType slideType, double t);
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user