spessasynth_core documentation
    Preparing search index...

    Class BasicMIDI

    BasicMIDI is the base of a complete MIDI file. It represents a single MIDI sequence, with an optional sound bank attached to it.

    Initialize the class using BasicMIDI.fromArrayBuffer.

    Hierarchy (View Summary)

    Index
    bankOffset: number = 0

    The bank offset used for RMID files. Only applies to RMID, for normal MIDIs it's set to 0.

    binaryName?: Uint8Array<ArrayBufferLike>

    The raw, encoded MIDI name, represented as a Uint8Array. Useful when the MIDI file uses a different code page. Undefined if no MIDI name could be found.

    duration: number = 0

    The duration of the sequence, in seconds.

    embeddedSoundBank?: ArrayBuffer

    The embedded sound bank in the MIDI file, represented as the binary ArrayBuffer, if available. It will be undefined for regular MIDI files.

    extraMetadata: MIDIMessage[] = []

    Any extra metadata found in the file. These messages were deemed "interesting" by the parsing algorithm and can be displayed by the MIDI player as some form of metadata.

    fileName?: string

    The file name of the MIDI sequence, if provided during parsing.

    firstNoteOn: number = 0

    The MIDI tick time of the first note-on event in the MIDI sequence.

    format: MIDIFormat = 0

    The MIDI file format. Usually 0 or 1, rarely 2, indicating the type of the MIDI file.

    isDLSRMIDI: boolean = false

    If the MIDI file is a DLS RMIDI file.

    isKaraokeFile: boolean = false

    If the MIDI file is a Soft Karaoke file (.kar), this is set to true. More information about this format here.

    isMultiPort: boolean = false

    Indicates if this file is a Multi-Port MIDI file.

    keyRange: GenericRange = ...

    The MIDI key range used in the sequence, represented by a minimum and maximum MIDI note numbers.

    lastVoiceEventTick: number = 0

    The MIDI tick time of the last voice event (such as note-on, note-off, or control change) in the sequence.

    loop: MIDILoop = ...

    The loop points (in ticks) of the sequence, including both start and end points.

    If there's nothing detected, the loop will start from the first note on event and end will be the last voice message. Current looping detection is: CC 2/4, 116/117 and "start," "loopStart" and "loopEnd" markers.

    lyrics: MIDIMessage[] = []

    An array containing the lyrics of the sequence.

    portChannelOffsetMap: number[] = ...

    An array of channel offsets for each MIDI port, using the SpessaSynth method. The index is the port number and the value is the channel offset.

    rmidiInfo: Partial<Record<keyof RMIDInfoData, Uint8Array<ArrayBuffer>>> = {}

    The RMID (Resource-Interchangeable MIDI) info data, if the file is RMID formatted. Otherwise, this object is empty. Info type: Chunk data as a binary array.

    tempoChanges: TempoChange[] = ...

    The tempo changes in the sequence, ordered from the last change to the first. Each change is represented by an object with a MIDI tick position and a tempo value in beats per minute.

    It will always contain at least one tempo change (the default 120BPM at zero ticks).

    [
    {
    tempo: 140 // tempo in BPM ,
    ticks: 5437 // absolute amount of MIDI Ticks from the start
    },

    // ...

    {
    // the default tempo change
    tempo: 120,
    ticks: 0
    }
    ];
    timeDivision: number = 480

    The time division of the MIDI file. The amount of MIDI ticks per beat, usually 480 ticks. Essentially the resolution of the file.

    For example a time division of 1 would mean that one MIDI tick (the smallest time unit) lasts one beat, so no shorter notes can be stored in the file.

    timeline: readonly Readonly<TimelineEvent>[] = []

    A flattened, time‑sorted list of all events in the MIDI sequence. The order between the tracks is preserved. Each entry points to the event's track number and its index within that track.

    tracks: MIDITrack[] = []

    The tracks in the sequence, represented as an array of MIDITrack.

    • get infoEncoding(): string | undefined

      The encoding of the RMIDI info in file (for example Shift_JIS or utf-8), if specified. Otherwise, undefined.

      Returns string | undefined

    • Applies a SynthesizerSnapshot to the sequence in place. This means changing the programs and controllers if they are locked.

      For example, if channel 1 has locked preset on Drawbar Organ, this will remove all program changes for channel 1 and add one at the start to change the program to Drawbar organ (using bank MSB/LSB and program change).

      Parameters

      Returns void

    • Updates all parameters. Call this after editing the contents of BasicMIDI.tracks (the events).

      This updates parameters like firstNoteOn, lastVoiceEventTick or loop.

      Parameters

      • sortEvents: boolean = true

        if the events should be sorted by ticks. Recommended to be true.

      Returns void

    • Gets the decoded extra metadata as text and removes any unneeded characters (such as @T for karaoke files)

      Parameters

      • encoding: string = "Shift_JIS"

        The encoding to use if the MIDI uses an extended code page.

      Returns string[]

      An array of strings - each extraMetadata decoded and sanitized.

    • Gets the MIDI's decoded name.

      Parameters

      • encoding: string = "Shift_JIS"

        The encoding to use if the MIDI uses an extended code page.

      Returns string | undefined

      The name of the song or the file name if it's not specified. Empty otherwise.

    • Calculates all note times in seconds.

      Parameters

      • minDrumLength: number = 0

        In seconds, represents the minimum allowed time for a drum note, since they sometimes have a length of 0.

      Returns NoteTime[][]

      An array of 16 channels, each channel containing its notes, with their key number, velocity, absolute start time and length in seconds.

      const data = [
      [{ midiNote: 60, velocity: 100, start: 0.5, length: 0.25 }], // channel 1
      // other 14 channels...
      [{ midiNote: 36, velocity: 96, start: 41.54, length: 0.1 }] // channel 16
      ];
    • Iterates over the MIDI file, ordered by the time the events happen.

      If the track data is being edited, remember to call <a href="#flush" class="tsd-kind-method">BasicMIDI.flush</a> it after editing!
      

      Parameters

      • callback: (event: MIDIMessage, trackNumber: number, eventIndexes: number[]) => unknown

        The callback function to process each event.

      Returns void

    • Converts MIDI ticks to time in seconds.

      Parameters

      • ticks: number

        The time in MIDI ticks.

      Returns number

      The returned value is the time in seconds from the start of the MIDI to the given tick.

    • Allows easily modifying the sequence's programs and controllers. This is a very sophisticated method that supports various MIDI systems and inserts/deletes messages appropriately.

      This modifies the MIDI sequence in-place.

      Parameters

      Returns void

    • Converts seconds to time in MIDI ticks.

      Parameters

      • seconds: number

        The time in seconds.

      Returns number

      The returned value is the time in MIDI ticks from the start of the MIDI to the given second.

    • Exports the midi as a standard MIDI file.

      Returns ArrayBuffer

      A binary representation of the Standard MIDI File.

      Below is a basic example of writing a modified MIDI file:

      // Create your midi and synthesizer
      const midi = BasicMIDI.fromArrayBuffer(yourBufferGoesHere);
      const synth = new SpessaSynthProcessor(44100);

      // ...

      // Get the snapshot and apply it
      const snapshot = synth.getSnapshot();
      midi.applySnapshot(snapshot);

      // Write midi
      const midiBinary = midi.writeMIDI();

      // Save the file
      const blob = new Blob([midiBinary], { type: "audio/midi" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = midi.getName() + ".mid";
      a.click();
    • Writes out an RMIDI file (MIDI + SF2). See more info about this format.

      Note that this method modifies the MIDI file in-place.

      The method is called on a BasicMIDI instance; that instance is the MIDI file to embed.

      Parameters

      • soundBankBinary: ArrayBuffer

        The binary sound bank (SF2 or DLS) to embed into the file.

      • configuration: Partial<RMIDIWriteOptions> = DEFAULT_RMIDI_WRITE_OPTIONS

        Extra options for writing the file.

      Returns ArrayBuffer

      the binary file data.

      Below is a simple example for exporting an RMIDI file

      <label for="soundfont_upload">Upload soundfont</label>
      <input type="file" id="soundfont_upload" />
      <label for="midi_upload">Upload MIDI</label>
      <input type="file" id="midi_upload" />
      <button id="export">Export</button>
      const sfInput = document.getElementById("soundfont_upload");
      const midiInput = document.getElementById("midi_upload");
      document.getElementById("export").onclick = async () => {
      // get the files
      const soundBank = SoundBankLoader.fromArrayBuffer(
      await sfInput.files[0].arrayBuffer()
      );
      const midi = BasicMIDI.fromArrayBuffer(
      await midiInput.files[0].arrayBuffer()
      );

      // trim the soundfont
      soundBank.trim(midi.getUsedProgramsAndKeys(soundBank));
      // write out with compression to save space (0.5 is medium quality)
      await soundBank.setSampleFormat({
      format: "compressed",
      compressionFunction: SampleEncodingFunction // Remember to get your compression function
      });
      const soundfontBinary = soundBank.writeSF2();
      // get the rmidi
      const rmidiBinary = midi.writeRMIDI(soundfontBinary, {
      soundBank,
      metadata: {
      name: "A cool song",
      artist: "John",
      creationDate: new Date(),
      album: "John's songs",
      genre: "Rock",
      comment: "My favorite!"
      }
      });

      // save the file
      const blob = new Blob([rmidiBinary], { type: "audio/rmid" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = midi.getName() + ".rmi";
      a.click();
      };
    • Loads a MIDI file (SMF, RMIDI, XMF, MOD, XM, S3M) from a given ArrayBuffer.

      Parameters

      • arrayBuffer: ArrayBuffer

        The ArrayBuffer containing the binary file data.

      • fileName: string = ""

        The optional name of the file, will be used if the MIDI file does not have a name.

      Returns BasicMIDI

      This function reads the MIDI file format, extracts the header and track chunks, and populates the BasicMIDI instance with the parsed data. It supports Standard MIDI Files (SMF), RIFF MIDI (RMIDI), and Extensible Music Format (XMF). It also handles embedded soundbanks in RMIDI files. Tracker modules (ProTracker MOD, Fast Tracker 2 XM, Scream Tracker 3 S3M) are converted into MIDI with an embedded sound bank.