Class MidiFileWriter2

The class MidiFileWriter2, available with MPTK Pro V2.85 , is useful to create Midi file by script. It replaces the class MidiFileWriter which is deprecated. MidiFileWriter2 proposes a more consistent behavior with the others classes of MPTK and new helpful functions.

  • Channel from 0 to 15
  • Methods for all Midi events
  • Better errors check

This page could help you also Midi Timing and also this one Integration of MPTK by script

The demonstration TestMidiWriter could help you to begin with this class:

The schema is classical and you will find all the detail for the class MidiFileWriter2 here in the documentation or from the PDF asset in Unity:

  • Create a MidiFileWriter2.
  • Create Tracks, minium one.
  • Add Midi Event (note, preset change, …).
  • Close each tracks.
  • Write the Midi file.

See below an extract of the demonstration script. The most important methods from the class MidiFileWriter2 are highlighted.

int track0 = 0; // use of variable to be more understandable int track1 = 1; int channel0 = 0; // we are using only one channel in this demo // https://paxstellar.fr/2020/09/11/midi-timing/ int beatsPerMinute = 60; int ticksPerQuarterNote = 120; // a classical value for a Midi. define the precision of the note playing in time long absoluteTime = 0; // Time to play a note expressed in 'ticksPerQuarterNote' // Create a Midi file of type 1 // with 120 ticks for a quarter (no impact on tempo but on precision) // Then, all duration are expressed in ticks, so this value can be used to convert // duration notes as quarter to ticks. https://paxstellar.fr/2020/09/11/midi-timing/ MidiFileWriter2 mfw = new MidiFileWriter2(ticksPerQuarterNote, 1); // First track (index=0) is a general midi information track, lyrics, tempo change. By convention contains no noteon. // Second track (index=1) will contains the notes, preset change, .... all events associated to a channel. // But you can arrange your song as you want. mfw.MPTK_CreateTrack(2); // Some textual information added to the track 0 at time=0 mfw.MPTK_AddText(track0, absoluteTime, MPTKMeta.SequenceTrackName, "Midi Generated with MPTK, tempo and preset change"); // TimeSignatureEvent (not mandatory) https://paxstellar.fr/2020/09/11/midi-timing/ // Numerator(number of beats in a bar, // Denominator(which is confusingly) in 'beat units' so 1 means 2, 2 means 4(crochet), 3 means 8(quaver), 4 means 16 and 5 means 32), mfw.MPTK_AddTimeSignature(track0, absoluteTime, 4, 2); // Playing tempo is defined in beat per minute (not mandatory) at time=0 // with beatsPerMinute set to 60 at start, it's a slow tempo, one quarter per second. mfw.MPTK_AddTempoChange(track0, absoluteTime, MidiFileWriter2.MPTK_GetMicrosecondsPerQuaterNote(beatsPerMinute)); // Preset to use for channel 1. Generally 25 is Acoustic Guitar, see https://en.wikipedia.org/wiki/General_MIDI mfw.MPTK_AddChangePreset(track0, absoluteTime, channel0, 25); // Add three notes : 60 (C5) 60 (D4) 64 (E5) with a duration of one quarter // and velocity at 50 at start with increase until 100 mfw.MPTK_AddNote(track1, absoluteTime, channel0, 60, 50, ticksPerQuarterNote); // Next note will be played just after the previous, so move absoluteTime for one quarternote absoluteTime += ticksPerQuarterNote; mfw.MPTK_AddNote(track1, absoluteTime, channel0, 62, 80, ticksPerQuarterNote); // Next note will be played just after the previous absoluteTime += ticksPerQuarterNote; // Play a note with a duration = 2 quarter mfw.MPTK_AddNote(track1, absoluteTime, channel0, 64, 100, 2 * ticksPerQuarterNote); // Some lyrics added to the track 0 mfw.MPTK_AddText(track0, absoluteTime, MPTKMeta.Lyric, "Add pitch wheel effect"); // Apply pitch wheel on the channel 1 by 10 steps for a duration of 2 quarter for (float pitch = 1f; pitch <= 2f; pitch += 0.1f) { mfw.MPTK_AddPitchWheelChange(track1, absoluteTime, channel0, pitch); // 10 steps and a duration of 2 quarter absoluteTime += ticksPerQuarterNote * 2 / 10; } // Double the tempo beatsPerMinute = beatsPerMinute * 2; mfw.MPTK_AddTempoChange(track0, absoluteTime, MidiFileWriter2.MPTK_GetMicrosecondsPerQuaterNote(beatsPerMinute)); // Patch/preset to use for channel 1. Generally 11 is Music Box, see https://en.wikipedia.org/wiki/General_MIDI mfw.MPTK_AddChangePreset(track1, absoluteTime, channel0, 11); // Add sixteenth notes (duration quarter / 4) : for (int note = 64; note <= 84; note += 2) { mfw.MPTK_AddNote(track1, absoluteTime, channel0, note, 100, ticksPerQuarterNote / 4); absoluteTime += ticksPerQuarterNote / 4; } // Add a last whole note (4 quarter duration) mfw.MPTK_AddNote(track1, absoluteTime, channel0, 85, 100, ticksPerQuarterNote * 4); // Some lyrics added to the track 0 mfw.MPTK_AddText(track0, absoluteTime, MPTKMeta.Lyric, "Add Vibrato"); // Apply modulation change, (vibrato for a Vibraphone) mfw.MPTK_AddControlChange(track1, absoluteTime, channel0, MPTKController.Modulation, 127); absoluteTime += ticksPerQuarterNote * 4; mfw.MPTK_AddText(track0, absoluteTime, MPTKMeta.Lyric, "Silence now!"); // It's better to not stop the playing just after the last note. // Add a silence, but silence does'nt exists in Midi, so add a note with velocity=0 mfw.MPTK_AddNote(track1, absoluteTime + ticksPerQuarterNote, channel0, 60, 0, ticksPerQuarterNote); // It's mandatory to close all tracks before writing the file mfw.MPTK_EndTrack(track0); mfw.MPTK_EndTrack(track1); // build the path + filename to the midi string filename = Path.Combine(Application.persistentDataPath, filanme); // write the midi file mfw.MPTK_WriteToFile(filename); midiExternalPlayer.MPTK_MidiName = "file://" + filename; midiExternalPlayer.MPTK_Play();