Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/sanear.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marsev <alex.marsev@gmail.com>2016-02-23 11:46:49 +0300
committerAlex Marsev <alex.marsev@gmail.com>2016-02-24 13:14:35 +0300
commitdf53e0d614344245932dc90c7960a0f8a42a9979 (patch)
tree8c469cfe92cc5965de3f707bc01329a444ab52db
parent377ab1f272dbf480dbd26fb63a221b6aa776e30e (diff)
Defeat initial clock jitter for custom rates
-rw-r--r--src/AudioDevice.h1
-rw-r--r--src/AudioRenderer.cpp55
-rw-r--r--src/AudioRenderer.h2
3 files changed, 58 insertions, 0 deletions
diff --git a/src/AudioDevice.h b/src/AudioDevice.h
index 2617ca4..e78f06f 100644
--- a/src/AudioDevice.h
+++ b/src/AudioDevice.h
@@ -67,6 +67,7 @@ namespace SaneAudioRenderer
REFERENCE_TIME GetStreamLatency() const { return m_backend->deviceLatency; }
bool IsExclusive() const { return m_backend->exclusive; }
+ bool IsRealtime() const { return m_backend->realtime; }
bool IgnoredSystemChannelMixer() const { return m_backend->ignoredSystemChannelMixer; }
diff --git a/src/AudioRenderer.cpp b/src/AudioRenderer.cpp
index 7c28567..b8cf2fc 100644
--- a/src/AudioRenderer.cpp
+++ b/src/AudioRenderer.cpp
@@ -84,6 +84,28 @@ namespace SaneAudioRenderer
// Establish time/frame relation.
chunk = m_sampleCorrection.ProcessSample(pSample, sampleProps, m_live || m_externalClock);
+ // Drop frames if requested.
+ if (m_dropNextFrames > 0 && !chunk.IsEmpty())
+ {
+ assert(!IsBitstreaming());
+
+ const size_t chunkFrames = chunk.GetFrameCount();
+
+ if (m_dropNextFrames >= chunkFrames)
+ {
+ DebugOut(ClassName(this), "dropping", chunkFrames, "frames");
+ m_dropNextFrames -= chunkFrames;
+ chunk = DspChunk();
+ assert(chunk.IsEmpty());
+ }
+ else
+ {
+ DebugOut(ClassName(this), "dropping", m_dropNextFrames, "frames");
+ chunk.ShrinkHead(chunkFrames - m_dropNextFrames);
+ m_dropNextFrames = 0;
+ }
+ }
+
// Apply clock corrections.
if (!m_live && m_device && m_state == State_Running)
ApplyClockCorrection();
@@ -220,6 +242,7 @@ namespace SaneAudioRenderer
m_myClock.UnslaveClockFromAudio();
m_device->Stop();
m_device->Reset();
+ m_dropNextFrames = 0;
m_sampleCorrection.NewDeviceBuffer();
InitializeProcessors();
m_startClockOffset = m_sampleCorrection.GetLastFrameEnd();
@@ -229,6 +252,7 @@ namespace SaneAudioRenderer
else
{
m_device->Reset();
+ m_dropNextFrames = 0;
m_sampleCorrection.NewDeviceBuffer();
InitializeProcessors();
}
@@ -506,6 +530,35 @@ namespace SaneAudioRenderer
else if (m_sampleCorrection.GetLastFrameEnd() == 0)
{
DebugOut(ClassName(this), "empty start");
+ const uint32_t rate = m_device->GetWaveFormat()->nSamplesPerSec;
+
+ if (!m_bitstreaming && !m_device->IsRealtime())
+ {
+ size_t silenceFrames = rate * m_device->GetBufferDuration() / 5000; // Buffer / 5
+
+ DspChunk chunk = DspChunk(m_device->GetDspFormat(), m_device->GetWaveFormat()->nChannels,
+ silenceFrames, rate);
+ ZeroMemory(chunk.GetData(), chunk.GetSize());
+
+ DebugOut(ClassName(this), "pushing", silenceFrames, "frames of silence");
+ m_device->Push(chunk, nullptr);
+
+ m_startClockOffset -= llMulDiv(silenceFrames, OneSecond, rate, 0);
+
+ jitter = EstimateSlavingJitter();
+ }
+
+ if (!m_bitstreaming && jitter < 0)
+ {
+ m_dropNextFrames = (size_t)llMulDiv(-jitter, rate, OneSecond, 0);
+
+ if (m_dropNextFrames > 0)
+ {
+ DebugOut(ClassName(this), "will be dropping next", m_dropNextFrames, "frames");
+ m_startClockOffset += llMulDiv(m_dropNextFrames, OneSecond, rate, 0);
+ jitter = EstimateSlavingJitter();
+ }
+ }
}
DebugOut(ClassName(this), "predicting approx", jitter / 10000., "ms slaving jitter");
@@ -571,6 +624,8 @@ namespace SaneAudioRenderer
}
m_device = nullptr;
}
+
+ m_dropNextFrames = 0;
}
REFERENCE_TIME AudioRenderer::EstimateSlavingJitter()
diff --git a/src/AudioRenderer.h b/src/AudioRenderer.h
index aff003f..c082cf1 100644
--- a/src/AudioRenderer.h
+++ b/src/AudioRenderer.h
@@ -146,5 +146,7 @@ namespace SaneAudioRenderer
std::atomic<REFERENCE_TIME> m_guidedReclockOffset = 0;
bool m_guidedReclockActive = false;
+
+ size_t m_dropNextFrames = 0;
};
}