Maestro - Midi Player Tool Kit for Unity Version 2.18.2
Loading...
Searching...
No Matches
Position, Duration, and Timing

Query and control playback position, timing, duration, and speed. More...

Position and Duration

double MidiPlayerTK.MidiFilePlayer.MPTK_Position [get, set]
 Gets or sets the current position in the MIDI in milliseconds.
When a new position is set, the corresponding tick in the MIDI event list is searched for by comparing it with the MPTKEvent.RealTime value, and the current MIDI playback is moved to this new tick position.
.
TimeSpan MidiPlayerTK.MidiFilePlayer.MPTK_Duration [get]
 Real duration expressed in TimeSpan of the full midi from the first event (tick=0) to the last event.
If MPTK_KeepEndTrack is false, the MIDI events End Track are not considered to calculate this time.
The tempo changes are taken into account if MPTK_EnableChangeTempo is set to true before loading the MIDI.
float MidiPlayerTK.MidiFilePlayer.MPTK_DurationMS [get]
 Real duration expressed in milliseconds of the full MIDI from the first event (tick=0) to the last event.
If MPTK_KeepEndTrack is false, the MIDI events End Track are not considered to calculate this time.
The tempo changes are taken into account if MPTK_EnableChangeTempo is set to true before loading the MIDI.
long MidiPlayerTK.MidiFilePlayer.MPTK_TickLast [get]
 Last tick tick in Midi: it's the value of the tick for the last MIDI event in sequence expressed in number of "ticks".
.
long MidiPlayerTK.MidiFilePlayer.MPTK_TickFirstNote [get]
 Tick tick for the first note-on found.
Most MIDI don't start playing a note immediately. There is often a delay.
Use this attribute to known the tick tick where the will start to play a sound.
See also MPTK_PositionFirstNote.
long MidiPlayerTK.MidiFilePlayer.MPTK_TickLastNote [get]
 Tick tick for the last note-on found.
There is often other MIDI events after the last note-on: for example event track-end.
Use this attribute to known the tick tick time when all sound will be stop.
See also the MPTK_PositionLastNote which provides the last time of the MIDI.
double MidiPlayerTK.MidiFilePlayer.MPTK_PositionFirstNote [get]
 Real time tick in milliseconds for the first note-on found.
Most MIDI don't start playing a note immediately. There is often a delay.
Use this attribute to known the real time which it will start.
See also MPTK_TickFirstNote.
double MidiPlayerTK.MidiFilePlayer.MPTK_PositionLastNote [get]
 Real time tick in milliseconds for the last note-on found in the MIDI.
There is often other MIDI events after the last note-on: for example event track-end.
Use this attribute to known the real time when all sound will be stop.
See also the MPTK_DurationMS which provides the full time of all MIDI events including track-end, control at the beginning and at the end, ....
See also MPTK_TickLastNote.
int MidiPlayerTK.MidiFilePlayer.MPTK_TrackCount [get]
 Count of track read in the MIDI file.
long MidiPlayerTK.MidiFilePlayer.MPTK_TickCurrent [get, set]
 Gets the tick value of the last MIDI event played.
Sets the tick value of the next MIDI event to played.
.
bool MidiPlayerTK.MidiFilePlayer.MPTK_RawSeek [get, set]
 This parameter controls how the playback position is adjusted within a MIDI file. By default (false), when the playback position is changed, all events except "note-on" are replayed from the start of the MIDI file up to the new position. This ensures the synthesizer is correctly updated with the appropriate context (tempo, selected instruments, controllers, etc.).
If set to true, the playback position is updated directly; consequently, the current context is preserved.
While this approach can lead to unintended (or amusing!) effects in some MIDI files, it allows for much faster position changes.
MPTKEvent MidiPlayerTK.MidiFilePlayer.MPTK_LastEventPlayed [get]
 Last MIDI event played by the MIDI sequencer.
double MidiPlayerTK.MidiFilePlayer.MPTK_Pulse [get]
 Length in milliseconds of a MIDI tick. The pulse length is the minimum time in milliseconds between two MIDI events.
It's like a definition of graphical resolution but for MIDI: the MIDI sequencer will not be able to play two separate MIDI events in a time below this value.
.
TimeSpan MidiPlayerTK.MidiFilePlayer.MPTK_PlayTime [get]
 Real time in TimeSpan format from the beginning of play. It's an access to the MIDI timer used by the MIDI sequencer.
double MidiPlayerTK.MidiFilePlayer.MPTK_RealTime [get]
 Real time in milliseconds from the beginning of play. It's an access to the MIDI timer used by the MIDI sequencer.
double MidiPlayerTK.MidiFilePlayer.MPTK_PulseLenght [get]
 Gets or sets the current position in the MIDI in milliseconds.
When a new position is set, the corresponding tick in the MIDI event list is searched for by comparing it with the MPTKEvent.RealTime value, and the current MIDI playback is moved to this new tick position.
.

MIDI Properties

float MidiPlayerTK.MidiFilePlayer.MPTK_Speed [get, set]
 Percentage of the default playback speed. Range 0.1 (10% of the current BPM) to 10 (1000%). Default is 1 for normal speed.
Speed also applied to the duration of the sample played at voice level (often multiple voices are played for one note).
bool MidiPlayerTK.MidiFilePlayer.MPTK_Loop [get, set]
double MidiPlayerTK.MidiFilePlayer.MPTK_Tempo [get, set]
 Gets or sets the current tempo played by the internal MIDI sequencer (independent from MPTK_Speed).
Return QuarterPerMinuteValue similar to BPM (Beat Per Measure).
.
string MidiPlayerTK.MidiFilePlayer.MPTK_SequenceTrackName [get]
 Gets sequence track name if defined in the MIDI file with MIDI MetaEventType = SequenceTrackName
See detail here https://ccrma.stanford.edu/~craig/14q/midifile/MidiFileFormat.html
Can be used only when the MIDI is playing.
string MidiPlayerTK.MidiFilePlayer.MPTK_ProgramName [get]
 Gets Program track name if defined in the MIDI file with MIDI MetaEventType = ProgramName
See detail here https://ccrma.stanford.edu/~craig/14q/midifile/MidiFileFormat.html
Can be used only when the MIDI is playing.
string MidiPlayerTK.MidiFilePlayer.MPTK_TrackInstrumentName [get]
 Gets Instrument track name if defined in the MIDI file with MIDI MetaEventType = TrackInstrumentName
See detail here https://ccrma.stanford.edu/~craig/14q/midifile/MidiFileFormat.html
Can be used only when the MIDI is playing.
string MidiPlayerTK.MidiFilePlayer.MPTK_TextEvent [get]
 Gets Text if defined in the MIDI file with MIDI MetaEventType = TextEvent
See detail here https://ccrma.stanford.edu/~craig/14q/midifile/MidiFileFormat.html
Can be used only when the MIDI is playing.
string MidiPlayerTK.MidiFilePlayer.MPTK_Copyright [get]
 Gets Copyright if defined in the MIDI file with MIDI MetaEventType = Copyright
See detail here https://ccrma.stanford.edu/~craig/14q/midifile/MidiFileFormat.html
Can be used only when the MIDI is playing.
List< MPTKEventMidiPlayerTK.MidiFilePlayer.MPTK_MidiEvents [get]
 Gets a list of all the MPTK MIDI events that are available in the MIDI.
.
int MidiPlayerTK.MidiFilePlayer.MPTK_Quantization [get, set]
 Level of quantization :
int MidiPlayerTK.MidiFilePlayer.MPTK_DeltaTicksPerQuarterNote [get]
 Delta Ticks Per Beat Note. Indicate the duration time in "ticks" which make up a quarter-note.
For instance, if 96, then a duration of an eighth-note in the file would be 48.
More info here https://paxstellar.fr/2020/09/11/midi-timing/
.
void MidiPlayerTK.MidiFilePlayer.MPTK_ResetTranspose ()
 Force all notes to return to their original values before transposing.
Useful when looping on a MIDI with a transpose value different than 0. When returning to 0 (no transpose) the note value can be reset to their original value.
MPTKEvent.EnumLength MidiPlayerTK.MidiFilePlayer.MPTK_NoteLength (MPTKEvent note)
 Return note length as https://en.wikipedia.org/wiki/Note_value.

