Skip to content

Fix VST sync when playback is paused#8352

Open
dyshin-uin wants to merge 1 commit intoLMMS:masterfrom
dyshin-uin:fix-issue-8343
Open

Fix VST sync when playback is paused#8352
dyshin-uin wants to merge 1 commit intoLMMS:masterfrom
dyshin-uin:fix-issue-8343

Conversation

@dyshin-uin
Copy link
Copy Markdown

Resolves #8343

Bug Summary:
When playback is paused, VST plugins loaded via VeSTige lose synchronization with the host's timeline. Specifically, m_currentSamplePos in RemoteVstPlugin continuously increments by bufferSize() regardless of playback state, pushing incorrect and constantly advancing time information to the VST.

Additionally, when the user drags the playhead on the LMMS timeline while playback is stopped, VstSyncController was not being updated, preventing the VST from receiving the new timeline position (Bars/Beats).

Changes Made:

  1. plugins/VstBase/RemoteVstPlugin.cpp:

    • Replaced the hardcoded m_currentSamplePos += bufferSize() increment with an absolute timeline calculation derived from syncData->ppqPos and bpm.
    • VSTs now receive geometrically accurate samplePos values tied to the timeline instead of raw frame accumulation.
  2. src/core/Song.cpp:

    • Modified Timeline::positionJumped to update m_vstSyncController.setAbsolutePosition(...) even when playback is paused / !m_playing.
    • This ensures VST plugins immediately snap to the correct Bar and Beat when the user seeks through the song editor's timeline while the transport is stopped.

@AW1534
Copy link
Copy Markdown
Member

AW1534 commented Apr 9, 2026

Copy link
Copy Markdown
Member

@AW1534 AW1534 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM

@messmerd
Copy link
Copy Markdown
Member

messmerd commented Apr 9, 2026

@AW1534 In your "After" recording, it appears the current bar (BBT) still isn't working correctly. When you drag the play head, the current bar in the display does not follow - it snaps back to the beginning.

@AW1534
Copy link
Copy Markdown
Member

AW1534 commented Apr 9, 2026

@AW1534 In your "After" recording, it appears the current bar (BBT) still isn't working correctly. When you drag the play head, the current bar in the display does not follow - it snaps back to the beginning.

I see that now. Although the frame and time are working as expected, I had ignored BBT because I was unsure what it was and wrongfully assumed it would be derived purely from frame, similarly to how time is.

Okay so after a little research, it appears on the Carla vst2 host, BBT is derived from the bar start position and PPQ (Position in quarter notes). Also, the kVstPpqPosValid flag needs to be set. Judging by the fact that the BBT was also broken in the same way before the PR, I’m assuming the bar start position and/or PPQ aren’t being sent or aren’t being sent correctly. Judging by the nature of the bug, my gut says PPQ is what’s causing this.

Anywho, since this doesn’t seem to be a regression and at least improves the frame based transport, I think it’s fair to merge this PR and open a separate issue (or issues), rather than inflating the scope of this PR?

Comment thread src/core/Song.cpp
Comment on lines +129 to +137

// Update VST plugins with the new position so they stay in sync when skipping around,
// even when playback is paused.
if ((m_playing && m_playMode == playMode) || (!m_playing)) {
const auto& tl = m_timelines[static_cast<std::size_t>(playMode)];
m_vstSyncController.setAbsolutePosition(
tl.ticks() + tl.frameOffset() / static_cast<double>(Engine::framesPerTick())
);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@regulus79 @sakertooth I'm going to run an idea by you two about how we could fix this problem more robustly.

For VST sync, from what I've gathered from this PR, it apparently needs to function the same regardless of whether the song is playing or not. But according to the comment a few lines above here, we've restricted the playbackPositionJumped signal emission to when the song is playing due to how the LFOs work.

My idea is that we remove the restriction on emitting the signal only while the song is playing since that is unintuitive for anyone relying on that signal (and LFOs are not the responsibility of Song), then in the LFO's slot we could add an early return if the song is not playing when it receives the position jumped signal (fixing the problem with the LFOs), and then VST sync would work even when the song is not playing.

And maybe we could also remove the connect() a few lines below this since it involves the Song connecting to its own signal, which seems very strange. Maybe something like this would work instead:

const auto onPositionJumped = [this, playMode = static_cast<PlayMode>(i)] {
	// Only emit the signal when the active timeline jumps
	if (m_playMode == playMode)
	{
		emit playbackPositionJumped();

		m_vstSyncController.setPlaybackJumped(true);
		const auto& tl = getTimeline(playMode);
		m_vstSyncController.setAbsolutePosition(
			tl.ticks() + tl.frameOffset() / static_cast<double>(Engine::framesPerTick())
		);
	}
};

connect(&m_timelines[i], &Timeline::positionJumped, this, onPositionJumped);

(NOTE: I haven't tested this yet)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that solution sounds reasonable. The nested logic within the lambda and the connect never felt quite right to me, although maybe it's fine if it's not too complex. Putting the responsibility of checking whether the song is playing on the LFO sounds like it would make Song simpler, which is good.

@messmerd messmerd changed the title Fix time information sent to VST when playback is paused (fixes #8343) Fix VST sync when playback is paused Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Correct time information is not being sent to the VST

4 participants