MIDI_file_class Module

Contains the main class you need to create a MIDI file.


Uses

  • module~~midi_file_class~~UsesGraph module~midi_file_class MIDI_file_class iso_fortran_env iso_fortran_env module~midi_file_class->iso_fortran_env module~utilities utilities module~midi_file_class->module~utilities module~utilities->iso_fortran_env

Used by

  • module~~midi_file_class~~UsedByGraph module~midi_file_class MIDI_file_class program~blues blues program~blues->module~midi_file_class program~canon canon program~canon->module~midi_file_class program~circle_of_fifths circle_of_fifths program~circle_of_fifths->module~midi_file_class program~la_folia la_folia program~la_folia->module~midi_file_class program~motifs motifs program~motifs->module~midi_file_class program~third_kind third_kind program~third_kind->module~midi_file_class

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: OFF = 128
integer, public, parameter :: ON = 144

Used by Note ON and Note OFF events:

integer, public, parameter :: drums = 9

Useful MIDI parameters Percussions channel (in the 0..15 range):


Derived Types

type, public ::  MIDI_file

The main class you need to create a MIDI file.

Components

Type Visibility Attributes Name Initial
character(len=:), private, allocatable :: filename
integer(kind=int32), private :: size_pos
integer, private :: status
integer, private :: unit

Type-Bound Procedures

procedure, public :: Control_Change
procedure, public :: Note_OFF
procedure, public :: Note_ON
procedure, public :: Pitch_Bend
procedure, public :: Program_Change
procedure, public :: close
procedure, public :: cue_point
procedure, public :: delta_time
procedure, public :: end_of_track
procedure, public :: get_name
procedure, public :: instrument_name
procedure, public :: lyric
procedure, public :: marker
procedure, public :: new
procedure, public :: play_broken_chord
procedure, public :: play_chord
procedure, public :: play_note
procedure, public :: sequence_track_name
procedure, public :: set_tempo
procedure, public :: set_time_signature
procedure, public :: text_event
procedure, public :: track_header
procedure, private :: copyright_notice
procedure, private :: init_formidi
procedure, private :: write_string
procedure, private :: write_track_size
procedure, private :: write_variable_length_quantity

Functions

public function get_name(self)

Returns the name of the MIDI file:

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(in) :: self

Return Value character(len=len(self%filename))

public pure function variable_length_quantity(i) result(VLQ)

MIDI delta times are composed of one to four bytes, depending on their values. If there is still bytes to write, the MSB (most significant bit) of the current byte is 1, else 0. This functions is automatically tested. https://en.wikipedia.org/wiki/Variable-length_quantity

Arguments

Type IntentOptional Attributes Name
integer(kind=int32), intent(in) :: i

Return Value integer(kind=int8), allocatable, dimension(:)


Subroutines

public subroutine Control_Change(self, channel, type, ctl_value)

Many MIDI parameters can be set by Control Change. See the list.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: type
integer, intent(in) :: ctl_value

public subroutine Note_OFF(self, channel, note, velocity)

Writes a Note OFF event. MIDI notes are in the range 0..127 The release velocity is in the range 0..127.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: note
integer, intent(in), optional :: velocity

public subroutine Note_ON(self, channel, note, velocity)

Writes a Note ON event. MIDI notes are in the range 0..127 The attack velocity is in the range 1..127 and will set the volume. A Note ON event with a zero velocity is equivalent to a Note OFF.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: note
integer, intent(in) :: velocity

public subroutine Pitch_Bend(self, channel, lsb, msb)

Apply a pitch bend to all notes currently sounding on the channel. No bend is 00 40 (64 in decimal), maximum downward bend is 00 00, maximum upward bend is 7F 7F. The Least Significant Byte (lsb) is optional (default value is 0), as it is useful only for fine adjustment. You can not use it with play_note, play_chord or play_broken_chord: you must manage yourself the Note ON and Note OFF events, and put the bend between.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in), optional :: lsb
integer, intent(in) :: msb

public subroutine Program_Change(self, channel, instrument)

Each channel (0..15) can use one General MIDI instrument (0..127) at a time.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: instrument

public subroutine close(self)

Closes the MIDI file.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self

public subroutine copyright_notice(self, text)

Copyright Notice event: FF 02 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine cue_point(self, text)

Cue Point event: FF 07 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine delta_time(self, ticks)

Each MIDI event must be preceded by a delay called "delta time", expressed in MIDI ticks.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: ticks

public subroutine end_of_track(self)

A track must end with 0xFF2F00.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self

public subroutine init_formidi(self)

Verifies the needed data types.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(in) :: self

public subroutine instrument_name(self, text)

Instrument Name event: FF 04 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine lyric(self, text)

Lyric event: FF 05 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine marker(self, text)

Marker event: FF 06 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine new(self, file_name, format, tracks, divisions, tempo, time_signature, copyright, text_event)

Create a new MIDI file and its metadata track. Concerning the "divisions" argument, ForMIDI uses the "metrical timing" scheme, defining the number of ticks in a quarter note. The "timecode" scheme is not implemented. SMF format: 0: only one track in the file 1: several tracks played together (generally used) 2: several tracks played sequentially

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: file_name
integer, intent(in) :: format
integer, intent(in) :: tracks
integer, intent(in) :: divisions
integer, intent(in) :: tempo
integer, intent(in), optional :: time_signature(:)
character(len=*), intent(in), optional :: copyright
character(len=*), intent(in), optional :: text_event

public subroutine play_broken_chord(self, channel, note, chord, velocity, value, values)

Writes a broken chord using an array containing the intervals (see the music_common module). https://en.wikipedia.org/wiki/Arpeggio You must pass either a scalar value (whole duration) or a values array (containing the values for each note).

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: note
integer, intent(in), dimension(:) :: chord
integer, intent(in) :: velocity
integer, intent(in), optional :: value
integer, intent(in), optional, dimension(:) :: values

public subroutine play_chord(self, channel, note, chord, velocity, value)

Writes a chord, waits for its duration, and writes the OFF events

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: note
integer, intent(in), dimension(:) :: chord
integer, intent(in) :: velocity
integer, intent(in) :: value

public subroutine play_note(self, channel, note, velocity, value)

Write a Note ON event, waits for its duration, and writes a Note OFF.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: channel
integer, intent(in) :: note
integer, intent(in) :: velocity
integer, intent(in) :: value

public subroutine sequence_track_name(self, text)

Sequence or Track Name event: FF 03 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine set_tempo(self, duration)

Specifies a tempo change by writing the duration of a quarter note expressed in µs. It is coded on 3 bytes: from 1 µs to 256**3 µs ~ 16.7 s. A duration of 500000 µs = 0.5 s is equivalent to a 120 bpm tempo. https://en.wikipedia.org/wiki/Tempo MIDI events must always be preceded by a "delta time", even if null:

Read more…

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: duration

public subroutine set_time_signature(self, numerator, denominator, metronome, tsnotes)

The time signature includes the numerator, the denominator, the number of MIDI clocks between metronome ticks, (there are 24 MIDI clocks per quarter note) and the number of 32nd notes in a quarter note. The number of "MIDI clocks" between metronome clicks.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: numerator
integer, intent(in) :: denominator
integer, intent(in) :: metronome
integer, intent(in), optional :: tsnotes

public subroutine text_event(self, text)

Text event: FF 01 len text

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in) :: text

public subroutine track_header(self, track_name, text_event)

Writes a track header and stores the position where the size of the track will be written when the track will be closed.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
character(len=*), intent(in), optional :: track_name
character(len=*), intent(in), optional :: text_event

public subroutine write_string(self, event, text)

This subroutine is used my many events. The text must be coded in ASCII (7 bits).

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer, intent(in) :: event
character(len=*), intent(in) :: text

public subroutine write_track_size(self)

Must be called when the track is finished. It writes its size at the memorized position in the track header.

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self

public subroutine write_variable_length_quantity(self, i)

Writes the integer i in the MIDI file using the variable length quantity representation:

Arguments

Type IntentOptional Attributes Name
class(MIDI_file), intent(inout) :: self
integer(kind=int32), intent(in) :: i