play_broken_chord Subroutine

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).

Type Bound

MIDI_file

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

Calls

proc~~play_broken_chord~~CallsGraph proc~play_broken_chord MIDI_file%play_broken_chord proc~checked_int32 checked_int32 proc~play_broken_chord->proc~checked_int32 proc~delta_time MIDI_file%delta_time proc~play_broken_chord->proc~delta_time proc~note_off MIDI_file%Note_OFF proc~play_broken_chord->proc~note_off proc~note_on MIDI_file%Note_ON proc~play_broken_chord->proc~note_on 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~checked_int8 checked_int8 proc~note_off->proc~checked_int8 proc~note_on->proc~checked_int8 proc~variable_length_quantity variable_length_quantity proc~write_variable_length_quantity->proc~variable_length_quantity

Called by

proc~~play_broken_chord~~CalledByGraph proc~play_broken_chord MIDI_file%play_broken_chord program~la_folia la_folia program~la_folia->proc~play_broken_chord program~motifs motifs program~motifs->proc~play_broken_chord

Source Code

    subroutine play_broken_chord(self, channel, note, chord, velocity, value, values)
        class(MIDI_file), intent(inout) :: self
        integer, intent(in)  :: channel, note     ! 8 bits
        integer, dimension(:), intent(in) :: chord
        integer, intent(in) :: velocity           ! 8 bits
        integer, optional, intent(in) :: value                   ! 32 bits
        integer, dimension(:), optional, intent(in) :: values    ! 32 bits
        integer, dimension(:), allocatable :: values_array
        integer(int32) :: dnote, residual
        integer :: i

        !> You must pass either a scalar value (whole duration) or a values array
        !> (containing the values for each note).
        if (((present(value).and.present(values)).or.(.not.present(value) .and. .not.present(values)))) then
            error stop "ERROR in play_broken_chord(): problem with value/values arguments"
        end if

        if (present(values)) then
            values_array = values
        else
            ! Each note will have the the same duration:
            dnote = nint(real(checked_int32(value)) / size(chord))
            ! The MIDI duration being an integer, the last note of the chord may
            ! have a slightly different duration to keep the total duration exact:
            residual = checked_int32(value) - dnote*(size(chord) - 1)
            allocate(values_array(size(chord)))
            values_array(1:size(chord)-1) = dnote
            values_array(size(chord)) = residual
        end if

        ! Each note is sequentially played:
        call self%delta_time(0)
        do i = 1, size(chord)
            call self%Note_ON(channel, note + chord(i), velocity)
            call self%delta_time(values_array(i))
        end do

        ! All notes are finally set off:
        do i = 1, size(chord)
            call self%Note_OFF(channel, note + chord(i))
            ! The delta time must always be placed before a note:
            if (i < size(chord)) call self%delta_time(0)
        end do

        deallocate(values_array)
    end subroutine play_broken_chord