Expose optional live source tracking through SoundTouch

This commit is contained in:
evgeny committed 2026-10-14 19:16:45 +02:00
1 parent edcd34d942
commit 1d43578335
2 files changed
+43

No files matched your search

@@ -67,6 +67,7 @@
#include "FIFOSamplePipe.h"
#include "STTypes.h"
#include "SourceSpan.h"
namespace soundtouch
{
@@ -197,6 +198,8 @@ private:
/// 'virtualPitch' parameters.
void calcEffectiveRateAndTempo();
bool sourceProfileSupported() const;
protected :
/// Number of channels
uint channels;
@@ -211,6 +214,13 @@ public:
SoundTouch();
~SoundTouch() override;
/* uTun: подключать после настройки, до первого putSamples либо после clear.
* Поддерживается float PCM, unity pitch/rate, cubic interpolation, AA off, mono/stereo.
* Ошибка сообщает Invalid и возвращает false. Изменение профиля после начала и flush
* инвалидируют карту; clear начинает новую. nullptr отключает события в любой момент.
* События описывают произведённый выход, включая ещё не прочитанные receiveSamples данные. */
bool setSourceCallback(SourceCallback callback, void* context);
/// Get SoundTouch library version string
static const char *getVersionString();
@@ -117,6 +117,28 @@ SoundTouch::~SoundTouch()
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
const char *SoundTouch::getVersionString()
@@ -139,6 +161,8 @@ void SoundTouch::setChannels(uint numChannels)
{
if (!verifyNumberOfChannels(numChannels)) return;
if (samplesExpectedOut != 0) pTDStretch->invalidateSource(SourceError::Reconfigure);
channels = numChannels;
pRateTransposer->setChannels((int)numChannels);
pTDStretch->setChannels((int)numChannels);
@@ -223,6 +247,8 @@ void SoundTouch::calcEffectiveRateAndTempo()
tempo = virtualTempo / virtualPitch;
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(tempo, oldTempo)) pTDStretch->setTempo(tempo);
@@ -266,6 +292,7 @@ void SoundTouch::calcEffectiveRateAndTempo()
// Sets sample rate.
void SoundTouch::setSampleRate(uint srate)
{
if (samplesExpectedOut != 0) pTDStretch->invalidateSource(SourceError::Reconfigure);
// set sample rate, leave other tempo changer parameters as they are.
pTDStretch->setParameters((int)srate);
bSrateSet = true;
@@ -285,6 +312,8 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
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
// processing setting
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.
void SoundTouch::flush()
{
// Padding и обрезка финального выхода не входят в контракт live-карты.
pTDStretch->invalidateSource(SourceError::Flush);
int i;
int numStillExpected;
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
@@ -350,6 +381,8 @@ void SoundTouch::flush()
// 'SETTING_...' defines for available setting ID's.
bool SoundTouch::setSetting(int settingId, int value)
{
if (samplesExpectedOut != 0 && settingId != SETTING_USE_QUICKSEEK)
pTDStretch->invalidateSource(SourceError::Reconfigure);
int sampleRate, sequenceMs, seekWindowMs, overlapMs;
// read current tdstretch routine parameters