Added automatic sequence/seek window length parameter calculation

This commit is contained in:
oparviai 2009-01-25 13:43:54 +00:00
parent f7a0143374
commit 9d7952e56e
2 changed files with 98 additions and 22 deletions

View File

@ -14,7 +14,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
// Last changed : $Date$ // Last changed : $Date$
// File revision : $Revision: 4 $ // File revision : $Revision: 1.12 $
// //
// $Id$ // $Id$
// //
@ -87,7 +87,7 @@ static const int _scanOffsets[4][24]={
TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
{ {
bQuickseek = FALSE; bQuickSeek = FALSE;
channels = 2; channels = 2;
bMidBufferDirty = FALSE; bMidBufferDirty = FALSE;
@ -95,6 +95,9 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
pRefMidBufferUnaligned = NULL; pRefMidBufferUnaligned = NULL;
overlapLength = 0; overlapLength = 0;
bAutoSeqSetting = TRUE;
bAutoSeekSetting = TRUE;
tempo = 1.0f; tempo = 1.0f;
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
setTempo(1.0f); setTempo(1.0f);
@ -102,7 +105,6 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
TDStretch::~TDStretch() TDStretch::~TDStretch()
{ {
delete[] pMidBuffer; delete[] pMidBuffer;
@ -111,7 +113,6 @@ TDStretch::~TDStretch()
// Sets routine control parameters. These control are certain time constants // Sets routine control parameters. These control are certain time constants
// defining how the sound is stretched to the desired duration. // defining how the sound is stretched to the desired duration.
// //
@ -124,16 +125,29 @@ TDStretch::~TDStretch()
void TDStretch::setParameters(int aSampleRate, int aSequenceMS, void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS) int aSeekWindowMS, int aOverlapMS)
{ {
// accept only positive parameter values - if negative, use old values instead // accept only positive parameter values - if zero or negative, use old values instead
if (aSampleRate >= 0) this->sampleRate = aSampleRate; if (aSampleRate > 0) this->sampleRate = aSampleRate;
if (aSequenceMS >= 0) this->sequenceMs = aSequenceMS; if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSeekWindowMS >= 0) this->seekWindowMs = aSeekWindowMS;
if (aOverlapMS >= 0) this->overlapMs = aOverlapMS;
seekLength = (sampleRate * seekWindowMs) / 1000; if (aSequenceMS > 0)
seekWindowLength = (sampleRate * sequenceMs) / 1000; {
this->sequenceMs = aSequenceMS;
bAutoSeqSetting = FALSE;
} else {
// zero or below, use automatic setting
bAutoSeqSetting = TRUE;
}
maxOffset = seekLength; if (aSeekWindowMS > 0)
{
this->seekWindowMs = aSeekWindowMS;
bAutoSeekSetting = FALSE;
} else {
// zero or below, use automatic setting
bAutoSeekSetting = TRUE;
}
calcSeqParameters();
calculateOverlapLength(overlapMs); calculateOverlapLength(overlapMs);
@ -156,12 +170,12 @@ void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWind
if (pSequenceMs) if (pSequenceMs)
{ {
*pSequenceMs = sequenceMs; *pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs;
} }
if (pSeekWindowMs) if (pSeekWindowMs)
{ {
*pSeekWindowMs = seekWindowMs; *pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs;
} }
if (pOverlapMs) if (pOverlapMs)
@ -216,14 +230,14 @@ void TDStretch::clear()
// to enable // to enable
void TDStretch::enableQuickSeek(BOOL enable) void TDStretch::enableQuickSeek(BOOL enable)
{ {
bQuickseek = enable; bQuickSeek = enable;
} }
// Returns nonzero if the quick seeking algorithm is enabled. // Returns nonzero if the quick seeking algorithm is enabled.
BOOL TDStretch::isQuickSeekEnabled() const BOOL TDStretch::isQuickSeekEnabled() const
{ {
return bQuickseek; return bQuickSeek;
} }
@ -233,7 +247,7 @@ int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
if (channels == 2) if (channels == 2)
{ {
// stereo sound // stereo sound
if (bQuickseek) if (bQuickSeek)
{ {
return seekBestOverlapPositionStereoQuick(refPos); return seekBestOverlapPositionStereoQuick(refPos);
} }
@ -245,7 +259,7 @@ int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
else else
{ {
// mono sound // mono sound
if (bQuickseek) if (bQuickSeek)
{ {
return seekBestOverlapPositionMonoQuick(refPos); return seekBestOverlapPositionMonoQuick(refPos);
} }
@ -479,6 +493,51 @@ void TDStretch::clearCrossCorrState()
} }
/// Calculates processing sequence length according to tempo setting
void TDStretch::calcSeqParameters()
{
// Adjust tempo param according to tempo, so that variating processing sequence length is used
// at varius tempo settings, between the given low...top limits
#define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%)
#define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
// sequence-ms setting values at above low & top tempo
#define AUTOSEQ_AT_MIN 125.0
#define AUTOSEQ_AT_MAX 50.0
#define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
#define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
// seek-window-ms setting values at above low & top tempo
#define AUTOSEEK_AT_MIN 25.0
#define AUTOSEEK_AT_MAX 15.0
#define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
#define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
#define CHECK_LIMITS(x, mi, ma) ((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x))
double seq, seek;
if (bAutoSeqSetting)
{
seq = AUTOSEQ_C + AUTOSEQ_K * tempo;
seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
sequenceMs = (int)(seq + 0.5);
}
if (bAutoSeekSetting)
{
seek = AUTOSEEK_C + AUTOSEEK_K * tempo;
seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
seekWindowMs = (int)(seek + 0.5);
}
// Update seek window lengths
seekWindowLength = (sampleRate * sequenceMs) / 1000;
seekLength = (sampleRate * seekWindowMs) / 1000;
}
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
// tempo, larger faster tempo. // tempo, larger faster tempo.
void TDStretch::setTempo(float newTempo) void TDStretch::setTempo(float newTempo)
@ -487,6 +546,9 @@ void TDStretch::setTempo(float newTempo)
tempo = newTempo; tempo = newTempo;
// Calculate new sequence duration
calcSeqParameters();
// Calculate ideal skip length (according to tempo value) // Calculate ideal skip length (according to tempo value)
nominalSkip = tempo * (seekWindowLength - overlapLength); nominalSkip = tempo * (seekWindowLength - overlapLength);
skipFract = 0; skipFract = 0;
@ -494,7 +556,7 @@ void TDStretch::setTempo(float newTempo)
// Calculate how many samples are needed in the 'inputBuffer' to // Calculate how many samples are needed in the 'inputBuffer' to
// process another batch of samples // process another batch of samples
sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset; sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength;
} }

View File

@ -61,7 +61,12 @@ namespace soundtouch
/// and vice versa. /// and vice versa.
/// ///
/// Increasing this value reduces computational burden & vice versa. /// Increasing this value reduces computational burden & vice versa.
#define DEFAULT_SEQUENCE_MS 130 //#define DEFAULT_SEQUENCE_MS 130
#define DEFAULT_SEQUENCE_MS USE_AUTO_SEQUENCE_LEN
/// Giving this value for the sequence length sets automatic parameter value
/// according to tempo setting (recommended)
#define USE_AUTO_SEQUENCE_LEN 0
/// Seeking window default length in milliseconds for algorithm that finds the best possible /// Seeking window default length in milliseconds for algorithm that finds the best possible
/// overlapping location. This determines from how wide window the algorithm may look for an /// overlapping location. This determines from how wide window the algorithm may look for an
@ -75,7 +80,12 @@ namespace soundtouch
/// around, try reducing this setting. /// around, try reducing this setting.
/// ///
/// Increasing this value increases computational burden & vice versa. /// Increasing this value increases computational burden & vice versa.
#define DEFAULT_SEEKWINDOW_MS 25 //#define DEFAULT_SEEKWINDOW_MS 25
#define DEFAULT_SEEKWINDOW_MS USE_AUTO_SEEKWINDOW_LEN
/// Giving this value for the seek window length sets automatic parameter value
/// according to tempo setting (recommended)
#define USE_AUTO_SEEKWINDOW_LEN 0
/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together, /// Overlap length in milliseconds. When the chopped sound sequences are mixed back together,
/// to form a continuous sound stream, this parameter defines over how long period the two /// to form a continuous sound stream, this parameter defines over how long period the two
@ -110,13 +120,15 @@ protected:
float skipFract; float skipFract;
FIFOSampleBuffer outputBuffer; FIFOSampleBuffer outputBuffer;
FIFOSampleBuffer inputBuffer; FIFOSampleBuffer inputBuffer;
BOOL bQuickseek; BOOL bQuickSeek;
BOOL bMidBufferDirty; BOOL bMidBufferDirty;
int sampleRate; int sampleRate;
int sequenceMs; int sequenceMs;
int seekWindowMs; int seekWindowMs;
int overlapMs; int overlapMs;
BOOL bAutoSeqSetting;
BOOL bAutoSeekSetting;
void acceptNewOverlapLength(int newOverlapLength); void acceptNewOverlapLength(int newOverlapLength);
@ -141,6 +153,8 @@ protected:
void precalcCorrReferenceMono(); void precalcCorrReferenceMono();
void precalcCorrReferenceStereo(); void precalcCorrReferenceStereo();
void calcSeqParameters();
/// Changes the tempo of the given sound samples. /// Changes the tempo of the given sound samples.
/// Returns amount of samples returned in the "output" buffer. /// Returns amount of samples returned in the "output" buffer.
/// The maximum amount of samples that can be returned at a time is set by /// The maximum amount of samples that can be returned at a time is set by