1
0
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:
Steve Daulton
2016-08-13 17:27:55 +01:00
parent 389d4dc9e6
commit 90e400b0a7
4 changed files with 78 additions and 15 deletions

View File

@@ -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, &region, 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)

View File

@@ -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();
};

View File

@@ -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)
{

View File

@@ -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: