Sequencer Class - spessasus/spessasynth_lib GitHub Wiki
This is the module
that plays MIDI sequences
using the Synthetizer
class.
Tip
If you encounter any errors in this documentation, please open an issue!
Important
Make sure you've read this
const sequencer = new Sequencer(midiBuffers, synth, options);
-
midiBuffers
- an array of the MIDI files to play. EitherMIDI
or objects with two properties:-
binary
: theArrayBuffer
representation of the file. It can be mixed up. -
altName
- alternative name of the sequence if it doesn't have one. It cn be undefined.
-
-
synth
- the synthetizer to use. An instance of theSynthetizer
class. -
options
- an optionalObject
with options for the sequencer (all of them are optional as well as the object itself)-
skipToFirstNoteOn
- aboolean
indicating if the sequencer should skip to the first note on. Defaults totrue
. -
autoPlay
- aboolean
indicating if the first sequence supplied should start playing. Defaults totrue
. -
preservePlaybackState
- aboolean
indicating if seeking or changing the playback rate will be kept. -
initialPlaybackRate
- anumber
with the initial playback rate, other than the default 1.0. paused instead of resuming. Defaults tofalse
.
-
Tip
For performance reasons, it is recommended passing the binary data rather than the parsed MIDI
instance.
Caution
Due to the way the sequencer has been coded,
only one sequencer can be used with a Synthetizer
instance at once!
If this is something that you want to be fixed, feel free to open an issue.
Load a new song list.
sequencer.loadNewSongList(midiBuffers, autoPlay = true);
- midiBuffers - an array of the parsed MIDI files to play, Either
MIDI
or objects (can be mixed up) with two properties:-
binary
- theArrayBuffer
representation of the file. -
altName
- alternative name of the sequence if it doesn't have one (like file name, for example).string
, can be undefined.
-
-
autoPlay
- aboolean
indicating if the first sequence supplied should start playing. Defaults totrue
.
Note
If only one file is supplied, the loop
will be set to false.
Start playing the sequence. If the sequence was paused, it won't change any controllers, but if it wasn't (ex. the time was changed) then it will go through all the controller changes from the start before playing. This function does NOT modify the current playback time!
sequencer.play(resetTime);
- resetTime - boolean, if set to
true
then the playback will start from 0. Defaults tofalse
;
Pause the playback of the sequence.
sequencer.pause();
Stop the playback of the sequence. Currently only used internally by the pause
function.
sequencer.stop();
Play the next song in the list.
sequencer.nextSong();
Play the previous song in the list.
sequencer.previousSong();
Set the song index to a specific number.
sequencer.setSongIndex(index);
- index - number, the song index, zero-based.
Connect a given MIDI output port and play the sequence to it.
sequencer.connectMidiOutput(output);
- output - a
MIDIOutput
object, the output port to play to.
Tip
Pass undefined
to use SpessaSynth.
Note
You can also use MIDIDeviceHandler
Hook up a given callback function to the song change event.
sequencer.addOnSongChangeEvent(callback, id);
- callback - the function that gets called back, takes a
MidiData
instance (the new song). - id -
string
, unique identifier for the callback. Can be anything as long as it's unique.
Important
This is the MidiData
type, not MIDI
. It has all the properties of MIDI
, except the tracks
property,
which is the actual song data.
Hook up a given callback function to the time change event.
sequencer.addOnTimeChangeEvent(callback, id);
- callback - the function that gets called back, takes a
number
(the new time, in seconds). - id -
string
, unique identifier for the callback. Can be anything as long as it's unique.
Hook up a given callback function to any MIDI meta event that occurs.
sequencer.addOnMetaEvent(callback, id);
- callback - the function that gets called back,
takes a
[MIDIMessage, number]
array. That is: -
- The MIDI message object for this message
-
- the track number for this message
- id -
string
, unique identifier for the callback. Can be anything as long as it's unique.
Hook up a given callback function to the tempo change event.
sequencer.addOnTempoChangeEvent(callback, id);
- callback - the function that gets called back, takes a
number
(the new tempo, in beats per minute). - id -
string
, unique identifier for the callback. Can be anything as long as it's unique.
Hook up a given callback function to the song end.
sequencer.addOnSongEndedEvent(callback, id);
- callback - the function that gets called back, no arguments.
- id -
string
, unique identifier for the callback. Can be anything as long as it's unique.
Warning
This will only get called if the loop is disabled.
Gets the actual MIDI
sequence, complete with track data.
const data = await sequencer.getMIDI();
Important
This function is asynchronous.
Warning
The track data can potentially have hundreds of thousands of messages for complex MIDIs. Use sparingly!
Read-only boolean, indicating that if the sequencer's playback is paused.
if(sequencer.paused)
{
console.log("Sequencer paused!");
}
else
{
console.log("Sequencer playing or stopped!");
}
Indicates how fast the song plays (1 is normal, 0.5 is half speed etc.)
sequencer.playbackRate = 0.5; // the playback speed is half the normal speed
Boolean that controls if the sequencer loops.
sequencer.loop = false; // the playback will stop after reaching the end
The number of loops remaining until the loop is disabled.
A value of -1
means infinite looping.
It will automatically decrease by one every loop.
Defaults to -1
.
sequencer.loopsRemaining = 2; // the sequencer will loop two times and then the loop will turn off
Boolean that controls if the song order is random. Note that setting this to on will change the current song. The order is randomized once, not every time the song changes.
sequencer.shuffleSongs = true;
Property used for changing and reading the current playback time.
Returns the current playback time in seconds.
console.log("The sequence is currently "+sequencer.currentTime+" seconds in.");
Set the current playback time. Calls stop
and then play
internally.
sequencer.currentTime = 0; // go to the start
The current tempo of the sequence, in BPM.
console.log("Current tempo: "+sequencer.currentTempo+" BPM.");
Tip
Tempo changes can be monitored via tempo change event
A boolean
indicating if the sequencer should skip to the first note on when the time is set to 0.
sequencer.skipToFirstNoteOn = false; // sequencer will no longer skip
A boolean
indicating if seeking or changing the playback rate will be kept
paused instead of resuming.
sequencer.preservePlaybackState = true; // now the song will stay paused when seeking
The data of the current sequence.
Essentially MIDI
except for the tracks
property
(the song data).
console.log(`This song is named "${sequencer.midiData.midiName}"`);
Tip
To get the actual MIDI data, use the getMIDI
method.
Important
The sequencer doesn't instantly get the new midi information.
Make sure to use addOnSongChangeEvent
instead of waiting or assuming that the data is available instantly.
Also keep in mind that The sequencer preloads the samples for the MIDI, which might take a bit!
Length of the current track in seconds. Equivalent of Audio.duration
;
console.log(`The track lasts for ${sequencer.duration} seconds!`);
The data of all the sequences, stored like the midiData
property, but for all songs.
Allows creating playlists with the decoded titles and metadata.
console.log(`The current playlist:\n${sequencer.songListData.map(s => s.midiName).join("\n")}`);
The current index of the song that's playing
console.log(sequencer.songIndex); // 0
The number of songs in the queue.
console.log(sequencer.songsAmount); // 3
A callback function if defined. Will be called on a text event, like lyrics.
sequencer.onTextEvent = (messageData, messageType, lyricsIndex) => {
const text = new TextDecoder("utf-8").decode(messageData.buffer);
console.log("Text event:", text)
}
Parameters:
- messageData -
Uint8Array
, the message's data (excluding the statusByte). - messageType - the Status byte of the meta-message useful for determining if the message is lyrics, or something else.
- lyricsIndex -
number
, the index of the lyrics in the song (midiData.lyrics
array). If the event is not lyrics, it will be -1.
A callback function if defined. Will be called on MIDI parsing error.
sequencer.onError = e => {
console.log(e);
}
- e -
string
, the error message. For exampleInvalid MIDI Header! Expected "MThd", got "#!/u"