Skip to contents

Setup

We’ll load some libraries in R:

First, we just load our package midi file to have some scaffolding to put our notes in:

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'

We will compose our data by generating a dataframe as the one on the example midi file.

mfr$df_notes_wide %>% kable()
Click here to show the format of the dataframe we need to have.



| i_track|meta  | note| channel| i_note| velocity_note_on| velocity_note_off| ticks_note_on| ticks_note_off|  b_note_on| b_note_off|
|-------:|:-----|----:|-------:|------:|----------------:|-----------------:|-------------:|--------------:|----------:|----------:|
|       0|FALSE |   43|       9|      1|               72|                72|             0|            240|  0.0000000|   1.000000|
|       0|FALSE |   39|       9|      1|               64|                64|             0|            240|  0.0000000|   1.000000|
|       0|FALSE |   36|       9|      1|              101|               101|             0|            240|  0.0000000|   1.000000|
|       0|FALSE |   42|       9|      1|              101|               101|           480|            720|  2.0000000|   3.000000|
|       0|FALSE |   38|       9|      1|              101|               101|           480|            720|  2.0000000|   3.000000|
|       0|FALSE |   43|       9|      2|               64|                64|           720|            960|  3.0000000|   4.000000|
|       0|FALSE |   36|       9|      2|              101|               101|           960|           1200|  4.0000000|   5.000000|
|       0|FALSE |   43|       9|      3|               60|                60|          1440|           1680|  6.0000000|   7.000000|
|       0|FALSE |   42|       9|      2|              101|               101|          1440|           1680|  6.0000000|   7.000000|
|       0|FALSE |   43|       9|      4|               60|                60|          1920|           2160|  8.0000000|   9.000000|
|       0|FALSE |   39|       9|      2|               66|                66|          1920|           2160|  8.0000000|   9.000000|
|       0|FALSE |   36|       9|      3|              101|               101|          1920|           2160|  8.0000000|   9.000000|
|       0|FALSE |   42|       9|      3|              101|               101|          2400|           2640| 10.0000000|  11.000000|
|       0|FALSE |   38|       9|      2|              101|               101|          2400|           2640| 10.0000000|  11.000000|
|       0|FALSE |   43|       9|      5|               53|                53|          2640|           2880| 11.0000000|  12.000000|
|       0|FALSE |   36|       9|      4|              101|               101|          2880|           3120| 12.0000000|  13.000000|
|       0|FALSE |   43|       9|      6|               52|                52|          3360|           3600| 14.0000000|  15.000000|
|       0|FALSE |   42|       9|      4|               66|                66|          3360|           3600| 14.0000000|  15.000000|
|       0|FALSE |   43|       9|      7|               72|                72|          3840|           4080| 16.0000000|  17.000000|
|       0|FALSE |   39|       9|      3|               64|                64|          3840|           4080| 16.0000000|  17.000000|
|       0|FALSE |   36|       9|      5|              101|               101|          3840|           4080| 16.0000000|  17.000000|
|       0|FALSE |   42|       9|      5|              101|               101|          4320|           4560| 18.0000000|  19.000000|
|       0|FALSE |   38|       9|      3|              101|               101|          4320|           4560| 18.0000000|  19.000000|
|       0|FALSE |   43|       9|      8|               64|                64|          4560|           4800| 19.0000000|  20.000000|
|       0|FALSE |   36|       9|      6|              101|               101|          4800|           5040| 20.0000000|  21.000000|
|       0|FALSE |   43|       9|      9|               60|                60|          5280|           5520| 22.0000000|  23.000000|
|       0|FALSE |   42|       9|      6|              101|               101|          5280|           5520| 22.0000000|  23.000000|
|       0|FALSE |   43|       9|     10|               60|                60|          5760|           6000| 24.0000000|  25.000000|
|       0|FALSE |   39|       9|      4|               66|                66|          5760|           6000| 24.0000000|  25.000000|
|       0|FALSE |   36|       9|      7|              101|               101|          5760|           6000| 24.0000000|  25.000000|
|       0|FALSE |   42|       9|      7|              101|               101|          6240|           6480| 26.0000000|  27.000000|
|       0|FALSE |   38|       9|      4|              101|               101|          6240|           6480| 26.0000000|  27.000000|
|       0|FALSE |   43|       9|     11|               53|                53|          6480|           6720| 27.0000000|  28.000000|
|       0|FALSE |   36|       9|      8|              101|               101|          6720|           6960| 28.0000000|  29.000000|
|       0|FALSE |   43|       9|     12|               52|                52|          7200|           7440| 30.0000000|  31.000000|
|       0|FALSE |   42|       9|      8|               66|                66|          7200|           7440| 30.0000000|  31.000000|
|       0|FALSE |   43|       9|     13|               72|                72|          7680|           7920| 32.0000000|  33.000000|
|       0|FALSE |   39|       9|      5|               64|                64|          7680|           7920| 32.0000000|  33.000000|
|       0|FALSE |   36|       9|      9|              101|               101|          7680|           7920| 32.0000000|  33.000000|
|       0|FALSE |   42|       9|      9|              101|               101|          8160|           8400| 34.0000000|  35.000000|
|       0|FALSE |   38|       9|      5|              101|               101|          8160|           8400| 34.0000000|  35.000000|
|       0|FALSE |   43|       9|     14|               64|                64|          8400|           8640| 35.0000000|  36.000000|
|       0|FALSE |   36|       9|     10|              101|               101|          8640|           8880| 36.0000000|  37.000000|
|       0|FALSE |   43|       9|     15|               60|                60|          9120|           9360| 38.0000000|  39.000000|
|       0|FALSE |   42|       9|     10|              101|               101|          9120|           9360| 38.0000000|  39.000000|
|       0|FALSE |   43|       9|     16|               60|                60|          9600|           9840| 40.0000000|  41.000000|
|       0|FALSE |   39|       9|      6|               66|                66|          9600|           9840| 40.0000000|  41.000000|
|       0|FALSE |   36|       9|     11|              101|               101|          9600|           9840| 40.0000000|  41.000000|
|       0|FALSE |   42|       9|     11|              101|               101|         10080|          10320| 42.0000000|  43.000000|
|       0|FALSE |   38|       9|      6|              101|               101|         10080|          10320| 42.0000000|  43.000000|
|       0|FALSE |   43|       9|     17|               53|                53|         10320|          10560| 43.0000000|  44.000000|
|       0|FALSE |   36|       9|     12|              101|               101|         10560|          10800| 44.0000000|  45.000000|
|       0|FALSE |   43|       9|     18|               52|                52|         11040|          11280| 46.0000000|  47.000000|
|       0|FALSE |   42|       9|     12|               66|                66|         11040|          11280| 46.0000000|  47.000000|
|       0|FALSE |   43|       9|     19|               81|                81|         11520|          11760| 48.0000000|  49.000000|
|       0|FALSE |   36|       9|     13|              101|               101|         11520|          11760| 48.0000000|  49.000000|
|       0|FALSE |   42|       9|     13|              101|               101|         12000|          12240| 50.0000000|  51.000000|
|       0|FALSE |   39|       9|      7|               57|                57|         12000|          12240| 50.0000000|  51.000000|
|       0|FALSE |   38|       9|      7|              101|               101|         12000|          12240| 50.0000000|  51.000000|
|       0|FALSE |   43|       9|     20|               60|                60|         12240|          12480| 51.0000000|  52.000000|
|       0|FALSE |   36|       9|     14|              101|               101|         12480|          12720| 52.0000000|  53.000000|
|       0|FALSE |   43|       9|     21|               66|                66|         12960|          13200| 54.0000000|  55.000000|
|       0|FALSE |   42|       9|     14|              101|               101|         12960|          13200| 54.0000000|  55.000000|
|       0|FALSE |   43|       9|     22|               66|                66|         13440|          13680| 56.0000000|  57.000000|
|       0|FALSE |   36|       9|     15|              101|               101|         13440|          13680| 56.0000000|  57.000000|
|       0|FALSE |   46|       9|      1|               81|                81|         13920|          14160| 58.0000000|  59.000000|
|       0|FALSE |   45|       9|      1|               67|                67|         13920|          14160| 58.0000000|  59.000000|
|       0|FALSE |   39|       9|      8|               60|                60|         13920|          14160| 58.0000000|  59.000000|
|       0|FALSE |   38|       9|      8|              101|               101|         13920|          14160| 58.0000000|  59.000000|
|       0|FALSE |   39|       9|      9|               59|                59|         14400|          14640| 60.0000000|  61.000000|
|       0|FALSE |   36|       9|     16|              101|               101|         14400|          14640| 60.0000000|  61.000000|
|       0|FALSE |   39|       9|     10|               55|                55|         14640|          14880| 61.0000000|  62.000000|
|       0|FALSE |   45|       9|      2|               63|                63|         14880|          15120| 62.0000000|  63.000000|
|       0|FALSE |   43|       9|     23|               52|                52|         14880|          15120| 62.0000000|  63.000000|
|       0|FALSE |   42|       9|     15|              101|               101|         14880|          15120| 62.0000000|  63.000000|
|       0|FALSE |   39|       9|     11|               55|                55|         14880|          15120| 62.0000000|  63.000000|
|       0|FALSE |   42|       9|     16|               59|                59|         15120|          15360| 63.0000000|  64.000000|
|       0|FALSE |   39|       9|     12|               57|                57|         15120|          15360| 63.0000000|  64.000000|
|       1|FALSE |   50|      15|      1|               82|                82|             0|            240|  0.0000000|   1.000000|
|       1|FALSE |   45|      15|      1|               85|                85|          3240|           3840| 13.5000000|  16.000000|
|       1|FALSE |   50|      15|      2|               81|                81|          3840|           4080| 16.0000000|  17.000000|
|       1|FALSE |   45|      15|      2|               69|                69|          7200|           7680| 30.0000000|  32.000000|
|       1|FALSE |   50|      15|      3|               69|                69|          7680|           8040| 32.0000000|  33.500000|
|       1|FALSE |   45|      15|      3|               82|                82|         10440|          11400| 43.5000000|  47.500000|
|       1|FALSE |   50|      15|      4|               72|                72|         11520|          12600| 48.0000000|  52.500000|
|       1|FALSE |   57|      15|      1|               79|                79|         12960|          13440| 54.0000000|  56.000000|
|       1|FALSE |   55|      15|      1|               50|                50|         13440|          13920| 56.0000000|  58.000000|
|       1|FALSE |   53|      15|      1|               73|                73|         13920|          14400| 58.0000000|  60.000000|
|       1|FALSE |   52|      15|      1|               69|                69|         14400|          14880| 60.0000000|  62.000000|
|       1|FALSE |   48|      15|      1|               85|                85|         14880|          15360| 62.0000000|  64.000000|
|       2|FALSE |   62|      15|      1|               78|                78|            54|            369|  0.2250000|   1.537500|
|       2|FALSE |   57|      15|      1|               78|                78|            64|            424|  0.2666667|   1.766667|
|       2|FALSE |   65|      15|      1|               72|                72|            70|            353|  0.2916667|   1.470833|
|       2|FALSE |   62|      15|      2|               57|                57|          1473|           3150|  6.1375000|  13.125000|
|       2|FALSE |   57|      15|      2|               53|                53|          1482|           3197|  6.1750000|  13.320833|
|       2|FALSE |   65|      15|      2|               58|                58|          1490|           3142|  6.2083333|  13.091667|
|       2|FALSE |   62|      15|      3|               61|                61|          3339|           3544| 13.9125000|  14.766667|
|       2|FALSE |   57|      15|      3|               53|                53|          3348|           3576| 13.9500000|  14.900000|
|       2|FALSE |   65|      15|      3|               58|                58|          3356|           3552| 13.9833333|  14.800000|
|       2|FALSE |   62|      15|      4|               47|                47|          3851|           4471| 16.0458333|  18.629167|
|       2|FALSE |   57|      15|      4|               42|                42|          3859|           4590| 16.0791667|  19.125000|
|       2|FALSE |   65|      15|      4|               46|                46|          3868|           4205| 16.1166667|  17.520833|
|       2|FALSE |   62|      15|      5|               56|                56|          5247|           6939| 21.8625000|  28.912500|
|       2|FALSE |   57|      15|      5|               53|                53|          5256|           6963| 21.9000000|  29.012500|
|       2|FALSE |   65|      15|      5|               58|                58|          5264|           6915| 21.9333333|  28.812500|
|       2|FALSE |   62|      15|      6|               49|                49|          7136|           7443| 29.7333333|  31.012500|
|       2|FALSE |   57|      15|      6|               42|                42|          7145|           7467| 29.7708333|  31.112500|
|       2|FALSE |   65|      15|      6|               49|                49|          7153|           7419| 29.8041667|  30.912500|
|       2|FALSE |   62|      15|      7|               37|                37|          7679|           8018| 31.9958333|  33.408333|
|       2|FALSE |   57|      15|      7|               34|                34|          7688|           8097| 32.0333333|  33.737500|
|       2|FALSE |   65|      15|      7|               51|                51|          7696|           8010| 32.0666667|  33.375000|
|       2|FALSE |   57|      15|      8|               58|                58|          9115|          10956| 37.9791667|  45.650000|
|       2|FALSE |   62|      15|      8|               60|                60|          9123|          10885| 38.0125000|  45.354167|
|       2|FALSE |   65|      15|      8|               56|                56|          9131|          10877| 38.0458333|  45.320833|
|       2|FALSE |   62|      15|      9|               50|                50|         11403|          11850| 47.5125000|  49.375000|
|       2|FALSE |   57|      15|      9|               40|                40|         11411|          11929| 47.5458333|  49.704167|
|       2|FALSE |   65|      15|      9|               52|                52|         11419|          11859| 47.5791667|  49.412500|
|       2|FALSE |   62|      15|     10|               63|                63|         12846|          13114| 53.5250000|  54.641667|
|       2|FALSE |   59|      15|      1|               69|                69|         12854|          13145| 53.5583333|  54.770833|
|       2|FALSE |   67|      15|      1|               58|                58|         12862|          13122| 53.5916667|  54.675000|
|       2|FALSE |   59|      15|      2|               58|                58|         13413|          14088| 55.8875000|  58.700000|
|       2|FALSE |   62|      15|     11|               58|                58|         13421|          14016| 55.9208333|  58.400000|
|       2|FALSE |   67|      15|      2|               58|                58|         13429|          14025| 55.9541667|  58.437500|
|       2|FALSE |   59|      15|      3|               52|                52|         14175|          14522| 59.0625000|  60.508333|
|       2|FALSE |   67|      15|      3|               60|                60|         14183|          14474| 59.0958333|  60.308333|
|       2|FALSE |   62|      15|     12|               65|                65|         14191|          14442| 59.1291667|  60.175000|
|       2|FALSE |   59|      15|      4|               57|                57|         14859|          15080| 61.9125000|  62.833333|
|       2|FALSE |   62|      15|     13|               60|                60|         14868|          15049| 61.9500000|  62.704167|
|       2|FALSE |   67|      15|      4|               57|                57|         14876|          15089| 61.9833333|  62.870833|
|       2|FALSE |   62|      15|     14|               82|                82|         15355|          15360| 63.9791667|  64.000000|


We will measure our time in b_note_on and b_note_off being the absolute times (in quarter notes) when the notes are played.

In sf2 soundfonts midi channel 10 (which is channel 9 in pythonista world :) is usually used for drums. Let’s try this out. 36 is the bass drum and 38 the snare

n_beats <- 16
ticks_per_beat <- 960L
drum <- tibble(
  i_track = 0,
  meta = FALSE,
  # This is just a repetition of a classical rock beat:
  note = rep(c(36, 38), n_beats / 2),
  channel = 9,
  i_note = 1:n_beats,
  velocity_note_on = 100,
  velocity_note_off = 0,
  b_note_on = 0:(n_beats-1),
  b_note_off = b_note_on + 1 / 2,
)
drum %>% kable()
Show drum dataframe



| i_track|meta  | note| channel| i_note| velocity_note_on| velocity_note_off| b_note_on| b_note_off|
|-------:|:-----|----:|-------:|------:|----------------:|-----------------:|---------:|----------:|
|       0|FALSE |   36|       9|      1|              100|                 0|         0|        0.5|
|       0|FALSE |   38|       9|      2|              100|                 0|         1|        1.5|
|       0|FALSE |   36|       9|      3|              100|                 0|         2|        2.5|
|       0|FALSE |   38|       9|      4|              100|                 0|         3|        3.5|
|       0|FALSE |   36|       9|      5|              100|                 0|         4|        4.5|
|       0|FALSE |   38|       9|      6|              100|                 0|         5|        5.5|
|       0|FALSE |   36|       9|      7|              100|                 0|         6|        6.5|
|       0|FALSE |   38|       9|      8|              100|                 0|         7|        7.5|
|       0|FALSE |   36|       9|      9|              100|                 0|         8|        8.5|
|       0|FALSE |   38|       9|     10|              100|                 0|         9|        9.5|
|       0|FALSE |   36|       9|     11|              100|                 0|        10|       10.5|
|       0|FALSE |   38|       9|     12|              100|                 0|        11|       11.5|
|       0|FALSE |   36|       9|     13|              100|                 0|        12|       12.5|
|       0|FALSE |   38|       9|     14|              100|                 0|        13|       13.5|
|       0|FALSE |   36|       9|     15|              100|                 0|        14|       14.5|
|       0|FALSE |   38|       9|     16|              100|                 0|        15|       15.5|


