From df54602a2a9a7e94d6c4b97fa783c0a61dd368de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 5 Jan 2024 08:20:51 +0100 Subject: [PATCH 1/4] VisualPlayPosition::calcOffsetAtNextVSync: Improve verbosity in case of clamping --- src/waveform/visualplayposition.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/waveform/visualplayposition.cpp b/src/waveform/visualplayposition.cpp index 973532ef0a7..b324ea07dce 100644 --- a/src/waveform/visualplayposition.cpp +++ b/src/waveform/visualplayposition.cpp @@ -76,7 +76,10 @@ double VisualPlayPosition::calcOffsetAtNextVSync( offset = -maxOffset; if (!m_noTransport) { qWarning() << "VisualPlayPosition::calcOffsetAtNextVSync" - << m_key << "no transport (offset < -maxOffset)"; + << m_key << "outdated position request (offset < minOffset)"; + qDebug() << m_key << "refToVSync:" << refToVSync + << "data.m_callbackEntrytoDac:" + << data.m_callbackEntrytoDac; m_noTransport = true; } } else if (offset > maxOffset) { @@ -84,9 +87,17 @@ double VisualPlayPosition::calcOffsetAtNextVSync( if (!m_noTransport) { qWarning() << "VisualPlayPosition::calcOffsetAtNextVSync" << m_key << "no transport (offset > maxOffset)"; + qDebug() << m_key << "refToVSync:" << refToVSync + << "data.m_callbackEntrytoDac:" + << data.m_callbackEntrytoDac; m_noTransport = true; } } else { + if (m_noTransport) { + qDebug() << m_key << "refToVSync:" << refToVSync + << "data.m_callbackEntrytoDac:" + << data.m_callbackEntrytoDac; + } m_noTransport = false; } // Apply the offset proportional to m_positionStep From d66e77309294c75ecf395f52a7fec0ac8f89c62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 5 Jan 2024 08:23:04 +0100 Subject: [PATCH 2/4] Adjust minimal offset limit to not prpagate outdated positions --- src/waveform/visualplayposition.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/waveform/visualplayposition.cpp b/src/waveform/visualplayposition.cpp index b324ea07dce..983f197c640 100644 --- a/src/waveform/visualplayposition.cpp +++ b/src/waveform/visualplayposition.cpp @@ -64,16 +64,22 @@ double VisualPlayPosition::calcOffsetAtNextVSync( const int refToVSync = pVSyncThread->fromTimerToNextSyncMicros(data.m_referenceTime); const int syncIntervalTimeMicros = pVSyncThread->getSyncIntervalTimeMicros(); #endif - // The offset is limited to the audio buffer + 2 x waveform sync interval + // The positive offset is limited to the audio buffer + 2 x waveform sync interval // This should be sufficient to compensate jitter, but does not continue // in case of underflows. const int maxOffset = static_cast( data.m_audioBufferMicroS + 2 * syncIntervalTimeMicros); + + // The negative offset is limited to -data.m_callbackEntrytoDac to not + // More negative values indicated an outdated request, that is anyway no + // longer valid. Probably cause bay a vsync issue. + const int minOffset = -data.m_callbackEntrytoDac; + // Calculate the offset in micros for the position of the sample that will be transferred // to the DAC when the next display frame is displayed int offset = refToVSync - data.m_callbackEntrytoDac; - if (offset < -maxOffset) { - offset = -maxOffset; + if (offset < minOffset) { + offset = minOffset; if (!m_noTransport) { qWarning() << "VisualPlayPosition::calcOffsetAtNextVSync" << m_key << "outdated position request (offset < minOffset)"; From 1361e7ef470c116c928b4a87ac8a1a1721a3e407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 7 Jan 2024 16:21:29 +0100 Subject: [PATCH 3/4] Don't request a visual playposition for an outdated frame --- src/waveform/vsyncthread.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/waveform/vsyncthread.cpp b/src/waveform/vsyncthread.cpp index 38c789fb320..a12496975aa 100644 --- a/src/waveform/vsyncthread.cpp +++ b/src/waveform/vsyncthread.cpp @@ -38,6 +38,8 @@ void VSyncThread::run() { //qDebug() << "VSyncThread::run()"; switch (m_vSyncMode) { case ST_FREE: + m_syncIntervalTimeMicros = 1000; + m_waitToSwapMicros = m_syncIntervalTimeMicros; runFree(); break; case ST_PLL: @@ -65,8 +67,7 @@ void VSyncThread::runFree() { m_semaVsyncSlot.acquire(); m_sinceLastSwap = m_timer.restart(); - m_waitToSwapMicros = 1000; - usleep(1000); + usleep(m_waitToSwapMicros); } } @@ -168,9 +169,11 @@ int VSyncThread::elapsed() { } void VSyncThread::setSyncIntervalTimeMicros(int syncTime) { - m_syncIntervalTimeMicros = syncTime; - m_vSyncPerRendering = static_cast( - round(m_displayFrameRate * m_syncIntervalTimeMicros / 1000)); + if (m_vSyncMode != ST_FREE) { + m_syncIntervalTimeMicros = syncTime; + m_vSyncPerRendering = static_cast( + round(m_displayFrameRate * m_syncIntervalTimeMicros / 1000)); + } } void VSyncThread::setVSyncType(int type) { @@ -187,7 +190,13 @@ void VSyncThread::setVSyncType(int type) { int VSyncThread::fromTimerToNextSyncMicros(const PerformanceTimer& timer) { int difference = static_cast(m_timer.difference(timer).toIntegerMicros()); // int math is fine here, because we do not expect times > 4.2 s - return difference + m_waitToSwapMicros; + int toNextSync = difference + m_waitToSwapMicros; + while (toNextSync < 0) { + // this function is called during rendering. A negative value indicates + // an attempt to render an outdated frame. Render the next frame instead + toNextSync += m_syncIntervalTimeMicros; + } + return toNextSync; } int VSyncThread::droppedFrames() { From 12f0bab1232220381e8097184ab9026ec821d0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Mon, 8 Jan 2024 08:55:34 +0100 Subject: [PATCH 4/4] improve description of minOffset --- src/waveform/visualplayposition.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/waveform/visualplayposition.cpp b/src/waveform/visualplayposition.cpp index 983f197c640..e99206a874a 100644 --- a/src/waveform/visualplayposition.cpp +++ b/src/waveform/visualplayposition.cpp @@ -70,9 +70,9 @@ double VisualPlayPosition::calcOffsetAtNextVSync( const int maxOffset = static_cast( data.m_audioBufferMicroS + 2 * syncIntervalTimeMicros); - // The negative offset is limited to -data.m_callbackEntrytoDac to not - // More negative values indicated an outdated request, that is anyway no - // longer valid. Probably cause bay a vsync issue. + // The minimum offset is limited to -data.m_callbackEntrytoDac to avoid a more + // negative value indicating an outdated request that is no longer valid anyway. + // This is probably caused by a vsync problem. const int minOffset = -data.m_callbackEntrytoDac; // Calculate the offset in micros for the position of the sample that will be transferred