-
Notifications
You must be signed in to change notification settings - Fork 236
Description
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
When I tested the Song "Rise" by Extreme once more on both next.js with webpack 1.8.1 and alphaTab 1.8.1 and also on vite by using the repo testing courtesy of LouisLam during a Loop test M4-M5 on track 1 guitar. I could see the cursor pause and/or hear a split second pause in the audio each and every time.
When using api.isLooping = true, AlphaTab overshoots the loop boundary by ~10–20 ticks before resetting to startTick.
This produces:
• Audible hiccup / micro pause at loop boundary
• Console spam: No beat found for tick XXXXX
• Occurs even with:
• No percussion
• No repeat expansion
• No custom cursor
• Workers disabled
• Minimal integration
This appears to be core playback engine behavior, not app-level logic.
Observed Behavior
Example loop:
startTick: 11520
endTick: 19200
Backward scan shows:
Last valid beat before endTick: 19190
Logs during playback:
Current Playback Tick: 19190
Current Playback Tick: 19203
Current Playback Tick: 19210
...
...
Jump back to 11520
There is a consistent 10–20 tick “dead zone” past the last valid beat before the internal loop reset occurs.
At high 179 BPM this produces a clear audible glitch.
See public video here:
https://youtu.be/uzPt0MyM1KA
Expected Behavior
When api.isLooping = true, playback should:
• Wrap cleanly at the last valid beat boundary
• Never enter an invalid tick region
• Avoid any audible pause or buffer stall
Looping should be proactive, not reactive.
Request
Would it be possible to:
1. Adjust internal looping to wrap at the last valid beat instead of at endTick?
2. Or implement a proactive boundary guard internally?
3. Or expose a lower-level loop boundary callback before the invalid region is entered?
If you need another stand alone repo for this I can get that for you.
Steps To Reproduce
And/or
git clone https://github.com/louislam/its-mytabs
cd its-mytabs
git checkout dev-alphatab181
deno task setup
deno task start
- Load my repo or LouisLam Repo and add the Extreme Rise - GP5 file. My repo already has it but it can be tested and duplicated on the Vite system as well.
- Load "Rise" Gp5
- Loop or Manual Loop M4-M5 press play
- As seen in the video you will get the same pause at the end of the Loop.
Isolation Steps Performed
The hiccup persists after eliminating:
• ❌ Percussion track state changes
• ❌ Repeat expansion logic
• ❌ Custom cursor interpolation
• ❌ boundsLookup.findBeat() calls
• ❌ Overlay logic
• ❌ Worker thread scheduling (useWorkers = false)
• ❌ All playerPositionChanged listeners
Even with:
api.settings.player.enableCursor = false;
api.cursorHandler = null;
api.settings.core.useWorkers = false;
The hiccup still occurs when api.isLooping = true.
Note: My current alphaTab Labs repo does not have an actual Loop system on that version I don't think, so it might be easier to just load that file onto LouisLam repo for testing via the Top Tabs Button on the top of the screen.
Link to jsFiddle, CodePen, Project
No response
Version and Environment
Environment
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: 1036x851
• AlphaTab: 1.8.1 (Same for Webpack version)
• Rendering mode: SVG
• Tested with:
• Maestro-AI (custom integration)
• LouisLam alphaTab implementation
• Multiple GP5 files (e.g. Rise, No More Tears, Bass-only files)
• BPM where issue is most noticeable: ≥ 160 BPM
• Workers: Tested with both useWorkers = true and false
• Custom cursor: Disabled during isolation
• Internal cursor: Disabled during isolationPlatform
Web
Anything else?
Root Cause Hypothesis
AlphaTab’s internal looping logic is reactive:
1. Playback continues until tick >= endTick
2. Engine then resets to startTick
3. During this boundary window, playback enters a region where:
• No beat exists in tick cache
• Engine attempts beat lookup
• Buffer refill / sequencing causes stall
This causes the audible pause.
The internal wrap occurs after the boundary is hit, rather than proactively before entering the invalid region.
⸻
Verified Workaround (Proactive Manual Wrap)
Disabling internal looping and manually wrapping before boundary eliminates the hiccup completely:
const start = api.playbackRange.startTick;
const endExclusive = api.playbackRange.endTick;
const endGuard = endExclusive - 10; // pre-empt overshoot
api.isLooping = false;
api.playerPositionChanged.on(e => {
const t = e.currentTick ?? e.tickPosition;
if (t >= endGuard) {
api.tickPosition = start;
}
});
Result:
• Zero hiccup
• No console spam
• Perfect audio continuity
• Works with workers enabled or disabled
This suggests the issue is specifically within the internal loop boundary logic.
Additional Notes
This behavior is reproducible across:
• Multiple GP5 files
• Multiple apps
• Multiple integrations
It is independent of:
• File content
• Repeat structure
• Rendering load
• Worker threading
This appears to be core playback scheduling logic.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status