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$
// File revision : $Revision: 4 $
// File revision : $Revision: 1.12 $
//
// $Id$
//
@ -87,7 +87,7 @@ static const int _scanOffsets[4][24]={
TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
{
bQuickseek = FALSE;
bQuickSeek = FALSE;
channels = 2;
bMidBufferDirty = FALSE;
@ -95,6 +95,9 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
pRefMidBufferUnaligned = NULL;
overlapLength = 0;
bAutoSeqSetting = TRUE;
bAutoSeekSetting = TRUE;
tempo = 1.0f;
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
setTempo(1.0f);
@ -102,7 +105,6 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
TDStretch::~TDStretch()
{
delete[] pMidBuffer;
@ -111,7 +113,6 @@ TDStretch::~TDStretch()
// Sets routine control parameters. These control are certain time constants
// defining how the sound is stretched to the desired duration.
//
@ -124,16 +125,29 @@ TDStretch::~TDStretch()
void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS)
{
// accept only positive parameter values - if negative, use old values instead
if (aSampleRate >= 0) this->sampleRate = aSampleRate;
if (aSequenceMS >= 0) this->sequenceMs = aSequenceMS;
if (aSeekWindowMS >= 0) this->seekWindowMs = aSeekWindowMS;
if (aOverlapMS >= 0) this->overlapMs = aOverlapMS;
// accept only positive parameter values - if zero or negative, use old values instead
if (aSampleRate > 0) this->sampleRate = aSampleRate;
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
seekLength = (sampleRate * seekWindowMs) / 1000;
seekWindowLength = (sampleRate * sequenceMs) / 1000;
if (aSequenceMS > 0)
{
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);
@ -156,12 +170,12 @@ void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWind
if (pSequenceMs)
{
*pSequenceMs = sequenceMs;
*pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs;
}
if (pSeekWindowMs)
{
*pSeekWindowMs = seekWindowMs;
*pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs;
}
if (pOverlapMs)
@ -216,14 +230,14 @@ void TDStretch::clear()
// to enable
void TDStretch::enableQuickSeek(BOOL enable)
{
bQuickseek = enable;
bQuickSeek = enable;
}
// Returns nonzero if the quick seeking algorithm is enabled.
BOOL TDStretch::isQuickSeekEnabled() const
{
return bQuickseek;
return bQuickSeek;
}
@ -233,7 +247,7 @@ int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
if (channels == 2)
{
// stereo sound
if (bQuickseek)
if (bQuickSeek)
{
return seekBestOverlapPositionStereoQuick(refPos);
}
@ -245,7 +259,7 @@ int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
else
{
// mono sound
if (bQuickseek)
if (bQuickSeek)
{
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
// tempo, larger faster tempo.
void TDStretch::setTempo(float newTempo)
@ -487,6 +546,9 @@ void TDStretch::setTempo(float newTempo)
tempo = newTempo;
// Calculate new sequence duration
calcSeqParameters();
// Calculate ideal skip length (according to tempo value)
nominalSkip = tempo * (seekWindowLength - overlapLength);
skipFract = 0;
@ -494,7 +556,7 @@ void TDStretch::setTempo(float newTempo)
// Calculate how many samples are needed in the 'inputBuffer' to
// 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.
///
/// 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
/// 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.
///
/// 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,
/// to form a continuous sound stream, this parameter defines over how long period the two
@ -110,13 +120,15 @@ protected:
float skipFract;
FIFOSampleBuffer outputBuffer;
FIFOSampleBuffer inputBuffer;
BOOL bQuickseek;
BOOL bQuickSeek;
BOOL bMidBufferDirty;
int sampleRate;
int sequenceMs;
int seekWindowMs;
int overlapMs;
BOOL bAutoSeqSetting;
BOOL bAutoSeekSetting;
void acceptNewOverlapLength(int newOverlapLength);
@ -141,6 +153,8 @@ protected:
void precalcCorrReferenceMono();
void precalcCorrReferenceStereo();
void calcSeqParameters();
/// Changes the tempo of the given sound samples.
/// Returns amount of samples returned in the "output" buffer.
/// The maximum amount of samples that can be returned at a time is set by