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 to display MIDI content.
javascript const var MIDIPlayer1 = Synth.getMidiPlayer("MIDI Player1");
Class methods
asMidiProcessor
Returns a typed MIDI processor reference (for setting attributes etc).
MidiPlayer.asMidiProcessor()
clearAllSequences
Removes all sequences and tracks.
MidiPlayer.clearAllSequences()
connectToMetronome
Connects this MIDI player to the given metronome.
MidiPlayer.connectToMetronome(var metronome)
connectToPanel
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:
- new MIDI content being loaded
- track / sequence being changed
- MIDI sequence being cleared
- flushing of a MIDI processing
- if setRepaintOnPositionChange() was enabled, whenever the playback position changes.
You can then use the functions getNoteRectangleList
and getPlaybackPosition()
to fetch the data and write the UI logic you want.
convertEventListToNoteRectangles
Converts a given array of Message holders to a rectangle list.
MidiPlayer.convertEventListToNoteRectangles(var eventList, var targetBounds)
create
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
flushMessageList
Writes the given array of MessageHolder objects into the current sequence. This is undoable.
MidiPlayer.flushMessageList(var messageList)
flushMessageListToSequence
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)
getEventList
Creates an array containing all MIDI messages wrapped into MessageHolders for processing.
MidiPlayer.getEventList()
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.
getEventListFromSequence
Creates an array containing all MIDI messages from the sequence with the given (one-based!) index into Message Holders.
MidiPlayer.getEventListFromSequence(int sequenceIndexOneBased)
getLastPlayedNotePosition
Returns the position of the last played note.
MidiPlayer.getLastPlayedNotePosition()
getMidiFileList
Returns a list of all MIDI files that are embedded in the plugin.
MidiPlayer.getMidiFileList()
getNoteRectangleList
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
Player.connectToPanel(Panel);
Panel.setPaintRoutine(function(g)
{
// 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);
g.setColour(Colours.white);
// 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.
g.fillRect(note);
}
});
getNumSequences
Returns the number of loaded sequences.
MidiPlayer.getNumSequences()
getNumTracks
Returns the number of tracks in the current sequence.
MidiPlayer.getNumTracks()
getPlaybackPosition
Returns the playback position in the current loop between 0.0 and 1.0.
MidiPlayer.getPlaybackPosition()
getPlayState
Returns the play state (0 = stop, 1 = play, 2 = recording.
MidiPlayer.getPlayState()
getTicksPerQuarter
Returns the tick resolution for a quarter note.
MidiPlayer.getTicksPerQuarter()
getTimeSignature
Returns an object with properties about the length of the current sequence.
MidiPlayer.getTimeSignature()
getTimeSignatureFromSequence
Returns an object with properties about the length of the sequence with the given index.
MidiPlayer.getTimeSignatureFromSequence(int index)
isEmpty
Checks if the MIDI player contains a sequence to read / write.
MidiPlayer.isEmpty()
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;
}
isSequenceEmpty
Returns true if the sequence with the given (one-based!) index doesn't contain any midi data.
MidiPlayer.isSequenceEmpty(int indexOneBased)
play
Starts playing. Use the timestamp to delay the event or use the currents event timestamp for sample accurate playback.
MidiPlayer.play(int timestamp)
record
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
Redo the last edit.
MidiPlayer.redo()
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).
reset
Resets the current sequence to the last loaded file.
MidiPlayer.reset()
saveAsMidiFile
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 .
setAutomationHandlerConsumesControllerEvents
This will send any CC messages from the MIDI file to the global MIDI handler.
MidiPlayer.setAutomationHandlerConsumesControllerEvents(bool shouldBeEnabled)
setFile
Loads a MIDI file and switches to this sequence if specified.
MidiPlayer.setFile(var fileName, bool clearExistingSequences, bool selectNewSequence)
setGlobalPlaybackRatio
Sets a global playback ratio (for all MIDI players).
MidiPlayer.setGlobalPlaybackRatio(double globalRatio)
setPlaybackCallback
Attaches a callback with two arguments (timestamp, playState) that gets executed when the play state changes.
MidiPlayer.setPlaybackCallback(var playbackCallback, var synchronous)
setPlaybackPosition
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
- whether you want to clear the existing sequences or add this to the end of the list of "loaded" sequences. You can switch between multiple sequences on the fly (even during playback), so if you want to use this feature, you need to add multiple sequences by setting this flag to
true
. - whether you want to set the newly loaded sequence to be played back or keep the current sequence in the playback slot.
setRecordEventCallback
Sets a inline function that will process every note that is about to be recorded.
MidiPlayer.setRecordEventCallback(var recordEventCallback)
setRepaintOnPositionChange
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.
setSequence
Enables the (previously loaded) sequence with the given (one-based!) index.
MidiPlayer.setSequence(int sequenceIndex)
setSequenceCallback
Attaches a callback that gets executed whenever the sequence was changed.
MidiPlayer.setSequenceCallback(var updateFunction)
setSyncToMasterClock
Syncs the playback of this MIDI player to the master clock (external or internal).
MidiPlayer.setSyncToMasterClock(bool shouldSyncToMasterClock)
setTimeSignature
Sets the timing information of the current sequence using the given object.
MidiPlayer.setTimeSignature(var timeSignatureObject)
setTimeSignatureToSequence
Sets the timing information of the sequence with the given index using the given object.
MidiPlayer.setTimeSignatureToSequence(int index, var timeSignatureObject)
setTrack
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.
setUseGlobalUndoManager
If enabled, it uses the global undo manager for all edits (So you can use Engine.undo()).
MidiPlayer.setUseGlobalUndoManager(bool shouldUseGlobalUndoManager)
setUseTimestampInTicks
Uses Ticks instead of samples when editing the MIDI data.
MidiPlayer.setUseTimestampInTicks(bool shouldUseTicksAsTimestamps)
stop
Starts playing. Use the timestamp to delay the event or use the currents event timestamp for sample accurate playback.
MidiPlayer.stop(int timestamp)
undo
Undo the last edit.
MidiPlayer.undo()