The class MidiFramer
can be used to read midi files to
dataframes in order to facilitate to manipulate the data from R. You can also
create midi data from R without reading it from a file.
The data is transformed to various formats.
One of the MidiFramer
fields is a
MidiFrames
object of the python miditapyr package. Its method
write_file()
can be used to write the data back to a midi file.
Details
See the
vignette("pyramidi")
for a brief usage introduction how to manipulate midi data.The
vignette("compose")
shows a more extended example how to generate midi files from scratch.vignette("package_workflow")
shows in detail the structure of theMidiFramer
class.vignette("functions_usage")
illustrates the low-level functions of the pyramidi package. thatMidiFramer
objects use under the hood.
Public fields
midi_file_string
Path to the midi file.
mf
miditapyr$MidiFrames
object.dfm
result of
tab_measures()
.df_notes_long
Result of
pivot_long_notes()
.df_meta, df_not_notes, df_notes_wide
Results of
split_midi_frame()
.midi_frame_mod
Result of
merge_midi_frames()
.params
Parameters used in internal functions; Named list; params$columns_to_add is passed to
tab_measures(columns_to_add)
.
Active bindings
df_meta, df_not_notes, df_notes_wide
Results of
split_midi_frame()
.ticks_per_beat
Set ticks per beat of
MidiFrames()$mf$midi_file
. The value ofticks_per_beat
passed should be integer. When a value is passed, the fieldmf$midi_file$ticks_per_beat
is modified.
Methods
Method update_notes_wide()
Update a MidiFramer object with modified notes
Examples
\dontrun{
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
mfr <- MidiFramer$new(midi_file_string)
# Function to replace every note with a random midi note between 60 & 71:
mod <- function(dfn) {
n_notes <- sum(!is.na(dfn$note))
dfn %>% dplyr::mutate(note = ifelse(
!is.na(note),
sample(60:71, n_notes, TRUE),
note
))
}
set.seed(123)
mfr$update_notes_wide(mod)
mfr$play()
# You can pass functions to the $update_notes_wide() method (as above), but
# you can also modify the dataframe directly and pass it. Therefore, the
# following results in the same:
set.seed(123)
df_mod <- mod(mfr$df_notes_wide)
mfr$update_notes_wide(df_mod)
mfr$play()
}
Method populate_r_fields()
Populate the fields of a MidiFramer object
This can also be used to recalculate all the object's attributes, when a value in params is changed (see examples).
Method play()
Play midi from MidiFramer object.
Writes a midi file and either playing it in the R console (live = TRUE
),
or otherwise (live = FALSE
) writes an audio file
and adding an html audio player in an Rmarkdown (/quarto?) document.
Calls player()
helper function.
WARNING: Setting overwrite = TRUE
(the default!!) will DELETE the specified audio files!!!
(see more details below)
Usage
MidiFramer$play(
audiofile = tempfile("mf_out_", fileext = ".mp3"),
soundfont = fluidsynth::soundfont_path(),
midifile = gsub("\\....$", ".mid", audiofile),
live = interactive(),
verbose = FALSE,
overwrite = TRUE,
...
)
Arguments
audiofile
Path to the audiofile to be synthesized. If audiofile of type mp3, it will first be synthesized to wav, and then converted to mp3 with ffmpeg; (character string).
soundfont
path to sf2 sound font (character string); if not specified, the default soundfont of the fluidsynth package (
fluidsynth::soundfont_path()
) will be (downloaded if not present and) used.midifile
Path to the midi file to synthesize on; (character string).
live
logical; if
TRUE
the synthesized midi is directly played in the console. IfFALSE
an audio html tag is written. This will generate a small audio player when knitting an Rmd document (and probably also Quarto qmd files; I didn't check).verbose
logical whether to print command line output; defaults to FALSE
overwrite
logical; defaults to TRUE; if file exists and overwrite = FALSE, the existing files will not be overwritten and the function errors out.
...
Arguments passed to the fluidsynth functions (
fluidsynth::midi_play
orfluidsynth::midi_convert
depending on the value oflive
).@seealso
player
Examples
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
mfr <- MidiFramer$new(midi_file_string)
mfr$play()
# The play method does basically this:
\dontrun{
midi_out <- "my_output.mid"
mp3file <- "test.mp3"
mfr$mf$write_file(midi_out)
fluidsynth::midi_convert(midi_out, output = mp3file)
# `overwrite` = TRUE overwrites midi_out & mp3file
}
Examples
if (FALSE) {
## Create a MidiFramer object from a midi file:
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
MidiFramer$new(midi_file_string)
## ------------------------------------------------
## Create empty MidiFramer object to illustrate
## the use of the `ticks_per_beat` active binding:
## ------------------------------------------------
mfr <- MidiFramer$new()
# Print default value of empty MidiFile object:
mfr$mf$midi_file$ticks_per_beat
# Modify it with the active binding ticks_per_beat:
mfr$ticks_per_beat <- 960L
# Print it again:
mfr$mf$midi_file$ticks_per_beat
}
## ------------------------------------------------
## Method `MidiFramer$update_notes_wide`
## ------------------------------------------------
if (FALSE) {
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
mfr <- MidiFramer$new(midi_file_string)
# Function to replace every note with a random midi note between 60 & 71:
mod <- function(dfn) {
n_notes <- sum(!is.na(dfn$note))
dfn %>% dplyr::mutate(note = ifelse(
!is.na(note),
sample(60:71, n_notes, TRUE),
note
))
}
set.seed(123)
mfr$update_notes_wide(mod)
mfr$play()
# You can pass functions to the $update_notes_wide() method (as above), but
# you can also modify the dataframe directly and pass it. Therefore, the
# following results in the same:
set.seed(123)
df_mod <- mod(mfr$df_notes_wide)
mfr$update_notes_wide(df_mod)
mfr$play()
}
## ------------------------------------------------
## Method `MidiFramer$populate_r_fields`
## ------------------------------------------------
if (FALSE) {
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
mfr <- MidiFramer$new(midi_file_string)
mfr$params$columns_to_add <- c("m", "b", "t", "time")
mfr$populate_r_fields()
}
## ------------------------------------------------
## Method `MidiFramer$play`
## ------------------------------------------------
midi_file_string <- system.file("extdata", "test_midi_file.mid", package = "pyramidi")
mfr <- MidiFramer$new(midi_file_string)
#> Error in python_config_impl(python) :
#> Error running '/home/runner/.virtualenvs/r-reticulate/python': No such file.
#> The Python installation used to create the virtualenv has been moved or removed:
#> '/opt/hostedtoolcache/Python/3.11.8/x64/bin'
mfr$play()
#> <audio controls="">
#> <source src="/tmp/RtmpcdQMVt/mf_out_1e2a725f17d7.mp3" type="audio/mp3"/>
#> </audio>
# The play method does basically this:
if (FALSE) {
midi_out <- "my_output.mid"
mp3file <- "test.mp3"
mfr$mf$write_file(midi_out)
fluidsynth::midi_convert(midi_out, output = mp3file)
# `overwrite` = TRUE overwrites midi_out & mp3file
}