When trying out jazz and blues licks I prefer a notation with note and duration in one single array, someting like
g_melody = [
:F4, 1.5,
:E4, 0.5,
:D4, 1.0,
:E4, 1.0,
:r, 0.5,
:Fs4, 1.0,
:D4, 1.0,
:B3, 0.5,
:B3, 0.5
]
This way my hands don’t have to type many braces and it’s clear, which duration belongs to which note. Unfortunately, if I want to play it quickly, there is play_pattern_timed. Unfortunately, this method takes two arrays, one with the notes and one with the durations.
I was searching a quick transformation of my melody array to the two arrays needed for play_pattern_timed. After playing around with .each_cons and .map without success, I went back to the good oldfashioned loop:
g_notes = []
g_durations = []
g_melody.each.with_index do |p_item, p_index|
if p_index.even? then
g_notes.push(p_item)
else
g_durations.push(p_item)
end
end
print g_notes
print g_durations
This works, but it is rather clumsy. In the end I asked my favourite AI - perplexity - for a more compact and elegant solution. It came up with a ruby function .partition.with_index I’ve never heard of. I couldn’t even find it in the official ruby documentation. With this the solution became a one-liner. Here is the full code:
use_synth :piano
use_bpm 160
g_melody = [
:F4, 1.5,
:E4, 0.5,
:D4, 1.0,
:E4, 1.0,
:r, 0.5,
:Fs4, 1.0,
:D4, 1.0,
:B3, 0.5,
:B3, 0.5
]
# make two arrays, one for the notes and one for the durations
g_notes, g_durations = g_melody.partition.with_index { |_, i| i.even? }
print g_notes
print g_durations
play_pattern_timed g_notes, g_durations