diff --git a/Source/AlphaTab/AlphaTabApi.cs b/Source/AlphaTab/AlphaTabApi.cs
index 56c0902ef..3bec2f0c8 100644
--- a/Source/AlphaTab/AlphaTabApi.cs
+++ b/Source/AlphaTab/AlphaTabApi.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using AlphaTab.Audio;
using AlphaTab.Audio.Generator;
using AlphaTab.Audio.Synth;
@@ -916,7 +917,7 @@ private void CursorUpdateTick(int tick, bool stop = false)
var beat = cache.FindBeat(tracks, tick);
if (beat != null)
{
- CursorUpdateBeat(beat.CurrentBeat, beat.NextBeat, beat.Duration, stop);
+ CursorUpdateBeat(beat.CurrentBeat, beat.NextBeat, beat.Duration, stop, beat.BeatsToHighlight);
}
}
}
@@ -926,7 +927,12 @@ private void CursorUpdateTick(int tick, bool stop = false)
///
/// updates the cursors to highlight the specified beat
///
- private void CursorUpdateBeat(Beat beat, Beat nextBeat, double duration, bool stop)
+ private void CursorUpdateBeat(
+ Beat beat,
+ Beat nextBeat,
+ double duration,
+ bool stop,
+ FastList beatsToHighlight = null)
{
if (beat == null)
{
@@ -983,8 +989,14 @@ private void CursorUpdateBeat(Beat beat, Beat nextBeat, double duration, bool st
if (!stop)
{
- var className = BeatContainerGlyph.GetGroupId(beat);
- UiFacade.HighlightElements(className);
+ if (beatsToHighlight != null)
+ {
+ foreach (var highlight in beatsToHighlight)
+ {
+ var className = BeatContainerGlyph.GetGroupId(highlight);
+ UiFacade.HighlightElements(className);
+ }
+ }
var nextBeatX = barBoundings.VisualBounds.X + barBoundings.VisualBounds.W;
// get position of next beat on same stavegroup
diff --git a/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs b/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs
index 4255f1086..2584b5861 100644
--- a/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs
+++ b/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs
@@ -266,6 +266,7 @@ private void GenerateBeat(Beat beat, int barStartTick, Bar realBar)
? audioDuration
: beat.NextBeat.AbsolutePlaybackStart - beat.AbsolutePlaybackStart;
beatLookup.End = barStartTick + beatStart;
+ beatLookup.HighlightBeat(beat);
beatLookup.End += realTickOffset > audioDuration ? realTickOffset : audioDuration;
diff --git a/Source/AlphaTab/Audio/MidiTickLookup.cs b/Source/AlphaTab/Audio/MidiTickLookup.cs
index 4111646bc..12106b5d9 100644
--- a/Source/AlphaTab/Audio/MidiTickLookup.cs
+++ b/Source/AlphaTab/Audio/MidiTickLookup.cs
@@ -8,13 +8,15 @@ namespace AlphaTab.Audio
///
public class BeatTickLookup
{
+ private FastDictionary _highlightedBeats;
+
///
- /// Gets or sets the start time in midi ticks at which the given beat is played.
+ /// Gets or sets the start time in midi ticks at which the given beat is played.
///
public int Start { get; set; }
///
- /// Gets or sets the end time in midi ticks at which the given beat is played.
+ /// Gets or sets the end time in midi ticks at which the given beat is played.
///
public int End { get; set; }
@@ -24,9 +26,30 @@ public class BeatTickLookup
public Beat Beat { get; set; }
///
- /// Gets or sets whether the beat is the placeholder beat for an empty bar.
+ /// Gets or sets whether the beat is the placeholder beat for an empty bar.
///
public bool IsEmptyBar { get; set; }
+
+ ///
+ /// Gets or sets a list of all beats that should be highlighted when
+ /// the beat of this lookup starts playing.
+ ///
+ public FastList BeatsToHighlight { get; set; }
+
+ public BeatTickLookup()
+ {
+ _highlightedBeats = new FastDictionary();
+ BeatsToHighlight = new FastList();
+ }
+
+ public void HighlightBeat(Beat beat)
+ {
+ if (!_highlightedBeats.ContainsKey(beat.Id))
+ {
+ _highlightedBeats[beat.Id] = true;
+ BeatsToHighlight.Add(beat);
+ }
+ }
}
///
@@ -35,12 +58,12 @@ public class BeatTickLookup
public class MasterBarTickLookup
{
///
- /// Gets or sets the start time in midi ticks at which the MasterBar is played.
+ /// Gets or sets the start time in midi ticks at which the MasterBar is played.
///
public int Start { get; set; }
///
- /// Gets or sets the end time in midi ticks at which the MasterBar is played.
+ /// Gets or sets the end time in midi ticks at which the MasterBar is played.
///
public int End { get; set; }
@@ -50,13 +73,13 @@ public class MasterBarTickLookup
public int Tempo { get; set; }
///
- /// Gets or sets the MasterBar which is played.
+ /// Gets or sets the MasterBar which is played.
///
public MasterBar MasterBar { get; set; }
///
/// Gets or sets the list of object which define the durations
- /// for all played within the period of this MasterBar.
+ /// for all played within the period of this MasterBar.
///
public FastList Beats { get; set; }
@@ -75,7 +98,7 @@ public MasterBarTickLookup()
}
///
- /// Performs the neccessary finalization steps after all information was written.
+ /// Performs the neccessary finalization steps after all information was written.
///
public void Finish()
{
@@ -83,7 +106,7 @@ public void Finish()
}
///
- /// Adds a new to the list of played beats during this MasterBar period.
+ /// Adds a new to the list of played beats during this MasterBar period.
///
///
public void AddBeat(BeatTickLookup beat)
@@ -93,29 +116,34 @@ public void AddBeat(BeatTickLookup beat)
}
///
- /// Represents the results of searching the currently played beat.
+ /// Represents the results of searching the currently played beat.
///
///
public class MidiTickLookupFindBeatResult
{
///
- /// Gets or sets the beat that is currently played.
+ /// Gets or sets the beat that is currently played.
///
public Beat CurrentBeat { get; set; }
///
- /// Gets or sets the beat that will be played next.
+ /// Gets or sets the beat that will be played next.
///
public Beat NextBeat { get; set; }
///
- /// Gets or sets the duration in milliseconds how long this beat is playing.
+ /// Gets or sets the duration in milliseconds how long this beat is playing.
///
public int Duration { get; set; }
+
+ ///
+ /// Gets or sets the beats ot highlight along the current beat.
+ ///
+ public FastList BeatsToHighlight { get; set; }
}
///
- /// This class holds all information about when s and s are played.
+ /// This class holds all information about when s and s are played.
///
public class MidiTickLookup
{
@@ -130,7 +158,7 @@ public class MidiTickLookup
public FastDictionary MasterBarLookup { get; }
///
- /// Gets a list of all sorted by time.
+ /// Gets a list of all sorted by time.
///
public FastList MasterBars { get; }
@@ -144,11 +172,12 @@ public MidiTickLookup()
}
///
- /// Performs the neccessary finalization steps after all information was written.
+ /// Performs the neccessary finalization steps after all information was written.
///
public void Finish()
{
MasterBarTickLookup previous = null;
+ var activeBeats = new FastList();
foreach (var bar in MasterBars)
{
bar.Finish();
@@ -157,12 +186,36 @@ public void Finish()
previous.NextMasterBar = bar;
}
+ foreach (var beat in bar.Beats)
+ {
+ // 1. calculate newly which beats are still active
+ var newActiveBeats = new FastList();
+ // TODO: only create new list if current position changed
+ foreach (var activeBeat in activeBeats)
+ {
+ if (activeBeat.End > beat.Start)
+ {
+ newActiveBeats.Add(activeBeat);
+ // 2. remember for current beat which active beats to highlight
+ beat.HighlightBeat(activeBeat.Beat);
+ // 3. ensure that active beat highlights current beat if they match the range
+ if (beat.Start <= activeBeat.Start)
+ {
+ activeBeat.HighlightBeat(beat.Beat);
+ }
+ }
+ }
+
+ newActiveBeats.Add(beat);
+ activeBeats = newActiveBeats;
+ }
+
previous = bar;
}
}
///
- /// Finds the currently played beat given a list of tracks and the current time.
+ /// Finds the currently played beat given a list of tracks and the current time.
///
/// The tracks in which to search the played beat for.
/// The current time in midi ticks.
@@ -253,6 +306,7 @@ public MidiTickLookupFindBeatResult FindBeat(Track[] tracks, int tick)
result.Duration = nextBeat == null
? MidiUtils.TicksToMillis(beat.End - beat.Start, masterBar.Tempo)
: MidiUtils.TicksToMillis(nextBeat.Start - beat.Start, masterBar.Tempo);
+ result.BeatsToHighlight = beat.BeatsToHighlight;
return result;
}
@@ -273,7 +327,7 @@ private MasterBarTickLookup FindMasterBar(int tick)
return bar;
}
- // search in lower half
+ // search in lower half
if (tick < bar.Start)
{
top = middle - 1;
@@ -289,7 +343,7 @@ private MasterBarTickLookup FindMasterBar(int tick)
}
///
- /// Gets the for a given masterbar at which the masterbar is played the first time.
+ /// Gets the for a given masterbar at which the masterbar is played the first time.
///
/// The masterbar to find the time period for.
/// A containing the details about the first time the is played.
@@ -311,7 +365,7 @@ public MasterBarTickLookup GetMasterBar(MasterBar bar)
}
///
- /// Gets the start time in midi ticks for a given masterbar at which the masterbar is played the first time.
+ /// Gets the start time in midi ticks for a given masterbar at which the masterbar is played the first time.
///
/// The masterbar to find the time period for.
/// The time in midi ticks at which the masterbar is played the first time or 0 if the masterbar is not contained
@@ -327,7 +381,7 @@ public int GetMasterBarStart(MasterBar bar)
}
///
- /// Adds a new to the lookup table.
+ /// Adds a new to the lookup table.
///
/// The item to add.
public void AddMasterBar(MasterBarTickLookup masterBar)