Detailed Description

Query and control playback position, timing, duration, and speed.

Function Documentation

◆ MPTK_ResetTranspose()

void MidiPlayerTK.MidiFilePlayer.MPTK_ResetTranspose ( )

Force all notes to return to their original values before transposing.
Useful when looping on a MIDI with a transpose value different than 0. When returning to 0 (no transpose) the note value can be reset to their original value.

Version
V2.14.0

◆ MPTK_NoteLength()

MPTKEvent.EnumLength MidiPlayerTK.MidiFilePlayer.MPTK_NoteLength ( MPTKEvent note)

Return note length as https://en.wikipedia.org/wiki/Note_value.

Parameters
note
Returns
MPTKEvent.EnumLength

Properties

◆ MPTK_Position

double MidiPlayerTK.MidiFilePlayer.MPTK_Position
getset

Gets or sets the current position in the MIDI in milliseconds.
When a new position is set, the corresponding tick in the MIDI event list is searched for by comparing it with the MPTKEvent.RealTime value, and the current MIDI playback is moved to this new tick position.
.

Note

Here, more information about Midi Timing https://paxstellar.fr/2020/09/11/midi-timing/

public MidiFilePlayer midiFilePlayer;
void Start()
{
// Find the prefab MidiFilePlayer in your scene
midiFilePlayer = FindFirstObjectByType<MidiFilePlayer>();
// Event trigger when midi file start playing
midiFilePlayer.OnEventStartPlayMidi.AddListener(info => StartPlay("Event set by script"));
// beginning playing
midiFilePlayer.MPTK_Play();
}
// Method executed when the MIDI file start playing
public void StartPlay(string name)
{
// The MIDI will start playing at 5 seconds from the beginning of the MIDI
midiFilePlayer.MPTK_Position = 5000;
}
void Update()
{
if ('condition from your application is true')
// The MIDI will continue playing at 10 seconds from the beginning of the MIDI
midiFilePlayer.MPTK_Position = 10000;
}
Plays a MIDI file from the MidiDB. This class must be used with the prefab MidiFilePlayer....
Definition MidiFilePlayer.cs:69
EventStartMidiClass OnEventStartPlayMidi
Define the Unity event to be triggered at the start of Midi playback. At this moment,...
Definition MidiFilePlayer.cs:973
virtual void MPTK_Play(bool alreadyLoaded=false)
Plays the midi file defined with MPTK_MidiName or MPTK_MidiIndex. In the most part of the case,...
Definition MidiFilePlayer.cs:303

◆ MPTK_TickCurrent

long MidiPlayerTK.MidiFilePlayer.MPTK_TickCurrent
getset

Gets the tick value of the last MIDI event played.
Sets the tick value of the next MIDI event to played.
.

MIDI tick is an easy way to identify a position in a song independently of the time which could vary with tempo change event.
The count of ticks by quarter is constant all along a MIDI, it's a properties of the whole MIDI. see MPTK_DeltaTicksPerQuarterNote.
With a time signature of 4/4 the ticks length of a bar is 4 * MPTK_DeltaTicksPerQuarterNote.
Here, more information about Midi Timing https://paxstellar.fr/2020/09/11/midi-timing/

Note
  • works only when the MIDI is playing.
  • you can't set the tick before or just after MPTK_Play() because MPTK_Play() reset the tick at the start.
  • rather, set the tick when the event OnEventStartPlayMidi() is triggereed. See example below.
  • look also the properties MPTK_Position to change the tick by milliseconds.
  • when the MIDI is playing look at the inspector of the MidiFilePlayer prefab to read (or change) the current tick and find the tick you want.
  • see also MPTK_RawSeek to change way current tick position is changed.
  • look also MidiLoad.MPTK_TickPlayer to get the real-time tick value from the MIDI player.
See example:
public MidiFilePlayer midiFilePlayer;
void Start()
{
// Find the prefab MidiFilePlayer in your scene
midiFilePlayer = FindFirstObjectByType<MidiFilePlayer>();
// Event trigger when midi file start playing
midiFilePlayer.OnEventStartPlayMidi.AddListener(info => StartPlay("Event set by script"));
// beginning playing
midiFilePlayer.MPTK_Play();
}
// Method executed when the MIDI file start playing
public void StartPlay(string name)
{
// The MIDI will start playing at tick 10000
midiFilePlayer.MPTK_TickCurrent = 10000;
}
void Update()
{
if ('condition from your application is true')
// The MIDI will continue playing at ticks 20000
midiFilePlayer.MPTK_TickCurrent = 20000;
}

◆ MPTK_RawSeek

bool MidiPlayerTK.MidiFilePlayer.MPTK_RawSeek
getset

This parameter controls how the playback position is adjusted within a MIDI file. By default (false), when the playback position is changed, all events except "note-on" are replayed from the start of the MIDI file up to the new position. This ensures the synthesizer is correctly updated with the appropriate context (tempo, selected instruments, controllers, etc.).
If set to true, the playback position is updated directly; consequently, the current context is preserved.
While this approach can lead to unintended (or amusing!) effects in some MIDI files, it allows for much faster position changes.

Version
2.12.0
Note
  • This value resets to false (default) each time a MIDI file is loaded. You can use MPTK_Load() to load the MIDI, adjust this parameter, and then play the MIDI using MPTK_Play().

◆ MPTK_Pulse

double MidiPlayerTK.MidiFilePlayer.MPTK_Pulse
get

Length in milliseconds of a MIDI tick. The pulse length is the minimum time in milliseconds between two MIDI events.
It's like a definition of graphical resolution but for MIDI: the MIDI sequencer will not be able to play two separate MIDI events in a time below this value.
.

Note
  • Depends on the current tempo (#MPTK_CurrentTempo) and the MPTK_DeltaTicksPerQuarterNote and Speed.
  • Read Only.
  • Formula: PulseLength = MPTK_CurrentTempo / MPTK_DeltaTicksPerQuarterNote / 1000 / Speed

◆ MPTK_PlayTime

TimeSpan MidiPlayerTK.MidiFilePlayer.MPTK_PlayTime
get

Real time in TimeSpan format from the beginning of play. It's an access to the MIDI timer used by the MIDI sequencer.

Note
MPTK_Tempo or MPTK_Speed change have no direct impact on this value.

◆ MPTK_RealTime

double MidiPlayerTK.MidiFilePlayer.MPTK_RealTime
get

Real time in milliseconds from the beginning of play. It's an access to the MIDI timer used by the MIDI sequencer.

Note
MPTK_Tempo or MPTK_Speed change have no direct impact on this value.

◆ MPTK_Speed

float MidiPlayerTK.MidiFilePlayer.MPTK_Speed
getset

Percentage of the default playback speed. Range 0.1 (10% of the current BPM) to 10 (1000%). Default is 1 for normal speed.
Speed also applied to the duration of the sample played at voice level (often multiple voices are played for one note).

Note
:

◆ MPTK_PulseLenght

double MidiPlayerTK.MidiFilePlayer.MPTK_PulseLenght
get

Gets or sets the current position in the MIDI in milliseconds.
When a new position is set, the corresponding tick in the MIDI event list is searched for by comparing it with the MPTKEvent.RealTime value, and the current MIDI playback is moved to this new tick position.
.

Note

Here, more information about Midi Timing https://paxstellar.fr/2020/09/11/midi-timing/

public MidiFilePlayer midiFilePlayer;
void Start()
{
// Find the prefab MidiFilePlayer in your scene
midiFilePlayer = FindFirstObjectByType<MidiFilePlayer>();
// Event trigger when midi file start playing
midiFilePlayer.OnEventStartPlayMidi.AddListener(info => StartPlay("Event set by script"));
// beginning playing
midiFilePlayer.MPTK_Play();
}
// Method executed when the MIDI file start playing
public void StartPlay(string name)
{
// The MIDI will start playing at 5 seconds from the beginning of the MIDI
midiFilePlayer.MPTK_Position = 5000;
}
void Update()
{
if ('condition from your application is true')
// The MIDI will continue playing at 10 seconds from the beginning of the MIDI
midiFilePlayer.MPTK_Position = 10000;
}

◆ MPTK_Loop

bool MidiPlayerTK.MidiFilePlayer.MPTK_Loop
getset
Deprecated
with 2.10.0 MPTK_Loop is deprecated. Please investigate #MPTK_MidiRestart or MPTK_InnerLoop (Pro) for a better looping accuracy.

◆ MPTK_Tempo

double MidiPlayerTK.MidiFilePlayer.MPTK_Tempo
getset

Gets or sets the current tempo played by the internal MIDI sequencer (independent from MPTK_Speed).
Return QuarterPerMinuteValue similar to BPM (Beat Per Measure).
.

Note
  • Can be handle only when the MIDI is playing.
  • Changing the current tempo when playing has no impact on the calculated duration of the MIDI.

◆ MPTK_MidiEvents

List<MPTKEvent> MidiPlayerTK.MidiFilePlayer.MPTK_MidiEvents
get

Gets a list of all the MPTK MIDI events that are available in the MIDI.
.

private void OnGUI_ModifyMidiAndPlay()
{
HelperDemo.GUI_Horizontal(HelperDemo.Zone.BEGIN, myStyle.BacgDemosLight);
HelperDemo.GUI_Indent(widthIndent);
HelperDemo.GUI_Vertical(HelperDemo.Zone.BEGIN, myStyle.BacgDemosLight);
GUILayout.Label("It's possible to change the MIDI events before playing. This demo loads the selected MIDI, adds some notes and plays the MIDI without reloading it. Result not guaranteed!", myStyle.TitleLabel3);
countNoteToInsert = (int)HelperDemo.GUI_Slider("Count notes to insert:", (float)countNoteToInsert, 1, 100,
alignCaptionRight: false, enableButton: true, widthCaption: 170, widthSlider: 250, widthLabelValue: 50);
tickPositionToInsert = (long)HelperDemo.GUI_Slider("Tick position to insert:", (long)tickPositionToInsert, 0, (long)midiFilePlayer.MPTK_TickLast,
alignCaptionRight: false, enableButton: true, widthCaption: 170, widthSlider: 250, widthLabelValue: 50);
long quarterPosition = tickPositionToInsert / midiFilePlayer.MPTK_DeltaTicksPerQuarterNote;
long newQuarter = (long)HelperDemo.GUI_Slider("Tick position by quarter:", (long)quarterPosition, 0, (long)midiFilePlayer.MPTK_TickLast / midiFilePlayer.MPTK_DeltaTicksPerQuarterNote,
alignCaptionRight: false, enableButton: true, widthCaption: 170, widthSlider: 250, widthLabelValue: 50);
if (newQuarter != quarterPosition)
{
quarterPosition = newQuarter;
tickPositionToInsert = quarterPosition * midiFilePlayer.MPTK_DeltaTicksPerQuarterNote;
}
channelToInsert = (int)HelperDemo.GUI_Slider("Channel to insert:", channelToInsert, 0, 15,
alignCaptionRight: false, enableButton: true, widthCaption: 170, widthSlider: 250, widthLabelValue: 50);
HelperDemo.GUI_Horizontal(HelperDemo.Zone.BEGIN, null, GUILayout.Width(500));
clearNote = GUILayout.Toggle(clearNote, "Clear MIDI list before inserting");
GUILayout.Space(10);
randomNote = GUILayout.Toggle(randomNote, "Random Note");
GUILayout.Space(10);
randomDuration = GUILayout.Toggle(randomDuration, "Random Duration");
GUILayout.Space(10);
calculateTiming = GUILayout.Toggle(calculateTiming, "Timing Recalculation");
HelperDemo.GUI_Horizontal(HelperDemo.Zone.END);
HelperDemo.GUI_Horizontal(HelperDemo.Zone.BEGIN);
if (GUILayout.Button("Insert And Play", GUILayout.Width(120)))
{
#if MPTK_PRO
// Better to stop playing.
midiFilePlayer.MPTK_Stop();
// There is no need of note-off events.
midiFilePlayer.MPTK_KeepNoteOff = false;
// MPTK_MidiName must contains the name of the MIDI to load.
if (midiFilePlayer.MPTK_Load() != null)
{
Debug.Log($"Duration: {midiFilePlayer.MPTK_Duration.TotalSeconds} seconds");
Debug.Log($"Count MIDI Events: {midiFilePlayer.MPTK_MidiEvents.Count}");
if (clearNote)
midiFilePlayer.MPTK_MidiEvents.Clear();
// Insert weird notes in this beautiful MIDI!
// ------------------------------------------
long tickToInsert = tickPositionToInsert;
for (int insertNote = 0; insertNote < countNoteToInsert; insertNote++)
{
int note;
if (randomNote)
note = UnityEngine.Random.Range(50, 73); // Random notes between 48 (C4) and 72 (C6)
else
note = 60 + insertNote % 12; // Hust a remap of notes!
int eightCount; // How many eight duration to generate
if (randomDuration)
eightCount = UnityEngine.Random.Range(0, 9); // max 8, so a whole note
else
eightCount = 2; // a quarter
int tickDuration = eightCount * midiFilePlayer.MPTK_DeltaTicksPerQuarterNote;
// Add a note
midiFilePlayer.MPTK_MidiEvents.Insert(0,
new MPTKEvent()
{
Channel = channelToInsert,
Command = MPTKCommand.NoteOn,
Value = note,
Length = tickDuration,
Duration = (long)(tickDuration * midiFilePlayer.MPTK_Pulse), // Transform ticks to millisecond
Tick = tickToInsert,
});
// Add a text
midiFilePlayer.MPTK_MidiEvents.Insert(0,
new MPTKEvent()
{
Command = MPTKCommand.MetaEvent,
Meta = MPTKMeta.TextEvent,
Info = $"Add a weird note {HelperNoteLabel.LabelFromMidi(note)}",
Tick = tickToInsert,
});
// Move to the next insert, add length of note added.
tickToInsert += tickDuration;
}
// New events has been inserted, MIDI events list must be sorted by tick value.
// ---------------------------------------------------------------------------
midiFilePlayer.MPTK_SortEvents();
if (calculateTiming)
{
// Timing recalculation is not useful for all use cases.
// Avoid if possible because this takes time and realloc data.
midiFilePlayer.midiLoaded.MPTK_CalculateTiming();
}
// Then play the event list modified (not guaranteed to be the hit of the year!)
// ----------------------------------------------------------------------------------
midiFilePlayer.MPTK_Play(alreadyLoaded: true);
}
#else
Debug.LogWarning("MIDI preload and alter MIDI events are available only with the PRO version");
#endif
}
HelperDemo.LinkTo("https://mptkapi.paxstellar.com/d7/deb/class_midi_player_t_k_1_1_midi_file_player.html#a7c1b1b1efab0022731f69e5161952c59");
if (GUILayout.Button("View MIDI events", GUILayout.Width(120)))
{
midiFilePlayer.MPTK_MidiEvents.ForEach(midi => Debug.Log(midi));
}
HelperDemo.GUI_Horizontal(HelperDemo.Zone.END);
HelperDemo.GUI_Vertical(HelperDemo.Zone.END);
HelperDemo.GUI_Horizontal(HelperDemo.Zone.END);
}

◆ MPTK_Quantization

int MidiPlayerTK.MidiFilePlayer.MPTK_Quantization
getset

Level of quantization :

  • 0 = None
  • 1 = Beat Note
  • 2 = Eighth Note
  • 3 = 16th Note
  • 4 = 32th Note
  • 5 = 64th Note
  • 6 = 128th Note

◆ MPTK_DeltaTicksPerQuarterNote

int MidiPlayerTK.MidiFilePlayer.MPTK_DeltaTicksPerQuarterNote
get

Delta Ticks Per Beat Note. Indicate the duration time in "ticks" which make up a quarter-note.
For instance, if 96, then a duration of an eighth-note in the file would be 48.
More info here https://paxstellar.fr/2020/09/11/midi-timing/
.

Move forward one quarter
midiFilePlayer.MPTK_TickCurrent = midiFilePlayer.MPTK_TickCurrent + midiFilePlayer.MPTK_DeltaTicksPerQuarterNote;