@@ -153,6 +153,10 @@ class Singer {
153153 this . tieFirstDrums = [ ] ;
154154 this . synthVolume = { } ;
155155 this . drift = 0 ;
156+ // Maximum fraction of note duration that can be used for lag correction per note.
157+ // This prevents notes from being rushed when catching up to the master clock.
158+ // Value of 0.25 means at most 25% of a note's duration can be skipped for catch-up.
159+ this . maxLagCorrectionRatio = 0.25 ;
156160 this . drumStyle = [ ] ;
157161 this . voices = [ ] ;
158162 this . backward = [ ] ;
@@ -1569,8 +1573,18 @@ class Singer {
15691573 const elapsedTime = ( new Date ( ) . getTime ( ) - activity . logo . firstNoteTime ) / 1000 ;
15701574
15711575 // When we are "drifting", we don't bother with lag.
1572- const turtleLag =
1573- tur . singer . drift === 0 ? Math . max ( elapsedTime - tur . singer . turtleTime , 0 ) : 0 ;
1576+ // When not drifting, we limit the lag correction to prevent notes from being rushed.
1577+ // This ensures that note sequences play correctly even when the system is behind.
1578+ let turtleLag = 0 ;
1579+ if ( tur . singer . drift === 0 ) {
1580+ const rawLag = Math . max ( elapsedTime - tur . singer . turtleTime , 0 ) ;
1581+ // Calculate the maximum lag correction allowed for this note
1582+ // based on the note's duration to prevent rushing
1583+ const noteDuration = bpmFactor / noteBeatValue ;
1584+ const maxLagCorrection = noteDuration * tur . singer . maxLagCorrectionRatio ;
1585+ // Apply gradual lag correction: correct at most maxLagCorrection per note
1586+ turtleLag = Math . min ( rawLag , maxLagCorrection ) ;
1587+ }
15741588
15751589 // Delay running graphics from second note in tie.
15761590 let tieDelay = tur . singer . tie ? tur . singer . tieCarryOver : 0 ;
0 commit comments