Browse Source

Expose optional live source tracking through SoundTouch

master
evgeny 4 days ago
parent
commit
1d43578335
  1. 10
      lib/soundtouch-master/include/soundtouch/SoundTouch.h
  2. 33
      lib/soundtouch-master/source/SoundTouch/SoundTouch.cpp

10
lib/soundtouch-master/include/soundtouch/SoundTouch.h

@ -67,6 +67,7 @@
#include "FIFOSamplePipe.h" #include "FIFOSamplePipe.h"
#include "STTypes.h" #include "STTypes.h"
#include "SourceSpan.h"
namespace soundtouch namespace soundtouch
{ {
@ -197,6 +198,8 @@ private:
/// 'virtualPitch' parameters. /// 'virtualPitch' parameters.
void calcEffectiveRateAndTempo(); void calcEffectiveRateAndTempo();
bool sourceProfileSupported() const;
protected : protected :
/// Number of channels /// Number of channels
uint channels; uint channels;
@ -211,6 +214,13 @@ public:
SoundTouch(); SoundTouch();
~SoundTouch() override; ~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 /// Get SoundTouch library version string
static const char *getVersionString(); static const char *getVersionString();

33
lib/soundtouch-master/source/SoundTouch/SoundTouch.cpp

@ -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

Loading…
Cancel
Save