canon Program

Uses

  • program~~canon~~UsesGraph program~canon canon module~gm_instruments GM_instruments program~canon->module~gm_instruments module~midi_control_changes MIDI_control_changes program~canon->module~midi_control_changes module~midi_file_class MIDI_file_class program~canon->module~midi_file_class module~music music program~canon->module~music iso_fortran_env iso_fortran_env module~midi_file_class->iso_fortran_env module~utilities utilities module~midi_file_class->module~utilities module~music->iso_fortran_env module~music_common music_common module~music->module~music_common module~music->module~utilities module~utilities->iso_fortran_env

An example based on the first measures of Pachelbel's Canon https://en.wikipedia.org/wiki/Pachelbel%27s_Canon


Calls

program~~canon~~CallsGraph program~canon canon proc~control_change MIDI_file%Control_Change program~canon->proc~control_change proc~end_of_track MIDI_file%end_of_track program~canon->proc~end_of_track proc~get_name MIDI_file%get_name program~canon->proc~get_name proc~midi_note MIDI_Note program~canon->proc~midi_note proc~new MIDI_file%new program~canon->proc~new proc~play_note MIDI_file%play_note program~canon->proc~play_note proc~program_change MIDI_file%Program_Change program~canon->proc~program_change proc~track_header MIDI_file%track_header program~canon->proc~track_header proc~checked_int8 checked_int8 proc~control_change->proc~checked_int8 proc~delta_time MIDI_file%delta_time proc~control_change->proc~delta_time proc~end_of_track->proc~delta_time proc~write_track_size MIDI_file%write_track_size proc~end_of_track->proc~write_track_size proc~new->proc~end_of_track proc~new->proc~track_header proc~checked_int16 checked_int16 proc~new->proc~checked_int16 proc~checked_int32 checked_int32 proc~new->proc~checked_int32 proc~new->proc~checked_int8 proc~copyright_notice MIDI_file%copyright_notice proc~new->proc~copyright_notice proc~init_formidi MIDI_file%init_formidi proc~new->proc~init_formidi proc~set_tempo MIDI_file%set_tempo proc~new->proc~set_tempo proc~set_time_signature MIDI_file%set_time_signature proc~new->proc~set_time_signature proc~text_event MIDI_file%text_event proc~new->proc~text_event proc~play_note->proc~checked_int32 proc~play_note->proc~delta_time proc~note_off MIDI_file%Note_OFF proc~play_note->proc~note_off proc~note_on MIDI_file%Note_ON proc~play_note->proc~note_on proc~program_change->proc~checked_int8 proc~program_change->proc~delta_time proc~sequence_track_name MIDI_file%sequence_track_name proc~track_header->proc~sequence_track_name proc~track_header->proc~text_event proc~write_string MIDI_file%write_string proc~copyright_notice->proc~write_string proc~delta_time->proc~checked_int32 proc~write_variable_length_quantity MIDI_file%write_variable_length_quantity proc~delta_time->proc~write_variable_length_quantity proc~note_off->proc~checked_int8 proc~note_on->proc~checked_int8 proc~sequence_track_name->proc~write_string proc~set_tempo->proc~checked_int32 proc~set_tempo->proc~delta_time proc~set_time_signature->proc~checked_int8 proc~set_time_signature->proc~delta_time proc~text_event->proc~write_string proc~write_string->proc~checked_int8 proc~write_string->proc~delta_time proc~write_string->proc~write_variable_length_quantity proc~variable_length_quantity variable_length_quantity proc~write_variable_length_quantity->proc~variable_length_quantity

Variables

Type Attributes Name Initial
character(len=3), parameter :: bass(1:8) = ["D3 ", "A2 ", "B2 ", "F#2", "G2 ", "D2 ", "G2 ", "A2 "]
integer :: i
integer, parameter :: instrument(1:17) = [40, 41, 42, 44, 45, 48, 49, 51, 52, 89, 90, 91, 92, 94, 95, 99, 100]
integer :: j
type(MIDI_file) :: midi
integer, parameter :: panning(2:5) = [54, 34, 74, 94]
character(len=3), parameter :: theme(1:16) = ["F#5", "E5 ", "D5 ", "C#5", "B4 ", "A4 ", "B4 ", "C#5", "D5 ", "C#5", "B4 ", "A4 ", "G4 ", "F#4", "G4 ", "E4 "]
integer :: track
character(len=13) :: track_name

Source Code

program canon
    use MIDI_file_class
    use music
    use MIDI_control_changes, only: Effects_1_Depth, Pan
    ! Contains the list of General MIDI 128 instruments and 47 percussions:
    use GM_instruments

    implicit none
    type(MIDI_file) :: midi
    ! Notes of the bass and theme:
    character(3), parameter :: bass(1:8) =  ["D3 ","A2 ","B2 ","F#2","G2 ", &
                                            &"D2 ","G2 ","A2 " ]
    character(3), parameter :: theme(1:16) = [ "F#5","E5 ","D5 ","C#5", &
                                             & "B4 ","A4 ","B4 ","C#5", &
                                             & "D5 ","C#5","B4 ","A4 ", &
                                             & "G4 ","F#4","G4 ","E4 " ]
    ! List of General MIDI instruments to use sequentially:
    integer, parameter :: instrument(1:17) = [ 40, 41, 42, 44, 45, 48,&
                                 & 49, 51, 52, 89, 90, 91, 92, 94, 95, 99, 100 ]
    ! Pan value for each track:
    integer, parameter :: panning(2:5) = [ 54, 34, 74, 94 ]
    integer :: track
    character(13) :: track_name
    integer :: i, j

    ! Create a file with 5 tracks (including the metadata track):
    ! A quarter note will last 1000000 µs = 1 s => tempo = 60 bpm
    call midi%new("canon.mid", format=1, tracks=5, divisions=quarter_note, tempo=1000000, copyright="Public domain")

    ! (1) A first music track: ground bass
    call midi%track_header(track_name="ground bass")
    call midi%Control_Change(channel=0, type=Effects_1_Depth, ctl_value=64)  ! Reverb
    ! Instrument on channel 0:
    call midi%Program_Change(channel=0, instrument=String_Ensemble_1)
    ! Panning:
    call midi%Control_Change(channel=0, type=Pan, ctl_value=panning(2))

    do j = 1, 30
        do i = 1, 8
            call midi%play_note(channel=0, note=MIDI_Note(bass(i)), velocity=mf_level, value=quarter_note)
        end do
    end do
    call midi%end_of_track()

    ! Three other music tracks: a three voices canon with various instruments
    do track = 3, 5
        write(track_name, '("Canon voice ",I0)') track-2
        call midi%track_header(track_name)

        ! Reverb and pan:
        call midi%Control_Change(channel=track, type=Effects_1_Depth, ctl_value=64)
        call midi%Control_Change(channel=track, type=Pan, ctl_value=panning(track))

        ! A pause to shift the start of each voice of the canon:
        call midi%play_note(channel=track, note=0, velocity=0, value=8*quarter_note*(track - 2))

        do j = 1, 15
            ! Let's change regularly the instruments to add some variations:
            call midi%Program_Change(channel=track, instrument=instrument((track - 3) + j))
            ! Let's play the theme:
            do i = 1, 16
                call midi%play_note(channel=track, note=MIDI_Note(theme(i)), velocity=mf_level, value=quarter_note)
            end do
        end do

        call midi%end_of_track()
    end do

    call midi%close()

    print *,"You can now play the file ", midi%get_name()
end program canon