Skip to contents
library(midiblender)

The midi-construct functions are helpers for building a valid midi_df data frame using dplyr syntax.

These functions can be useful for constructing blocks of meta_messages, or whole midi_dfs. The functions are mostly wrapping dplyr::add_row(). The advantage of wrapping is that important parameters become available with auto-complete.

new_midi_df <- create_empty_midi_df() %>% # initialize 
  add_meta_track_name(name = "My track") %>%
  add_meta_tempo(tempo = 500000) %>%
  add_meta_time_sig(numerator = 4,
                    denominator = 4,
                    clocks_per_click = 36,
                    notated_32nd_notes_per_beat = 8) %>%
  add_program_change(program = 0,
                     channel = 0) %>%
  add_control_change(control = 0,value = 0) %>%
  add_note_on(time = 0,note = 60) %>%
  add_note_off(time = 8,note = 60) %>%
  add_meta_end_of_track()

knitr::kable(new_midi_df)

##############
# write midi

#Initialize new pyramidi object
new_pyramidi_object <- pyramidi::MidiFramer$new()
# update ticks per beat
new_pyramidi_object$ticks_per_beat <- 96L
# update object with new midi df
new_pyramidi_object$mf$midi_frame_unnested$update_unnested_mf(new_midi_df)
# write to midi file
new_pyramidi_object$mf$write_file("file_name.mid")
  

Mono lead example

This code chunk generates a random series of notes from a vector of possible notes.

# note parameters
num_notes <- 128
note_duration <- 24
possible_notes <- c(60, 63, 65, 66, 67, 70, 72, 75)

new_midi_df <- create_empty_midi_df() %>% # initialize 
  add_meta_track_name(name = "My track") %>%
  add_meta_tempo(tempo = 500000) %>%
  add_meta_time_sig(numerator = 4,
                    denominator = 4,
                    clocks_per_click = 36,
                    notated_32nd_notes_per_beat = 8) %>%
  add_program_change(program = 0,
                     channel = 0) %>%
  add_control_change(control = 0,value = 0) %>%
  #use dplyr::add_row to add a bunch of notes
  add_row(
    i_track = 0,
    meta = FALSE,
    type = rep(c("note_on", "note_off"),num_notes),
    time = rep(c(0, note_duration), num_notes),
    note = rep(sample(possible_notes,
                  size = num_notes,
                  replace= TRUE),each=2)
  ) %>%
  add_meta_end_of_track()


##############
# write midi

#Initialize new pyramidi object
new_pyramidi_object <- pyramidi::MidiFramer$new()
# update ticks per beat
new_pyramidi_object$ticks_per_beat <- 96L
# update object with new midi df
new_pyramidi_object$mf$midi_frame_unnested$update_unnested_mf(new_midi_df)
# write to midi file
new_pyramidi_object$mf$write_file("file_name.mid")

Composing with a wide data frame


# note parameters
bars <- 16
possible_time_steps <- 16
note_duration <- 24
possible_notes <- c(60, 63, 65, 66, 67, 70, 72, 75)

compose_notes <- tibble::tibble(note_id = integer(),
                             note = integer(),
                             beat_on = integer(),
                             note_on = integer(),
                             note_off = integer()) %>%
  # use euclidean rhythm
  rowwise() %>%
  add_row(beat_on = c(replicate(bars,bresenham_euclidean(sample(5:15,1),
                                            possible_time_steps,
                                            start=1))),
          note = sample(possible_notes, 
                        size = possible_time_steps*bars, 
                        replace= TRUE)) %>%
  ungroup() %>%
  # handle note times
  mutate(note_id = 1:n(),
         note_on = (1:n()-1)*note_duration,
         note_off = note_on+note_duration) %>%
  filter(beat_on == 1) %>%
  #pivot to long
  tidyr::pivot_longer(c("note_on","note_off"),names_to="type",values_to="time") %>%
  mutate(time = time - lag(time,default=0))

## add to a new midi df
new_midi_df <- create_empty_midi_df() %>% # initialize
  add_meta_track_name(name = "My track") %>%
  add_meta_tempo(tempo = 500000) %>%
  add_meta_time_sig(
    numerator = 4,
    denominator = 4,
    clocks_per_click = 36,
    notated_32nd_notes_per_beat = 8
  ) %>%
  add_program_change(program = 0,
                     channel = 0) %>%
  add_control_change(control = 0, value = 0) %>%
  #use dplyr::add_row to add a bunch of notes
  add_row(i_track = rep(0,dim(compose_notes)[1]), 
          meta = rep(FALSE,dim(compose_notes)[1]),
          note = compose_notes$note,
          type = compose_notes$type,
          time = compose_notes$time,
          velocity = 64) %>%
  add_meta_end_of_track()

#write midi
#Initialize new pyramidi object
new_pyramidi_object <- pyramidi::MidiFramer$new()
# update ticks per beat
new_pyramidi_object$ticks_per_beat <- 96L
# update object with new midi df
new_pyramidi_object$mf$midi_frame_unnested$update_unnested_mf(new_midi_df)
# write to midi file
new_pyramidi_object$mf$write_file("file_name.mid")