"Rational Melodies" by Tom Johnson

Hi! Yesterday I was listening to the Rational Melodies by the minimalist composer Tom Johnson. Now I’m thinking how can I write the code for the first piece:

As you can see, there’s only a few notes, repeated almost equally, but with a little change in each measure (the rests change their place). How could I write a code to play it with the option of changing the notes? Thanks!

Do you have any initial thoughts about the kinds of “building blocks” that you could use/you might need to make it work? :slightly_smiling_face:


I realized that we need to insert some rests at a changing position so here is what I suggest to answer your question

notes = [:d, :a, :b, :f5, :b, :a]

p1 = *notes
pattern_01 = p1.insert(1, :r)
pattern_01 = p1.insert(7, :r)
puts pattern_01
puts notes

p2 = *notes
pattern_02 = p2.insert(2, :r)
pattern_02 = p2.insert(7, :r)
puts pattern_02

p3 = *notes
pattern_03 = p3.insert(3, :r)
pattern_03 = p3.insert(7, :r)
puts pattern_03

use_synth :piano
use_synth_defaults sustain: 1, release: 1

play_pattern_timed pattern_01, 0.5
play_pattern_timed pattern_02, 0.5
play_pattern_timed pattern_03, 0.5


I’ve been trying with play_pattern without success. After the ideas of nlb, now I can complete the piece. I’ll share it when I finish it, thanks!


That’s it! Thank you so much! I’ll share the complete piece soon :slight_smile:

I recently came across a solution to this again, that I’d made a while ago and forgotten about. Here’s another way you could approach it:

# change the melody notes as desired
ns = (ring :d3, :a3, :b3, :fs4, :b3, :a3)

# 7 sequences, each made up of...
7.times do
  # ...7 bars
  7.times do
    # rotate the position of the rest note 'triggers' every time we play a
    # new bar of 8 notes
    rest_bools = (bools 0, 1, 0, 0, 0, 0, 0).rotate(-tick(:rotate))
    # on the last bar of every melody sequence,
    # (index 6 when starting from 0),
    # the number of rest triggers vs notes changes,
    # and we reset to start counting the bars of the next melody sequence again.
    if look(:rotate) == 6
      rest_bools = (bools 0, 1, 1, 1, 1, 1, 1)
    rest_bools = rest_bools + (bools 1)
    8.times do
      # 2 counters to track the next items in the melody notes
      # and the rest note triggers. Both counters count up regardless of
      # whether the next 'note' to play is melody or a rest.
      note = ns.look
      # if the next item in the rest note triggers is true / 1,
      # make the note to play a rest, and change the melody note counter
      # using tick_set so that the next melody note (which we want to be
      # played *after* this rest) is played *next* time, instead of
      # being skipped over entirely.
      # tick_set(X) causes both the next 'look' *and* 'tick'
      # to return X.
      if rest_bools.look(:rest) == true
        note = :r
      synth :piano, note: note
      sleep 0.25
1 Like