We’ll just define a small helper function to calculate the absolute midi ticks passed from the time measured in beats, because when we generate the format to save the data to midi we need to calculate the relative time increments in ticks.

beats_to_ticks <- function(notes_wide) {
  notes_wide %>%
    mutate(
      ticks_note_on  = b_note_on  * ticks_per_beat,
      ticks_note_off = b_note_off * ticks_per_beat
    )
}

Ok we are ready to pass these modified notes to our MidiFramer object

mfr$update_notes_wide(beats_to_ticks(drum))

and listen to the drums of our first composition:

mfr$play("drum.mp3")

Now we’ll add notes. Channel 1 should be grand piano. We will play major chords We define that all the 4 notes in the chord are played at the same time:

(b_note_on = (0:(n_beats-1) %/% 4) * 4)
#>  [1]  0  0  0  0  4  4  4  4  8  8  8  8 12 12 12 12

These starting times will be used to define a notes dataframe.

notes <- tibble(
  i_track = 0,
  meta = FALSE,
  note = rep(c(60, 64, 67, 72), n_beats / 4),
  channel = 0,
  i_note = 1:n_beats,
  velocity_note_on = 100,
  velocity_note_off = 0,
  b_note_on = b_note_on,
  b_note_off = b_note_on + 1 * 2,
)
notes %>% kable()
click to show notes frame



| i_track|meta  | note| channel| i_note| velocity_note_on| velocity_note_off| b_note_on| b_note_off|
|-------:|:-----|----:|-------:|------:|----------------:|-----------------:|---------:|----------:|
|       0|FALSE |   60|       0|      1|              100|                 0|         0|          2|
|       0|FALSE |   64|       0|      2|              100|                 0|         0|          2|
|       0|FALSE |   67|       0|      3|              100|                 0|         0|          2|
|       0|FALSE |   72|       0|      4|              100|                 0|         0|          2|
|       0|FALSE |   60|       0|      5|              100|                 0|         4|          6|
|       0|FALSE |   64|       0|      6|              100|                 0|         4|          6|
|       0|FALSE |   67|       0|      7|              100|                 0|         4|          6|
|       0|FALSE |   72|       0|      8|              100|                 0|         4|          6|
|       0|FALSE |   60|       0|      9|              100|                 0|         8|         10|
|       0|FALSE |   64|       0|     10|              100|                 0|         8|         10|
|       0|FALSE |   67|       0|     11|              100|                 0|         8|         10|
|       0|FALSE |   72|       0|     12|              100|                 0|         8|         10|
|       0|FALSE |   60|       0|     13|              100|                 0|        12|         14|
|       0|FALSE |   64|       0|     14|              100|                 0|        12|         14|
|       0|FALSE |   67|       0|     15|              100|                 0|        12|         14|
|       0|FALSE |   72|       0|     16|              100|                 0|        12|         14|


With a small helper function, we can change the notes played depending on the measure we’re in:

# We play the tonic for 2 bars, 
  # and the subdominant (+5) and dominant (+7) for one each:
change_notes_on_measures <- function(notes) {
  notes %>% 
    mutate(
      note = case_when(
        floor(b_note_on/4) %% 4 == 0 ~ note, 
        floor(b_note_on/4) %% 4 == 1 ~ note, 
        floor(b_note_on/4) %% 4 == 2 ~ note + 5, 
        floor(b_note_on/4) %% 4 == 3 ~ note + 7 
      )
    )
}

notes <- notes %>% 
  change_notes_on_measures()

When we join the drum and notes dataframes together:

midi_note_events_wide <- bind_rows(drum, notes) %>% beats_to_ticks()

We can apply the same as above:

mfr$update_notes_wide(midi_note_events_wide)

And play it:

mfr$play("combine.mp3")

Let’s rock! 🤟🥳

Write functions to compose midi frames

Instead of defining a whole dataframe as in the section before, we’ll now write a small helper function writing single notes to the needed dataframe format:

frame_notes <- function(
  b,
  dur,
  note,
  velocity = 100,
  channel = 0,
  i_track = 0,
  meta = FALSE,
  velocity_note_off = 0,
  ...
) {
  tibble(
    i_track = i_track,
    meta = meta,
    note = note,
    channel = channel,
    velocity_note_on = velocity,
    velocity_note_off = velocity_note_off,
    b_note_on = b,
    b_note_off = b + dur,
  )
}

It outputs one line of a dataframe for each midi in the note vector. We’ll design a repeating bass pattern of a C major chord:

bass <- frame_notes(
  b = 1:n_beats - 1 + 0.5, 
  dur = 1, 
  note = rep(c(36, 43, 41, 48), n_beats / 4)
)
bass %>% kable()
Show output



