MIDI Player

A MidiPlayer reference can be used to control the playback of a MIDI Player module as well as processing the currently loaded MIDI sequency. It also acts as event controller for building customised UI elements that display the MIDI content.

Class methods


Returns a typed MIDI processor reference (for setting attributes etc).



Removes all sequences and tracks.



Connects this MIDI player to the given metronome.

MidiPlayer.connectToMetronome(var metronome)


Connect this to the panel and it will be automatically updated when something changes.

MidiPlayer.connectToPanel(var panel)

This function is particularly helpful when you want to build a custom UI for the MIDI Player's content.

Once this is called and a ScriptPanel is connected to this reference, It will automatically cause a repaint of the ScriptPanel on these events:

You can then use the functions getNoteRectangleList and getPlaybackPosition() to fetch the data and write the UI logic you want.


Converts a given array of Message holders to a rectangle list.

MidiPlayer.convertEventListToNoteRectangles(var eventList, var targetBounds)


Creates an empty sequence with the given length.

MidiPlayer.create(int nominator, int denominator, int barLength)

The nominator and denominator will define the time signature, so for a 3/4 time signature and 7 bars, use MidiPlayer.create(3, 4, 7)

Be aware that this adds a new sequence to the player add the end of the list, so you probably want to check isEmpty() if you just want to write a bunch of notes


Writes the given array of MessageHolder objects into the current sequence. This is undoable.

MidiPlayer.flushMessageList(var messageList)


Writes the given array of MessageHolder objects into the sequence with the given (one-based!) index. This is undoable.

MidiPlayer.flushMessageListToSequence(var messageList, int sequenceIndexOneBased)


Creates an array containing all MIDI messages wrapped into MessageHolders for processing.


This is the first step of three when you want to process the content of a MIDI Player.
It creates an array of MessageHolder objects which can be used to transform the MIDI data.

The event ID of the events will be created consecutively and the events are sorted chronologically. You can find the matching note-off event to a note-on event using something like this:

inline function getNoteOff(list, noteOn)
    for(e in list)
        if(e.isNoteOff() && e.getEventId() == noteOn.getEventId())
            return e;

The timestamp will be using the current samplerate and host BPM tempo to convert the relative MIDI timing to absolute sample positions. Be careful to never change the order of a note-on / note-off pair, otherwise the results will be very weird.

There are a few new helper functions in the Engine class to help you converting between the domains (search for QuarterBeats )

Also make sure to call flushMessageList() after finishing the processing to apply the changes.


Creates an array containing all MIDI messages from the sequence with the given (one-based!) index into Message Holders.

MidiPlayer.getEventListFromSequence(int sequenceIndexOneBased)


Returns the position of the last played note.



Returns a list of all MIDI files that are embedded in the plugin.



Returns an array containing all notes converted to the space supplied with the target bounds [x, y, w, h].

MidiPlayer.getNoteRectangleList(var targetBounds)

This converts the MIDI data in the current sequence to a list of rectangles for each note scaled to fill the rectangle supplied as argument.

A rectangle in HISEScript is always an array of 4 integers:
[x, y, width, height] .

The most simple application of this is to draw a piano-roll content into a Panel.

// Fetch a Panel
const var Panel = Content.getComponent("Panel1");

// Fetch a MIDI Player
const var Player = Synth.getMidiPlayer("MIDI Player1");

// Connect the player to the panel to make it update automatically

    // create a list of note rectangles.
    // the argument is the boundaries of this panel so it will scale
    // them to the dimensions of the entire panel.
    var entireArea = [0, 0, this.getWidth(), this.getHeight()];
    var list = Player.getNoteRectangleList(entireArea);

    // Now we can simply iterate over them and paint them
    for(note in list)
        // `note` is a array with 4 numbers and can be passed
        // into all Graphic API functions pretty conveniently.


Returns the number of loaded sequences.



Returns the number of tracks in the current sequence.



Returns the playback position in the current loop between 0.0 and 1.0.



Returns the play state (0 = stop, 1 = play, 2 = recording.



Returns the tick resolution for a quarter note.



Returns an object with properties about the length of the current sequence.



Checks if the MIDI player contains a sequence to read / write.


This doesn't check whether the current sequence contains any notes, but checks whether there is any sequence loaded at all: If you load up the MIDI Player, it will not have a sequence loaded until you either load a MIDI file, or call Midiplayer.create .

If you want to check whether the sequence is empty, you can use this:

// Do not call this in the audio thread obviously...
inline function sequenceHasNoEvents(player)
    return player.getEventList().length == 0;


Returns true if the sequence with the given (one-based!) index doesn't contain any midi data.

MidiPlayer.isSequenceEmpty(int indexOneBased)


Starts playing. Use the timestamp to delay the event or use the currents event timestamp for sample accurate playback.

MidiPlayer.play(int timestamp)


Starts recording (not yet implemented). Use the timestamp to delay the event or use the currents event timestamp for sample accurate playback.

MidiPlayer.record(int timestamp)


Redo the last edit.


Just like undo() , this will not use the global undo manager, but a dedicated undo manager for each MIDI player (otherwise the actions interfere with changing UI values, which would be very annoying).


Resets the current sequence to the last loaded file.



Saves the current sequence into the given file at the track position.

MidiPlayer.saveAsMidiFile(var file, int trackIndex)

This overwrites the track (starting with one) in the given file.

This is not undoable and the original content will be swept into digital nirvana (except if you have a backup of the original file, obviously), so NEVER use this method unless you know exactly what to do .


This will send any CC messages from the MIDI file to the global MIDI handler.

MidiPlayer.setAutomationHandlerConsumesControllerEvents(bool shouldBeEnabled)


Loads a MIDI file and switches to this sequence if specified.

MidiPlayer.setFile(var fileName, bool clearExistingSequences, bool selectNewSequence)


Sets a global playback ratio (for all MIDI players).

MidiPlayer.setGlobalPlaybackRatio(double globalRatio)


Attaches a callback with two arguments (timestamp, playState) that gets executed when the play state changes.

MidiPlayer.setPlaybackCallback(var playbackCallback, var synchronous)


Sets the playback position in the current loop. Input must be between 0.0 and 1.0.

MidiPlayer.setPlaybackPosition(var newPosition)

Similar to AudioSampleProcessor.setFile() , this will load a file into the MIDI player.

It uses the standard HISE syntax for file references . The other arguments let you choose


Sets a inline function that will process every note that is about to be recorded.

MidiPlayer.setRecordEventCallback(var recordEventCallback)


If true, the panel will get a repaint() call whenever the playback position changes.

MidiPlayer.setRepaintOnPositionChange(var shouldRepaintPanel)

By default this is off, but if you need your connected Panel to repaint during playback (eg. to display a ruler that indicates the position), set this to true and it repaint() will be called periodically during playback.


Enables the (previously loaded) sequence with the given (one-based!) index.

MidiPlayer.setSequence(int sequenceIndex)


Attaches a callback that gets executed whenever the sequence was changed.

MidiPlayer.setSequenceCallback(var updateFunction)


Syncs the playback of this MIDI player to the master clock (external or internal).

MidiPlayer.setSyncToMasterClock(bool shouldSyncToMasterClock)


Sets the timing information of the current sequence using the given object.

MidiPlayer.setTimeSignature(var timeSignatureObject)


Sets the track index (starting with one).

MidiPlayer.setTrack(int trackIndex)

This makes the MIDI Player choose the selected track (again, starting with 1 , not with zero). Be aware that changing tracks is not as "dynamic" as switching between different sequences.


If enabled, it uses the global undo manager for all edits (So you can use Engine.undo()).

MidiPlayer.setUseGlobalUndoManager(bool shouldUseGlobalUndoManager)


Uses Ticks instead of samples when editing the MIDI data.

MidiPlayer.setUseTimestampInTicks(bool shouldUseTicksAsTimestamps)


Starts playing. Use the timestamp to delay the event or use the currents event timestamp for sample accurate playback.

MidiPlayer.stop(int timestamp)


Undo the last edit.