@@ -4,6 +4,26 @@ import { MidiUtils } from '@src/midi/MidiUtils';
44import { Beat } from '@src/model/Beat' ;
55import { MasterBar } from '@src/model/MasterBar' ;
66
7+ /**
8+ * Describes how a cursor should be moving.
9+ */
10+ export enum MidiTickLookupFindBeatResultCursorMode {
11+ /**
12+ * Unknown/Undetermined mode. Should not happen on user level.
13+ */
14+ Unknown ,
15+
16+ /**
17+ * The cursor should animate to the next beat.
18+ */
19+ ToNextBext ,
20+
21+ /**
22+ * The cursor should animate to the end of the bar (typically on repeats and jumps)
23+ */
24+ ToEndOfBar
25+ }
26+
727/**
828 * Represents the results of searching the currently played beat.
929 * @see MidiTickLookup.FindBeat
@@ -40,6 +60,11 @@ export class MidiTickLookupFindBeatResult {
4060 */
4161 public duration : number = 0 ;
4262
63+ /**
64+ * The mode how the cursor should be handled.
65+ */
66+ public cursorMode : MidiTickLookupFindBeatResultCursorMode = MidiTickLookupFindBeatResultCursorMode . Unknown ;
67+
4368 public get start ( ) : number {
4469 return this . masterBar . start + this . beatLookup . start ;
4570 }
@@ -57,7 +82,7 @@ export class MidiTickLookupFindBeatResult {
5782 if ( this . masterBar . tempoChanges . length === 1 ) {
5883 this . duration = MidiUtils . ticksToMillis ( this . tickDuration , this . masterBar . tempoChanges [ 0 ] . tempo ) ;
5984 } else {
60- // Performance Note: I still wonder if we cannot calculate these slices efficiently ahead-of-time.
85+ // Performance Note: I still wonder if we cannot calculate these slices efficiently ahead-of-time.
6186 // the sub-slicing in the lookup across beats makes it a bit tricky to do on-the-fly
6287 // but maybe on finalizing the tick lookup?
6388
@@ -77,7 +102,7 @@ export class MidiTickLookupFindBeatResult {
77102 // next change is after beat, we can stop looking at changes
78103 else if ( change . tick > endTick ) {
79104 break ;
80- }
105+ }
81106 // change while beat is playing
82107 else {
83108 millis += MidiUtils . ticksToMillis ( change . tick - currentTick , currentTempo ) ;
@@ -87,7 +112,7 @@ export class MidiTickLookupFindBeatResult {
87112 }
88113
89114 // last slice
90- if ( endTick > currentTick ) {
115+ if ( endTick > currentTick ) {
91116 millis += MidiUtils . ticksToMillis ( endTick - currentTick , currentTempo ) ;
92117 }
93118
@@ -199,7 +224,6 @@ export class MidiTickLookup {
199224 current . beatLookup . nextBeat ,
200225 current . end ,
201226 trackLookup ,
202- false ,
203227 true
204228 ) ;
205229
@@ -210,14 +234,29 @@ export class MidiTickLookup {
210234 // if we have the next beat take the difference between the times as duration
211235 if ( current . nextBeat ) {
212236 current . tickDuration = current . nextBeat . start - current . start ;
237+ current . cursorMode = MidiTickLookupFindBeatResultCursorMode . ToNextBext ;
213238 current . calculateDuration ( ) ;
214239 }
215240
216241 // no next beat, animate to the end of the bar (could be an incomplete bar)
217242 if ( ! current . nextBeat ) {
218243 current . tickDuration = current . masterBar . end - current . start ;
244+ current . cursorMode = MidiTickLookupFindBeatResultCursorMode . ToEndOfBar ;
219245 current . calculateDuration ( ) ;
220246 }
247+
248+ // if the next beat is not directly the next master bar (e.g. jumping back or forth)
249+ // we report no next beat and animate to the end
250+ if (
251+ current . nextBeat &&
252+ current . nextBeat . masterBar . masterBar . index != current . masterBar . masterBar . index + 1 &&
253+ (
254+ current . nextBeat . masterBar . masterBar . index != current . masterBar . masterBar . index ||
255+ current . nextBeat . beat . playbackStart <= current . beat . playbackStart
256+ )
257+ ) {
258+ current . cursorMode = MidiTickLookupFindBeatResultCursorMode . ToEndOfBar ;
259+ }
221260 }
222261
223262 private findBeatSlow (
@@ -261,7 +300,6 @@ export class MidiTickLookup {
261300 masterBar . firstBeat ,
262301 tick ,
263302 trackLookup ,
264- true ,
265303 isNextSearch
266304 ) ;
267305
@@ -282,16 +320,15 @@ export class MidiTickLookup {
282320 * @param currentStartLookup
283321 * @param tick
284322 * @param visibleTracks
285- * @param fillNext
323+ * @param isNextSearch
286324 * @returns
287325 */
288326 private findBeatInMasterBar (
289327 masterBar : MasterBarTickLookup ,
290328 currentStartLookup : BeatTickLookup | null ,
291329 tick : number ,
292330 visibleTracks : Set < number > ,
293- fillNext : boolean ,
294- isNextSeach : boolean
331+ isNextSearch : boolean
295332 ) : MidiTickLookupFindBeatResult | null {
296333 if ( ! currentStartLookup ) {
297334 return null ;
@@ -310,7 +347,7 @@ export class MidiTickLookup {
310347 // found the matching beat lookup but none of the beats are visible
311348 // in this case scan further to the next lookup which has any visible beat
312349 if ( ! startBeat ) {
313- if ( isNextSeach ) {
350+ if ( isNextSearch ) {
314351 let currentMasterBar : MasterBarTickLookup | null = masterBar ;
315352 while ( currentMasterBar != null && startBeat == null ) {
316353 while ( currentStartLookup != null ) {
@@ -363,7 +400,7 @@ export class MidiTickLookup {
363400 return null ;
364401 }
365402
366- const result = this . createResult ( masterBar , startBeatLookup ! , startBeat , fillNext , visibleTracks ) ;
403+ const result = this . createResult ( masterBar , startBeatLookup ! , startBeat , isNextSearch , visibleTracks ) ;
367404
368405 return result ;
369406 }
@@ -372,7 +409,7 @@ export class MidiTickLookup {
372409 masterBar : MasterBarTickLookup ,
373410 beatLookup : BeatTickLookup ,
374411 beat : Beat ,
375- fillNext : boolean ,
412+ isNextSearch : boolean ,
376413 visibleTracks : Set < number >
377414 ) {
378415 const result = new MidiTickLookupFindBeatResult ( masterBar ) ;
@@ -382,7 +419,7 @@ export class MidiTickLookup {
382419
383420 result . tickDuration = beatLookup ! . end - beatLookup ! . start ;
384421
385- if ( fillNext ) {
422+ if ( ! isNextSearch ) {
386423 this . fillNextBeat ( result , visibleTracks ) ;
387424 }
388425
0 commit comments