|
|
|
@ -117,6 +117,28 @@ SoundTouch::~SoundTouch() |
|
|
|
delete pTDStretch; |
|
|
|
delete pTDStretch; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool SoundTouch::sourceProfileSupported() const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#if defined(SOUNDTOUCH_FLOAT_SAMPLES) && !defined(SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER) |
|
|
|
|
|
|
|
return rate == 1.0 && virtualPitch == 1.0 && channels >= 1 && channels <= 2 |
|
|
|
|
|
|
|
&& bSrateSet && pRateTransposer->unitySourceOffset() >= 0; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool SoundTouch::setSourceCallback(SourceCallback callback, void* context) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!callback) { pTDStretch->setSourceCallback(nullptr, nullptr, 0); return true; } |
|
|
|
|
|
|
|
if (samplesExpectedOut != 0 || !sourceProfileSupported()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
callback(context, {SourceKind::Invalid, samplesExpectedOut != 0 ? SourceError::LateAttach : SourceError::Profile}); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
pTDStretch->setSourceCallback(callback, context, (unsigned)pRateTransposer->unitySourceOffset()); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Get SoundTouch library version string
|
|
|
|
/// Get SoundTouch library version string
|
|
|
|
const char *SoundTouch::getVersionString() |
|
|
|
const char *SoundTouch::getVersionString() |
|
|
|
@ -139,6 +161,8 @@ void SoundTouch::setChannels(uint numChannels) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!verifyNumberOfChannels(numChannels)) return; |
|
|
|
if (!verifyNumberOfChannels(numChannels)) return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (samplesExpectedOut != 0) pTDStretch->invalidateSource(SourceError::Reconfigure); |
|
|
|
|
|
|
|
|
|
|
|
channels = numChannels; |
|
|
|
channels = numChannels; |
|
|
|
pRateTransposer->setChannels((int)numChannels); |
|
|
|
pRateTransposer->setChannels((int)numChannels); |
|
|
|
pTDStretch->setChannels((int)numChannels); |
|
|
|
pTDStretch->setChannels((int)numChannels); |
|
|
|
@ -223,6 +247,8 @@ void SoundTouch::calcEffectiveRateAndTempo() |
|
|
|
tempo = virtualTempo / virtualPitch; |
|
|
|
tempo = virtualTempo / virtualPitch; |
|
|
|
rate = virtualPitch * virtualRate; |
|
|
|
rate = virtualPitch * virtualRate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (rate != 1.0 || virtualPitch != 1.0) pTDStretch->invalidateSource(SourceError::Profile); |
|
|
|
|
|
|
|
|
|
|
|
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); |
|
|
|
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); |
|
|
|
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); |
|
|
|
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); |
|
|
|
|
|
|
|
|
|
|
|
@ -266,6 +292,7 @@ void SoundTouch::calcEffectiveRateAndTempo() |
|
|
|
// Sets sample rate.
|
|
|
|
// Sets sample rate.
|
|
|
|
void SoundTouch::setSampleRate(uint srate) |
|
|
|
void SoundTouch::setSampleRate(uint srate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (samplesExpectedOut != 0) pTDStretch->invalidateSource(SourceError::Reconfigure); |
|
|
|
// set sample rate, leave other tempo changer parameters as they are.
|
|
|
|
// set sample rate, leave other tempo changer parameters as they are.
|
|
|
|
pTDStretch->setParameters((int)srate); |
|
|
|
pTDStretch->setParameters((int)srate); |
|
|
|
bSrateSet = true; |
|
|
|
bSrateSet = true; |
|
|
|
@ -285,6 +312,8 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) |
|
|
|
ST_THROW_RT_ERROR("SoundTouch : Number of channels not defined"); |
|
|
|
ST_THROW_RT_ERROR("SoundTouch : Number of channels not defined"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!sourceProfileSupported()) pTDStretch->invalidateSource(SourceError::Profile); |
|
|
|
|
|
|
|
|
|
|
|
// accumulate how many samples are expected out from processing, given the current
|
|
|
|
// accumulate how many samples are expected out from processing, given the current
|
|
|
|
// processing setting
|
|
|
|
// processing setting
|
|
|
|
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo); |
|
|
|
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo); |
|
|
|
@ -317,6 +346,8 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) |
|
|
|
// in the middle of a sound stream.
|
|
|
|
// in the middle of a sound stream.
|
|
|
|
void SoundTouch::flush() |
|
|
|
void SoundTouch::flush() |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
// Padding и обрезка финального выхода не входят в контракт live-карты.
|
|
|
|
|
|
|
|
pTDStretch->invalidateSource(SourceError::Flush); |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
int numStillExpected; |
|
|
|
int numStillExpected; |
|
|
|
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels]; |
|
|
|
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels]; |
|
|
|
@ -350,6 +381,8 @@ void SoundTouch::flush() |
|
|
|
// 'SETTING_...' defines for available setting ID's.
|
|
|
|
// 'SETTING_...' defines for available setting ID's.
|
|
|
|
bool SoundTouch::setSetting(int settingId, int value) |
|
|
|
bool SoundTouch::setSetting(int settingId, int value) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (samplesExpectedOut != 0 && settingId != SETTING_USE_QUICKSEEK) |
|
|
|
|
|
|
|
pTDStretch->invalidateSource(SourceError::Reconfigure); |
|
|
|
int sampleRate, sequenceMs, seekWindowMs, overlapMs; |
|
|
|
int sampleRate, sequenceMs, seekWindowMs, overlapMs; |
|
|
|
|
|
|
|
|
|
|
|
// read current tdstretch routine parameters
|
|
|
|
// read current tdstretch routine parameters
|
|
|
|
|