mirror of
https://github.com/azahar-emu/soundtouch
synced 2025-11-08 16:10:10 +01:00
Added automatic sequence/seek window length parameter calculation
This commit is contained in:
parent
f7a0143374
commit
9d7952e56e
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user