Skip to content

GP5 with 3x repeats: tickCache.findBeat resolves to wrong (earlier) repeat pass after seek, causing playback/visual desync (“Extreme – Rise”) #2548

@AvaTheArchitect

Description

@AvaTheArchitect

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Tick-to-Beat Resolution Failure:

https://youtu.be/stt11W1L2OQ


When loading the GP5 file “Extreme – Rise” (contains a repeated section M25-M26, e.g. “3x repeat”), seeking to a tick (or click to seek) after the repeat section to M27. The custom cursor moves correctly to M27 (Default alphaTab Cursor and player thinks we clicked on M25) Press Play starts playback at the correct audio tick, but AlphaTab’s beat resolution/events continue to resolve to an earlier tick inside the repeat pass. This causes the cursor/beat mapping to “snap back” to the earlier pass while audio is playing the later position.

Evidence from logs (representative):
• Seek target: tick 695040 (M363)
• Audio starts: Player state: PLAYING … tick: 695041
• Beat lookup called with tick in the 695k range:
🎯 Beat lookup { playing: true, tickUsed: 695045, scope: 'all', found: true }
• But played beat/event is from earlier repeat pass:
⚖️ Timeline Correction (beatChanged) { audioTick: 695049, eventTick: 664320 }
• Resulting beat reported corresponds to earlier pass (≈tick 664k / M347), not the seek position.

The Conclusion:
AlphaTab's tickCache is collapsing the timeline. Even when provided with a unique playback tick that should correspond to the "second pass" of a repeat, the resolver is "snapping" back to the "first pass" coordinates. This creates a permanent mismatch between the Audio (playing at 695k) and the Visuals (rendered at 664k).

Expected Behavior

Default Cursor and Player should move to the click to seek start position (Example M27 and player and cursor should move and resume playback from this spot). It should maintain the normal mapping system logic needed to move and play normal:

After seeking to tick 695040, AlphaTab should:
• Play audio from the seeked position and
• Resolve beats/cursor position for the same playback timeline position (≈695k), not a prior repeat pass (≈664k).

tickCache.findBeat(trackIndices, 695045) should return a beat whose absolutePlaybackStart (or equivalent) is close to 695045, not ~664320.

Steps To Reproduce

  1. Load the GP5 file “Extreme – Rise” (has a repeat section, including “3x repeat” behavior). Start at M27 and watch where the cursor moves too.
    2. Start playback and/or allow the piece to progress so repeat behavior is active (optional, but issue reproduces after seek regardless).
    3. Seek/click to a position after the repeated section, e.g. tick ~695,040 (in our test UI this corresponds to measure ~363). or any measure from M27 to the end of the file and the behavior will be present anywhere.
    4. Press Play.
    5. Observe:
    • Audio plays from the seeked position (tick ~695k).
    • Beat resolution/events (playedBeatChanged / tickCache.findBeat results) resolve to an earlier tick inside the repeat pass (~664k), causing visual cursor/beat mapping to jump backward.

Link to jsFiddle, CodePen, Project

No response

Version and Environment

alphaTab 1.8.1
initAlphaTab.ts:206 
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) 
AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/144.0.0.0 
Safari/537.36
initAlphaTab.ts:207 
Screen: 1148x859

Platform

Web

Anything else?

I will work on getting some sample files for the repo tomorrow as well.

Metadata

Metadata

Assignees

Type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions