Setting for MIDI inner loop [Pro]. Look at MidiFilePlayer.MPTK_InnerLoop
Example: More...

Public Types

enum  InnerLoopPhase { Start , Resume , Exit }

Public Attributes

int Count
bool Enabled
long End
bool Finished
bool Log
int Max
Func< InnerLoopPhase, long, long, int, bool > OnEventInnerLoop
long Resume
long Start

Detailed Description

Setting for MIDI inner loop [Pro]. Look at MidiFilePlayer.MPTK_InnerLoop

// Full source code in TestInnerLoop.cs
// As usual with a MVP demo, focus is on the essentials:
// - no value check,
// - limited error catch,
// - no optimization,
// - limited functions
// - ...
// Contains a reference to the current InnerLoop instance, useful only for clarity in the demo ...
private MPTKInnerLoop innerLoop;
// Start is called before the first frame update
void Start()
// Find a MidiFilePlayer in the scene hierarchy
// (Innerloop works also with MidiExternalPlayer, see TestMidiGenerator.cs)
// ----------------------------------------------
midiFilePlayer = FindObjectOfType<MidiFilePlayer>();
if (midiFilePlayer == null)
Debug.LogWarning("Can't find a MidiFilePlayer Prefab in the current Scene Hierarchy. Add it with the Maestro menu.");
// Preload the MIDI file to be able to set MIDI attributes before playing.
// In particular MPTK_InnerLoop which is cleared when MIDI is loaded.
// Get a shortcut (for clarity) to the inner loop instance (instanciated in the awake phase of the MidiFilePlayer)
// You can also instanciate or manage your own references and set midiFilePlayer.MPTK_InnerLoop with your MPTKInnerLoop instance.
innerLoop = midiFilePlayer.MPTK_InnerLoop;
// No log for this demo, rather we prefer using a callback.
innerLoop.Log = false;
// Define C# event of type Func() for each loop phase change: Start --> Resume --> Resume --> ... -> Exit
// If return is false then looping can be earlier ended.
// It's also possible to set innerLoop.Finished to True at all places in your script
// but the loop will finished only when tickPlayer reaches the end of the loop.
innerLoop.OnEventInnerLoop = (MPTKInnerLoop.InnerLoopPhase mode, long tickPlayer, long tickSeek, int count) =>
Debug.Log($"Inner Loop {mode} - MPTK_TickPlayer:{tickPlayer} --> TickSeek:{tickSeek} Count:{count}/{innerLoop.Max}");
if (mode == MPTKInnerLoop.InnerLoopPhase.Exit)
// Set the value for the Unity User Interface to be able to reactivate the loop.
LoopFinished = true;
return true;
innerLoop.Enabled = true;
midiFilePlayer.MPTK_Play(alreadyLoaded: true);
// Update is called once per frame
void Update()
if (midiFilePlayer != null && midiFilePlayer.MPTK_MidiLoaded != null)
// Display current real-time tick value of the MIDI sequencer
TickPlayer = midiFilePlayer.MPTK_MidiLoaded.MPTK_TickPlayer;
// Display tick value of the last MIDI event read by the MIDI sequencer.
TickCurrent = midiFilePlayer.MPTK_MidiLoaded.MPTK_TickCurrent;
// Display current measure and beat value of the last MIDI event read by the MIDI sequencer.
MeasurePlayer = $"{midiFilePlayer.MPTK_MidiLoaded.MPTK_CurrentMeasure}.{midiFilePlayer.MPTK_MidiLoaded.MPTK_CurrentBeat} - Last measure: {midiFilePlayer.MPTK_MidiLoaded.MPTK_MeasureLastNote}";
// These parameters can be changed dynamically with the inspector
innerLoop.Max = LoopMax;
innerLoop.Start = TickStart;
innerLoop.Resume = TickResume;
innerLoop.End = TickEnd;
innerLoop.Finished = LoopFinished;
// These values are read from the inner loop instance and display on the UI.
loopEnabled = innerLoop.Enabled;
LoopCount = innerLoop.Count;
// Calculate tick position of a measure (just for a demo how to calculate tick from bar).
// So, it's easy to create loop based on measure.
Tick = MPTKSignature.MPTK_MeasureToTick(midiFilePlayer.MPTK_MidiLoaded.MPTK_SignMap, Measure);
// Add quarter. Beat start at the begin of the measure (Beat = 1).
Tick += (Quarter - 1) * midiFilePlayer.MPTK_DeltaTicksPerQuarterNote;
Setting for MIDI inner loop [Pro]. Look at MidiFilePlayer.MPTK_InnerLoop Example:
Definition: MPTKInnerLoop.cs:16
bool Enabled
Definition: MPTKInnerLoop.cs:62
long Start
Definition: MPTKInnerLoop.cs:73
Definition: MPTKInnerLoop.cs:26
int Count
Definition: MPTKInnerLoop.cs:94
bool Log
Definition: MPTKInnerLoop.cs:20

Member Enumeration Documentation

◆ InnerLoopPhase

Loop phase action sent to OnEventInnerLoop


Start the loop


Resume the loop


Exit the loop

Member Data Documentation

◆ Count

int MidiPlayerTK.MPTKInnerLoop.Count

Current loop count. Default is 0.

◆ Enabled

bool MidiPlayerTK.MPTKInnerLoop.Enabled

Enable or disable the loop. Default is false.

◆ End

long MidiPlayerTK.MPTKInnerLoop.End

Tick position to trigger the loop restart to the Resume position (when MidiLoad.MPTK_TickPlayer >= to End). Default is 0.

◆ Finished

bool MidiPlayerTK.MPTKInnerLoop.Finished

Become true when looping is over or OnEventInnerLoop return false. Set to false at start.

◆ Log

bool MidiPlayerTK.MPTKInnerLoop.Log

Enable logging message

◆ Max

int MidiPlayerTK.MPTKInnerLoop.Max

Maximum iteration for the loop including the first. When Count >= Max the MIDI sequencer continue to the next MIDI events AFTER TICK #eND.
Set to 0 for infinite loop. Default is 0.

◆ OnEventInnerLoop

Func<InnerLoopPhase, long, long, int, bool> MidiPlayerTK.MPTKInnerLoop.OnEventInnerLoop

Unity event triggered when a loop occurs. parameters:

  • InnerLoopPhase current loop phase
  • long current tick player (MPTK_TickPlayer)
  • long tick target (End)
  • long loop count (Count). return:
  • boolean true continue looping, false exit loop.
  • this action is done from the MIDI thread, not from the Unity thread.
  • It's not possible to call Unity API (only Debug.Log).
  • it's a managed thread, so all variables from your script are visible.

◆ Resume

long MidiPlayerTK.MPTKInnerLoop.Resume

Tick position to resume the loop when MidiLoad.MPTK_TickPlayer >= to End. Default is 0.

◆ Start

long MidiPlayerTK.MPTKInnerLoop.Start

Tick position where the loop begin when the MIDI start. The MIDI sequencer go immediately to this position.
if Start > Resume the loop will begin at Resume position. Default is 0.