| i_track|meta  | note| channel| velocity_note_on| velocity_note_off| b_note_on| b_note_off|
|-------:|:-----|----:|-------:|----------------:|-----------------:|---------:|----------:|
|       0|FALSE |   36|       0|              100|                 0|       0.5|        1.5|
|       0|FALSE |   43|       0|              100|                 0|       1.5|        2.5|
|       0|FALSE |   41|       0|              100|                 0|       2.5|        3.5|
|       0|FALSE |   48|       0|              100|                 0|       3.5|        4.5|
|       0|FALSE |   36|       0|              100|                 0|       4.5|        5.5|
|       0|FALSE |   43|       0|              100|                 0|       5.5|        6.5|
|       0|FALSE |   41|       0|              100|                 0|       6.5|        7.5|
|       0|FALSE |   48|       0|              100|                 0|       7.5|        8.5|
|       0|FALSE |   36|       0|              100|                 0|       8.5|        9.5|
|       0|FALSE |   43|       0|              100|                 0|       9.5|       10.5|
|       0|FALSE |   41|       0|              100|                 0|      10.5|       11.5|
|       0|FALSE |   48|       0|              100|                 0|      11.5|       12.5|
|       0|FALSE |   36|       0|              100|                 0|      12.5|       13.5|
|       0|FALSE |   43|       0|              100|                 0|      13.5|       14.5|
|       0|FALSE |   41|       0|              100|                 0|      14.5|       15.5|
|       0|FALSE |   48|       0|              100|                 0|      15.5|       16.5|


In order to avoid repetitive typing we’ll also define a small helper function for chords:

frame_chords <- function(...) {
  frame_notes(...) %>% 
    unnest(note)
}

Now we can pass a list of chord vectors to the function. We’ll repeat the same C major chord:

chords_list <- rep(list(c(60, 64, 67, 72)), n_beats)
chords_list
Show list of chords passed

[[1]]
[1] 60 64 67 72

[[2]]
[1] 60 64 67 72

[[3]]
[1] 60 64 67 72

[[4]]
[1] 60 64 67 72

[[5]]
[1] 60 64 67 72

[[6]]
[1] 60 64 67 72

[[7]]
[1] 60 64 67 72

[[8]]
[1] 60 64 67 72

[[9]]
[1] 60 64 67 72

[[10]]
[1] 60 64 67 72

[[11]]
[1] 60 64 67 72

[[12]]
[1] 60 64 67 72

[[13]]
[1] 60 64 67 72

[[14]]
[1] 60 64 67 72

[[15]]
[1] 60 64 67 72

[[16]]
[1] 60 64 67 72


frame them:

chords <- frame_chords(
  b = 1:n_beats - 1, 
  dur = 1,
  velocity = 70,
  note = chords_list
)
chords
Show framed chords


