library(midiblender)
library(dplyr)
library(pyramidi)
library(fluidsynth)
all_tracks <- data.frame()
# note parameters
bars <- 12
repeat_bars <- 2
possible_time_steps <- 16
note_interval <- 24
note_duration <- 48
track_params <- list(track_1_kick =
list(possible_notes = rep(1:5, times = rep(5,2,1,1,1)),
key_vector = rep(rep(c(0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 10, 15),
each = possible_time_steps),
times = repeat_bars),
possible_beats = rep(c(5, 11), times=c(7,1)),
program = 0,
channel = 1
),
track_2_snare =
list(possible_notes = rep(1:5, times = rep(5,2,1,1,1)),
key_vector = rep(rep(c(0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 10, 15),
each = possible_time_steps),
times = repeat_bars),
possible_beats = rep(c(1, 2, 7), times=c(4,1,1)),
program = 1,
channel = 2
),
track_3_cymb =
list(possible_notes = rep(1:5, times = rep(5,2,1,1,1)),
key_vector = rep(rep(c(0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 10, 15),
each = possible_time_steps),
times = repeat_bars),
possible_beats = rep(c(8, 11, 12, 16), times=c(4,1,1,1)),
program = 2,
channel = 3
)
)
# loop for each track
for(t in 1:3) {
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*repeat_bars,
bresenham_euclidean(sample(track_params[[t]]$possible_beats, 1),
possible_time_steps,
start = 1)
)),
note = sample(track_params[[t]]$possible_notes,
size = possible_time_steps * (bars*repeat_bars),
replace = TRUE) + track_params[[t]]$key_vector
) %>%
ungroup() %>%
# handle note times
mutate(
note_id = 1:n(),
note_on = (1:n() - 1) * note_interval,
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") %>%
arrange(time) %>%
mutate(time = time - lag(time, default = 0),
channel = track_params[[t]]$channel)
######################
# End composition
#######################
## add composition 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 = track_params[[t]]$program,
channel = track_params[[t]]$channel) %>%
add_control_change(control = 0, value = 0) %>%
# Composition added here
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,
channel = compose_notes$channel,
velocity = sample(100L:112L,dim(compose_notes)[1],replace=T)
#velocity = 64
) %>%
add_meta_end_of_track() %>%
mutate(i_track = t) %>%
mutate(velocity = case_when(type == "note_on" ~ velocity,
type == "note_off" ~ 0))# set current track number
all_tracks <- rbind(all_tracks,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(all_tracks)
# write to midi file
new_pyramidi_object$mf$write_file("TE-EP-133-B.mid")
# play
fluidsynth::midi_play(midi = "TE-EP-133-B.mid",soundfont = "~/Library/Audio/Sounds/Banks/TE-EP-133-A.sf2")
#bounce
fluidsynth::midi_convert(midi = "TE-EP-133-B.mid",
soundfont = "~/Library/Audio/Sounds/Banks/TE-EP-133-A.sf2",
output = "TE-EP-133-B.mp3")