[38;5;246m# A tibble: 64 × 8
[39m
   i_track meta   note channel velocity_note_on velocity_note_off b_note_on
     
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<lgl>
[39m
[23m 
[3m
[38;5;246m<dbl>
[39m
[23m   
[3m
[38;5;246m<dbl>
[39m
[23m            
[3m
[38;5;246m<dbl>
[39m
[23m             
[3m
[38;5;246m<dbl>
[39m
[23m     
[3m
[38;5;246m<dbl>
[39m
[23m

[38;5;250m 1
[39m       0 FALSE    60       0               70                 0         0

[38;5;250m 2
[39m       0 FALSE    64       0               70                 0         0

[38;5;250m 3
[39m       0 FALSE    67       0               70                 0         0

[38;5;250m 4
[39m       0 FALSE    72       0               70                 0         0

[38;5;250m 5
[39m       0 FALSE    60       0               70                 0         1

[38;5;250m 6
[39m       0 FALSE    64       0               70                 0         1

[38;5;250m 7
[39m       0 FALSE    67       0               70                 0         1

[38;5;250m 8
[39m       0 FALSE    72       0               70                 0         1

[38;5;250m 9
[39m       0 FALSE    60       0               70                 0         2

[38;5;250m10
[39m       0 FALSE    64       0               70                 0         2

[38;5;246m# ℹ 54 more rows
[39m

[38;5;246m# ℹ 1 more variable: b_note_off <dbl>
[39m


Now let’s write a simple rising arpeggiatator function:

arpeggiate <- function(
  b,
  chords_list,
  dur = 1,
  pattern = "rising",
  n_beat = 4,
  octave = 1,
  ...
) {
  times <- tibble(b) %>%
    rowwise() %>% 
    summarise(c(b + seq(0, 1, length.out = n_beat + 1)[-(n_beat + 1)])) %>% 
    pull()
  notes <- 
    tibble(temp = chords_list) %>% 
    unnest(temp) %>% 
    pull() %>% 
    {. + octave * 12; .}
  frame_notes(
    dur = dur/n_beat,
    b = times,
    note = notes,
    ...
  )
    
}
arp <- arpeggiate(
  b = 1:n_beats - 1, 
  velocity = 90,
  chords_list = chords_list
)
#> Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
#> dplyr 1.1.0.
#>  Please use `reframe()` instead.
#>  When switching from `summarise()` to `reframe()`, remember that `reframe()`
#>   always returns an ungrouped data frame and adjust accordingly.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
arp %>% kable()
Show arpeggio function output



| i_track|meta  | note| channel| velocity_note_on| velocity_note_off| b_note_on| b_note_off|
|-------:|:-----|----:|-------:|----------------:|-----------------:|---------:|----------:|
|       0|FALSE |   60|       0|               90|                 0|      0.00|       0.25|
|       0|FALSE |   64|       0|               90|                 0|      0.25|       0.50|
|       0|FALSE |   67|       0|               90|                 0|      0.50|       0.75|
|       0|FALSE |   72|       0|               90|                 0|      0.75|       1.00|
|       0|FALSE |   60|       0|               90|                 0|      1.00|       1.25|
|       0|FALSE |   64|       0|               90|                 0|      1.25|       1.50|
|       0|FALSE |   67|       0|               90|                 0|      1.50|       1.75|
|       0|FALSE |   72|       0|               90|                 0|      1.75|       2.00|
|       0|FALSE |   60|       0|               90|                 0|      2.00|       2.25|
|       0|FALSE |   64|       0|               90|                 0|      2.25|       2.50|
|       0|FALSE |   67|       0|               90|                 0|      2.50|       2.75|
|       0|FALSE |   72|       0|               90|                 0|      2.75|       3.00|
|       0|FALSE |   60|       0|               90|                 0|      3.00|       3.25|
|       0|FALSE |   64|       0|               90|                 0|      3.25|       3.50|
|       0|FALSE |   67|       0|               90|                 0|      3.50|       3.75|
|       0|FALSE |   72|       0|               90|                 0|      3.75|       4.00|
|       0|FALSE |   60|       0|               90|                 0|      4.00|       4.25|
|       0|FALSE |   64|       0|               90|                 0|      4.25|       4.50|
|       0|FALSE |   67|       0|               90|                 0|      4.50|       4.75|
|       0|FALSE |   72|       0|               90|                 0|      4.75|       5.00|
|       0|FALSE |   60|       0|               90|                 0|      5.00|       5.25|
|       0|FALSE |   64|       0|               90|                 0|      5.25|       5.50|
|       0|FALSE |   67|       0|               90|                 0|      5.50|       5.75|
|       0|FALSE |   72|       0|               90|                 0|      5.75|       6.00|
|       0|FALSE |   60|       0|               90|                 0|      6.00|       6.25|
|       0|FALSE |   64|       0|               90|                 0|      6.25|       6.50|
|       0|FALSE |   67|       0|               90|                 0|      6.50|       6.75|
|       0|FALSE |   72|       0|               90|                 0|      6.75|       7.00|
|       0|FALSE |   60|       0|               90|                 0|      7.00|       7.25|
|       0|FALSE |   64|       0|               90|                 0|      7.25|       7.50|
|       0|FALSE |   67|       0|               90|                 0|      7.50|       7.75|
|       0|FALSE |   72|       0|               90|                 0|      7.75|       8.00|
|       0|FALSE |   60|       0|               90|                 0|      8.00|       8.25|
|       0|FALSE |   64|       0|               90|                 0|      8.25|       8.50|
|       0|FALSE |   67|       0|               90|                 0|      8.50|       8.75|
|       0|FALSE |   72|       0|               90|                 0|      8.75|       9.00|
|       0|FALSE |   60|       0|               90|                 0|      9.00|       9.25|
|       0|FALSE |   64|       0|               90|                 0|      9.25|       9.50|
|       0|FALSE |   67|       0|               90|                 0|      9.50|       9.75|
|       0|FALSE |   72|       0|               90|                 0|      9.75|      10.00|
|       0|FALSE |   60|       0|               90|                 0|     10.00|      10.25|
|       0|FALSE |   64|       0|               90|                 0|     10.25|      10.50|
|       0|FALSE |   67|       0|               90|                 0|     10.50|      10.75|
|       0|FALSE |   72|       0|               90|                 0|     10.75|      11.00|
|       0|FALSE |   60|       0|               90|                 0|     11.00|      11.25|
|       0|FALSE |   64|       0|               90|                 0|     11.25|      11.50|
|       0|FALSE |   67|       0|               90|                 0|     11.50|      11.75|
|       0|FALSE |   72|       0|               90|                 0|     11.75|      12.00|
|       0|FALSE |   60|       0|               90|                 0|     12.00|      12.25|
|       0|FALSE |   64|       0|               90|                 0|     12.25|      12.50|
|       0|FALSE |   67|       0|               90|                 0|     12.50|      12.75|
|       0|FALSE |   72|       0|               90|                 0|     12.75|      13.00|
|       0|FALSE |   60|       0|               90|                 0|     13.00|      13.25|
|       0|FALSE |   64|       0|               90|                 0|     13.25|      13.50|
|       0|FALSE |   67|       0|               90|                 0|     13.50|      13.75|
|       0|FALSE |   72|       0|               90|                 0|     13.75|      14.00|
|       0|FALSE |   60|       0|               90|                 0|     14.00|      14.25|
|       0|FALSE |   64|       0|               90|                 0|     14.25|      14.50|
|       0|FALSE |   67|       0|               90|                 0|     14.50|      14.75|
|       0|FALSE |   72|       0|               90|                 0|     14.75|      15.00|
|       0|FALSE |   60|       0|               90|                 0|     15.00|      15.25|
|       0|FALSE |   64|       0|               90|                 0|     15.25|      15.50|
|       0|FALSE |   67|       0|               90|                 0|     15.50|      15.75|
|       0|FALSE |   72|       0|               90|                 0|     15.75|      16.00|


We can concatenate these different parts into one dataframe by also changing the chords played with our small function change_notes_on_measures():

combination <- bind_rows(
  # We'll add our note variation 
  # of a major chord to tonic, subdominant and dominant:
  bass %>% change_notes_on_measures(),
  chords %>% change_notes_on_measures(),
  arp %>% change_notes_on_measures(),
  # But not on the drum :)
  drum
) %>% 
  beats_to_ticks()
combination %>% kable()
Show dataframe of whole combination



| i_track|meta  | note| channel| velocity_note_on| velocity_note_off| b_note_on| b_note_off| i_note| ticks_note_on| ticks_note_off|
|-------:|:-----|----:|-------:|----------------:|-----------------:|---------:|----------:|------:|-------------:|--------------:|
|       0|FALSE |   36|       0|              100|                 0|      0.50|       1.50|     NA|           480|           1440|
|       0|FALSE |   43|       0|              100|                 0|      1.50|       2.50|     NA|          1440|           2400|
|       0|FALSE |   41|       0|              100|                 0|      2.50|       3.50|     NA|          2400|           3360|
|       0|FALSE |   48|       0|              100|                 0|      3.50|       4.50|     NA|          3360|           4320|
|       0|FALSE |   36|       0|              100|                 0|      4.50|       5.50|     NA|          4320|           5280|
|       0|FALSE |   43|       0|              100|                 0|      5.50|       6.50|     NA|          5280|           6240|
|       0|FALSE |   41|       0|              100|                 0|      6.50|       7.50|     NA|          6240|           7200|
|       0|FALSE |   48|       0|              100|                 0|      7.50|       8.50|     NA|          7200|           8160|
|       0|FALSE |   41|       0|              100|                 0|      8.50|       9.50|     NA|          8160|           9120|
|       0|FALSE |   48|       0|              100|                 0|      9.50|      10.50|     NA|          9120|          10080|
|       0|FALSE |   46|       0|              100|                 0|     10.50|      11.50|     NA|         10080|          11040|
|       0|FALSE |   53|       0|              100|                 0|     11.50|      12.50|     NA|         11040|          12000|
|       0|FALSE |   43|       0|              100|                 0|     12.50|      13.50|     NA|         12000|          12960|
|       0|FALSE |   50|       0|              100|                 0|     13.50|      14.50|     NA|         12960|          13920|
|       0|FALSE |   48|       0|              100|                 0|     14.50|      15.50|     NA|         13920|          14880|
|       0|FALSE |   55|       0|              100|                 0|     15.50|      16.50|     NA|         14880|          15840|
|       0|FALSE |   60|       0|               70|                 0|      0.00|       1.00|     NA|             0|            960|
|       0|FALSE |   64|       0|               70|                 0|      0.00|       1.00|     NA|             0|            960|
|       0|FALSE |   67|       0|               70|                 0|      0.00|       1.00|     NA|             0|            960|
|       0|FALSE |   72|       0|               70|                 0|      0.00|       1.00|     NA|             0|            960|
|       0|FALSE |   60|       0|               70|                 0|      1.00|       2.00|     NA|           960|           1920|
|       0|FALSE |   64|       0|               70|                 0|      1.00|       2.00|     NA|           960|           1920|
|       0|FALSE |   67|       0|               70|                 0|      1.00|       2.00|     NA|           960|           1920|
|       0|FALSE |   72|       0|               70|                 0|      1.00|       2.00|     NA|           960|           1920|
|       0|FALSE |   60|       0|               70|                 0|      2.00|       3.00|     NA|          1920|           2880|
|       0|FALSE |   64|       0|               70|                 0|      2.00|       3.00|     NA|          1920|           2880|
|       0|FALSE |   67|       0|               70|                 0|      2.00|       3.00|     NA|          1920|           2880|
|       0|FALSE |   72|       0|               70|                 0|      2.00|       3.00|     NA|          1920|           2880|
|       0|FALSE |   60|       0|               70|                 0|      3.00|       4.00|     NA|          2880|           3840|
|       0|FALSE |   64|       0|               70|                 0|      3.00|       4.00|     NA|          2880|           3840|
|       0|FALSE |   67|       0|               70|                 0|      3.00|       4.00|     NA|          2880|           3840|
|       0|FALSE |   72|       0|               70|                 0|      3.00|       4.00|     NA|          2880|           3840|
|       0|FALSE |   60|       0|               70|                 0|      4.00|       5.00|     NA|          3840|           4800|
|       0|FALSE |   64|       0|               70|                 0|      4.00|       5.00|     NA|          3840|           4800|
|       0|FALSE |   67|       0|               70|                 0|      4.00|       5.00|     NA|          3840|           4800|
|       0|FALSE |   72|       0|               70|                 0|      4.00|       5.00|     NA|          3840|           4800|
|       0|FALSE |   60|       0|               70|                 0|      5.00|       6.00|     NA|          4800|           5760|
|       0|FALSE |   64|       0|               70|                 0|      5.00|       6.00|     NA|          4800|           5760|
|       0|FALSE |   67|       0|               70|                 0|      5.00|       6.00|     NA|          4800|           5760|
|       0|FALSE |   72|       0|               70|                 0|      5.00|       6.00|     NA|          4800|           5760|
|       0|FALSE |   60|       0|               70|                 0|      6.00|       7.00|     NA|          5760|           6720|
|       0|FALSE |   64|       0|               70|                 0|      6.00|       7.00|     NA|          5760|           6720|
|       0|FALSE |   67|       0|               70|                 0|      6.00|       7.00|     NA|          5760|           6720|
|       0|FALSE |   72|       0|               70|                 0|      6.00|       7.00|     NA|          5760|           6720|
|       0|FALSE |   60|       0|               70|                 0|      7.00|       8.00|     NA|          6720|           7680|
|       0|FALSE |   64|       0|               70|                 0|      7.00|       8.00|     NA|          6720|           7680|
|       0|FALSE |   67|       0|               70|                 0|      7.00|       8.00|     NA|          6720|           7680|
|       0|FALSE |   72|       0|               70|                 0|      7.00|       8.00|     NA|          6720|           7680|
|       0|FALSE |   65|       0|               70|                 0|      8.00|       9.00|     NA|          7680|           8640|
|       0|FALSE |   69|       0|               70|                 0|      8.00|       9.00|     NA|          7680|           8640|
|       0|FALSE |   72|       0|               70|                 0|      8.00|       9.00|     NA|          7680|           8640|
|       0|FALSE |   77|       0|               70|                 0|      8.00|       9.00|     NA|          7680|           8640|
|       0|FALSE |   65|       0|               70|                 0|      9.00|      10.00|     NA|          8640|           9600|
|       0|FALSE |   69|       0|               70|                 0|      9.00|      10.00|     NA|          8640|           9600|
|       0|FALSE |   72|       0|               70|                 0|      9.00|      10.00|     NA|          8640|           9600|
|       0|FALSE |   77|       0|               70|                 0|      9.00|      10.00|     NA|          8640|           9600|
|       0|FALSE |   65|       0|               70|                 0|     10.00|      11.00|     NA|          9600|          10560|
|       0|FALSE |   69|       0|               70|                 0|     10.00|      11.00|     NA|          9600|          10560|
|       0|FALSE |   72|       0|               70|                 0|     10.00|      11.00|     NA|          9600|          10560|
|       0|FALSE |   77|       0|               70|                 0|     10.00|      11.00|     NA|          9600|          10560|
|       0|FALSE |   65|       0|               70|                 0|     11.00|      12.00|     NA|         10560|          11520|
|       0|FALSE |   69|       0|               70|                 0|     11.00|      12.00|     NA|         10560|          11520|
|       0|FALSE |   72|       0|               70|                 0|     11.00|      12.00|     NA|         10560|          11520|
|       0|FALSE |   77|       0|               70|                 0|     11.00|      12.00|     NA|         10560|          11520|
|       0|FALSE |   67|       0|               70|                 0|     12.00|      13.00|     NA|         11520|          12480|
|       0|FALSE |   71|       0|               70|                 0|     12.00|      13.00|     NA|         11520|          12480|
|       0|FALSE |   74|       0|               70|                 0|     12.00|      13.00|     NA|         11520|          12480|
|       0|FALSE |   79|       0|               70|                 0|     12.00|      13.00|     NA|         11520|          12480|
|       0|FALSE |   67|       0|               70|                 0|     13.00|      14.00|     NA|         12480|          13440|
|       0|FALSE |   71|       0|               70|                 0|     13.00|      14.00|     NA|         12480|          13440|
|       0|FALSE |   74|       0|               70|                 0|     13.00|      14.00|     NA|         12480|          13440|
|       0|FALSE |   79|       0|               70|                 0|     13.00|      14.00|     NA|         12480|          13440|
|       0|FALSE |   67|       0|               70|                 0|     14.00|      15.00|     NA|         13440|          14400|
|       0|FALSE |   71|       0|               70|                 0|     14.00|      15.00|     NA|         13440|          14400|
|       0|FALSE |   74|       0|               70|                 0|     14.00|      15.00|     NA|         13440|          14400|
|       0|FALSE |   79|       0|               70|                 0|     14.00|      15.00|     NA|         13440|          14400|
|       0|FALSE |   67|       0|               70|                 0|     15.00|      16.00|     NA|         14400|          15360|
|       0|FALSE |   71|       0|               70|                 0|     15.00|      16.00|     NA|         14400|          15360|
|       0|FALSE |   74|       0|               70|                 0|     15.00|      16.00|     NA|         14400|          15360|
|       0|FALSE |   79|       0|               70|                 0|     15.00|      16.00|     NA|         14400|          15360|
|       0|FALSE |   60|       0|               90|                 0|      0.00|       0.25|     NA|             0|            240|
|       0|FALSE |   64|       0|               90|                 0|      0.25|       0.50|     NA|           240|            480|
|       0|FALSE |   67|       0|               90|                 0|      0.50|       0.75|     NA|           480|            720|
|       0|FALSE |   72|       0|               90|                 0|      0.75|       1.00|     NA|           720|            960|
|       0|FALSE |   60|       0|               90|                 0|      1.00|       1.25|     NA|           960|           1200|
|       0|FALSE |   64|       0|               90|                 0|      1.25|       1.50|     NA|          1200|           1440|
|       0|FALSE |   67|       0|               90|                 0|      1.50|       1.75|     NA|          1440|           1680|
|       0|FALSE |   72|       0|               90|                 0|      1.75|       2.00|     NA|          1680|           1920|
|       0|FALSE |   60|       0|               90|                 0|      2.00|       2.25|     NA|          1920|           2160|
|       0|FALSE |   64|       0|               90|                 0|      2.25|       2.50|     NA|          2160|           2400|
|       0|FALSE |   67|       0|               90|                 0|      2.50|       2.75|     NA|          2400|           2640|
|       0|FALSE |   72|       0|               90|                 0|      2.75|       3.00|     NA|          2640|           2880|
|       0|FALSE |   60|       0|               90|                 0|      3.00|       3.25|     NA|          2880|           3120|
|       0|FALSE |   64|       0|               90|                 0|      3.25|       3.50|     NA|          3120|           3360|
|       0|FALSE |   67|       0|               90|                 0|      3.50|       3.75|     NA|          3360|           3600|
|       0|FALSE |   72|       0|               90|                 0|      3.75|       4.00|     NA|          3600|           3840|
|       0|FALSE |   60|       0|               90|                 0|      4.00|       4.25|     NA|          3840|           4080|
|       0|FALSE |   64|       0|               90|                 0|      4.25|       4.50|     NA|          4080|           4320|
|       0|FALSE |   67|       0|               90|                 0|      4.50|       4.75|     NA|          4320|           4560|
|       0|FALSE |   72|       0|               90|                 0|      4.75|       5.00|     NA|          4560|           4800|
|       0|FALSE |   60|       0|               90|                 0|      5.00|       5.25|     NA|          4800|           5040|
|       0|FALSE |   64|       0|               90|                 0|      5.25|       5.50|     NA|          5040|           5280|
|       0|FALSE |   67|       0|               90|                 0|      5.50|       5.75|     NA|          5280|           5520|
|       0|FALSE |   72|       0|               90|                 0|      5.75|       6.00|     NA|          5520|           5760|
|       0|FALSE |   60|       0|               90|                 0|      6.00|       6.25|     NA|          5760|           6000|
|       0|FALSE |   64|       0|               90|                 0|      6.25|       6.50|     NA|          6000|           6240|
|       0|FALSE |   67|       0|               90|                 0|      6.50|       6.75|     NA|          6240|           6480|
|       0|FALSE |   72|       0|               90|                 0|      6.75|       7.00|     NA|          6480|           6720|
|       0|FALSE |   60|       0|               90|                 0|      7.00|       7.25|     NA|          6720|           6960|
|       0|FALSE |   64|       0|               90|                 0|      7.25|       7.50|     NA|          6960|           7200|
|       0|FALSE |   67|       0|               90|                 0|      7.50|       7.75|     NA|          7200|           7440|
|       0|FALSE |   72|       0|               90|                 0|      7.75|       8.00|     NA|          7440|           7680|
|       0|FALSE |   65|       0|               90|                 0|      8.00|       8.25|     NA|          7680|           7920|
|       0|FALSE |   69|       0|               90|                 0|      8.25|       8.50|     NA|          7920|           8160|
|       0|FALSE |   72|       0|               90|                 0|      8.50|       8.75|     NA|          8160|           8400|
|       0|FALSE |   77|       0|               90|                 0|      8.75|       9.00|     NA|          8400|           8640|
|       0|FALSE |   65|       0|               90|                 0|      9.00|       9.25|     NA|          8640|           8880|
|       0|FALSE |   69|       0|               90|                 0|      9.25|       9.50|     NA|          8880|           9120|
|       0|FALSE |   72|       0|               90|                 0|      9.50|       9.75|     NA|          9120|           9360|
|       0|FALSE |   77|       0|               90|                 0|      9.75|      10.00|     NA|          9360|           9600|
|       0|FALSE |   65|       0|               90|                 0|     10.00|      10.25|     NA|          9600|           9840|
|       0|FALSE |   69|       0|               90|                 0|     10.25|      10.50|     NA|          9840|          10080|
|       0|FALSE |   72|       0|               90|                 0|     10.50|      10.75|     NA|         10080|          10320|
|       0|FALSE |   77|       0|               90|                 0|     10.75|      11.00|     NA|         10320|          10560|
|       0|FALSE |   65|       0|               90|                 0|     11.00|      11.25|     NA|         10560|          10800|
|       0|FALSE |   69|       0|               90|                 0|     11.25|      11.50|     NA|         10800|          11040|
|       0|FALSE |   72|       0|               90|                 0|     11.50|      11.75|     NA|         11040|          11280|
|       0|FALSE |   77|       0|               90|                 0|     11.75|      12.00|     NA|         11280|          11520|
|       0|FALSE |   67|       0|               90|                 0|     12.00|      12.25|     NA|         11520|          11760|
|       0|FALSE |   71|       0|               90|                 0|     12.25|      12.50|     NA|         11760|          12000|
|       0|FALSE |   74|       0|               90|                 0|     12.50|      12.75|     NA|         12000|          12240|
|       0|FALSE |   79|       0|               90|                 0|     12.75|      13.00|     NA|         12240|          12480|
|       0|FALSE |   67|       0|               90|                 0|     13.00|      13.25|     NA|         12480|          12720|
|       0|FALSE |   71|       0|               90|                 0|     13.25|      13.50|     NA|         12720|          12960|
|       0|FALSE |   74|       0|               90|                 0|     13.50|      13.75|     NA|         12960|          13200|
|       0|FALSE |   79|       0|               90|                 0|     13.75|      14.00|     NA|         13200|          13440|
|       0|FALSE |   67|       0|               90|                 0|     14.00|      14.25|     NA|         13440|          13680|
|       0|FALSE |   71|       0|               90|                 0|     14.25|      14.50|     NA|         13680|          13920|
|       0|FALSE |   74|       0|               90|                 0|     14.50|      14.75|     NA|         13920|          14160|
|       0|FALSE |   79|       0|               90|                 0|     14.75|      15.00|     NA|         14160|          14400|
|       0|FALSE |   67|       0|               90|                 0|     15.00|      15.25|     NA|         14400|          14640|
|       0|FALSE |   71|       0|               90|                 0|     15.25|      15.50|     NA|         14640|          14880|
|       0|FALSE |   74|       0|               90|                 0|     15.50|      15.75|     NA|         14880|          15120|
|       0|FALSE |   79|       0|               90|                 0|     15.75|      16.00|     NA|         15120|          15360|
|       0|FALSE |   36|       9|              100|                 0|      0.00|       0.50|      1|             0|            480|
|       0|FALSE |   38|       9|              100|                 0|      1.00|       1.50|      2|           960|           1440|
|       0|FALSE |   36|       9|              100|                 0|      2.00|       2.50|      3|          1920|           2400|
|       0|FALSE |   38|       9|              100|                 0|      3.00|       3.50|      4|          2880|           3360|
|       0|FALSE |   36|       9|              100|                 0|      4.00|       4.50|      5|          3840|           4320|
|       0|FALSE |   38|       9|              100|                 0|      5.00|       5.50|      6|          4800|           5280|
|       0|FALSE |   36|       9|              100|                 0|      6.00|       6.50|      7|          5760|           6240|
|       0|FALSE |   38|       9|              100|                 0|      7.00|       7.50|      8|          6720|           7200|
|       0|FALSE |   36|       9|              100|                 0|      8.00|       8.50|      9|          7680|           8160|
|       0|FALSE |   38|       9|              100|                 0|      9.00|       9.50|     10|          8640|           9120|
|       0|FALSE |   36|       9|              100|                 0|     10.00|      10.50|     11|          9600|          10080|
|       0|FALSE |   38|       9|              100|                 0|     11.00|      11.50|     12|         10560|          11040|
|       0|FALSE |   36|       9|              100|                 0|     12.00|      12.50|     13|         11520|          12000|
|       0|FALSE |   38|       9|              100|                 0|     13.00|      13.50|     14|         12480|          12960|
|       0|FALSE |   36|       9|              100|                 0|     14.00|      14.50|     15|         13440|          13920|
|       0|FALSE |   38|       9|              100|                 0|     15.00|      15.50|     16|         14400|          14880|


mfr$update_notes_wide(combination)
mfr$play("combination.mp3")

Combine parts

In vignette("pyramidi", package = "pyramidi") there is an example with accumulate() how you can generate multiple midifiles while successively adding modifications to the data. Now we will also successively add parts together, but in the same midifile.

(part_names <- c("drum", "bass", "chords", "arp") %>% accumulate(paste, sep = " + "))
#> [1] "drum"                       "drum + bass"               
#> [3] "drum + bass + chords"       "drum + bass + chords + arp"

To do this, let’s first generate a list of midi frames, where at each step the accumulative former results are added to the new:

augmentation <- list(
  drum,
  chords %>% change_notes_on_measures(),
  bass %>% change_notes_on_measures(),
  arp %>% change_notes_on_measures()
) %>% 
  accumulate(full_join) %>% 
  set_names(part_names)
#> Joining with `by = join_by(i_track, meta, note, channel, velocity_note_on,
#> velocity_note_off, b_note_on, b_note_off)`
#> Joining with `by = join_by(i_track, meta, note, channel, velocity_note_on,
#> velocity_note_off, b_note_on, b_note_off)`
#> Joining with `by = join_by(i_track, meta, note, channel, velocity_note_on,
#> velocity_note_off, b_note_on, b_note_off)`
augmentation
Click here to see the list of parts.

$drum

[38;5;246m# A tibble: 16 × 9
[39m
   i_track meta   note channel i_note velocity_note_on velocity_note_off
     
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<lgl>
[39m
[23m 
[3m
[38;5;246m<dbl>
[39m
[23m   
[3m
[38;5;246m<dbl>
[39m
[23m  
[3m
[38;5;246m<int>
[39m
[23m            
[3m
[38;5;246m<dbl>
[39m
[23m             
[3m
[38;5;246m<dbl>
[39m
[23m

[38;5;250m 1
[39m       0 FALSE    36       9      1              100                 0

[38;5;250m 2
[39m       0 FALSE    38       9      2              100                 0

[38;5;250m 3
[39m       0 FALSE    36       9      3              100                 0

[38;5;250m 4
[39m       0 FALSE    38       9      4              100                 0

[38;5;250m 5
[39m       0 FALSE    36       9      5              100                 0

[38;5;250m 6
[39m       0 FALSE    38       9      6              100                 0

[38;5;250m 7
[39m       0 FALSE    36       9      7              100                 0

[38;5;250m 8
[39m       0 FALSE    38       9      8              100                 0

[38;5;250m 9
[39m       0 FALSE    36       9      9              100                 0

[38;5;250m10
[39m       0 FALSE    38       9     10              100                 0

[38;5;250m11
[39m       0 FALSE    36       9     11              100                 0

[38;5;250m12
[39m       0 FALSE    38       9     12              100                 0

[38;5;250m13
[39m       0 FALSE    36       9     13              100                 0

[38;5;250m14
[39m       0 FALSE    38       9     14              100                 0

[38;5;250m15
[39m       0 FALSE    36       9     15              100                 0

[38;5;250m16
[39m       0 FALSE    38       9     16              100                 0

[38;5;246m# ℹ 2 more variables: b_note_on <int>, b_note_off <dbl>
[39m

$`drum + bass`

[38;5;246m# A tibble: 80 × 9
[39m
   i_track meta   note channel i_note velocity_note_on velocity_note_off
     
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<lgl>
[39m
[23m 
[3m
[38;5;246m<dbl>
[39m
[23m   
[3m
[38;5;246m<dbl>
[39m
[23m  
[3m
[38;5;246m<int>
[39m
[23m            
[3m
[38;5;246m<dbl>
[39m
[23m             
[3m
[38;5;246m<dbl>
[39m
[23m

[38;5;250m 1
[39m       0 FALSE    36       9      1              100                 0

[38;5;250m 2
[39m       0 FALSE    38       9      2              100                 0

[38;5;250m 3
[39m       0 FALSE    36       9      3              100                 0

[38;5;250m 4
[39m       0 FALSE    38       9      4              100                 0

[38;5;250m 5
[39m       0 FALSE    36       9      5              100                 0

[38;5;250m 6
[39m       0 FALSE    38       9      6              100                 0

[38;5;250m 7
[39m       0 FALSE    36       9      7              100                 0

[38;5;250m 8
[39m       0 FALSE    38       9      8              100                 0

[38;5;250m 9
[39m       0 FALSE    36       9      9              100                 0

[38;5;250m10
[39m       0 FALSE    38       9     10              100                 0

[38;5;246m# ℹ 70 more rows
[39m

[38;5;246m# ℹ 2 more variables: b_note_on <dbl>, b_note_off <dbl>
[39m

$`drum + bass + chords`

[38;5;246m# A tibble: 96 × 9
[39m
   i_track meta   note channel i_note velocity_note_on velocity_note_off
     
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<lgl>
[39m
[23m 
[3m
[38;5;246m<dbl>
[39m
[23m   
[3m
[38;5;246m<dbl>
[39m
[23m  
[3m
[38;5;246m<int>
[39m
[23m            
[3m
[38;5;246m<dbl>
[39m
[23m             
[3m
[38;5;246m<dbl>
[39m
[23m

[38;5;250m 1
[39m       0 FALSE    36       9      1              100                 0

[38;5;250m 2
[39m       0 FALSE    38       9      2              100                 0

[38;5;250m 3
[39m       0 FALSE    36       9      3              100                 0

[38;5;250m 4
[39m       0 FALSE    38       9      4              100                 0

[38;5;250m 5
[39m       0 FALSE    36       9      5              100                 0

[38;5;250m 6
[39m       0 FALSE    38       9      6              100                 0

[38;5;250m 7
[39m       0 FALSE    36       9      7              100                 0

[38;5;250m 8
[39m       0 FALSE    38       9      8              100                 0

[38;5;250m 9
[39m       0 FALSE    36       9      9              100                 0

[38;5;250m10
[39m       0 FALSE    38       9     10              100                 0

[38;5;246m# ℹ 86 more rows
[39m

[38;5;246m# ℹ 2 more variables: b_note_on <dbl>, b_note_off <dbl>
[39m

$`drum + bass + chords + arp`

[38;5;246m# A tibble: 160 × 9
[39m
   i_track meta   note channel i_note velocity_note_on velocity_note_off
     
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<lgl>
[39m
[23m 
[3m
[38;5;246m<dbl>
[39m
[23m   
[3m
[38;5;246m<dbl>
[39m
[23m  
[3m
[38;5;246m<int>
[39m
[23m            
[3m
[38;5;246m<dbl>
[39m
[23m             
[3m
[38;5;246m<dbl>
[39m
[23m

[38;5;250m 1
[39m       0 FALSE    36       9      1              100                 0

[38;5;250m 2
[39m       0 FALSE    38       9      2              100                 0

[38;5;250m 3
[39m       0 FALSE    36       9      3              100                 0

[38;5;250m 4
[39m       0 FALSE    38       9      4              100                 0

[38;5;250m 5
[39m       0 FALSE    36       9      5              100                 0

[38;5;250m 6
[39m       0 FALSE    38       9      6              100                 0

[38;5;250m 7
[39m       0 FALSE    36       9      7              100                 0

[38;5;250m 8
[39m       0 FALSE    38       9      8              100                 0

[38;5;250m 9
[39m       0 FALSE    36       9      9              100                 0

[38;5;250m10
[39m       0 FALSE    38       9     10              100                 0

[38;5;246m# ℹ 150 more rows
[39m

[38;5;246m# ℹ 2 more variables: b_note_on <dbl>, b_note_off <dbl>
[39m


All of these parts start at time 0. In order to make the parts start one after one another, we need to shift them in time. This is what the following code does.

# after augmenting, we'll add parts subtracting the instruments one after one
# another (the rev()erse):
composition <- c(augmentation, rev(set_names(augmentation, ~paste0(., "2")))) %>% 
  # put them in one dataframe and modify the starting time of the notes in the parts:
  bind_rows(.id = "part") %>% 
  # (we need as_factor() to avoid alphabetical ordering of the parts)
  group_by(part = as_factor(part)) %>% 
  mutate(i_part = cur_group_id()) %>% 
  ungroup() %>% 
  mutate_at(c("b_note_on", "b_note_off"), ~ . + (i_part - 1) * n_beats) %>%
  # remove new columns to have the needed format for midi export:
  select(-part, -i_part) %>% 
  beats_to_ticks()

Let’s have a listen to my first composition in R:

mfr$update_notes_wide(composition)
mfr$play("composition.mp3")