Tables & Waves

Self Similarity

Note List:
Steps:
BPM: 128 Step Rate:

About Self Similar Melodies

The form of self-similar melodies demonstrated here are note sequences that self replicate at multiple rhythms. For example, it is possible to construct a melodic line that plays the same sequence of notes if you play every note in order and also when you play every other note or every fourth note. The composer Tom Johnson used this technique for his composition "Rational Melody XV" and included this composition in his Illustrated Music series on YouTube [1]. (As an aside, this video series is excellent and includes a number of great visual examples of many different algorithmic composition techniques. Just go watch them!)

Here is a linear reprepsentation of a melody that self replicates at the ratios of 1:1, 2:1, 4:1 and 8:1.

Highlight Ratio Index:

Note Sequence C2 D2 D2 Eb2 D2 F2 Eb2 G2 D2 Eb2 F2 G2 Eb2 G2 G2
1:1 Note Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2:1 Note Index 1 9 2 10 3 11 4 12 5 13 6 14 7 15 8
4:1 Note Index 1 5 9 13 2 6 10 14 3 7 11 15 4 8 12
8:1 Note Index 1 3 5 7 9 11 13 15 2 4 6 8 10 12 14

To see what this table is trying illustrate, let's start with the top, header row. This row is the self-similar melody itself as a sequence of 15 notes. The sequence length is important and we'll get to the reason why 15 notes was chosen below. The second row is the indices of melody at the most basic one-to-one (1:1) ratio. Because this ratio is 1:1, the note sequence in the header row and the note indices (1-15) of the sequence line up with each other.

Things get interesting at the ratios that are not one-to-one. The third row in the table shows the 2:1 Note Index. This row simply counts by twos and (as all the subsequent rows do) it wraps around the sequence back to the beginning to continue counting when it runs out of columns. For a 15 note sequence, when counting by 2, the first pass through the sequence will be able to count up to 8. Then for the 9th index, it must go back to the beginning. It is important to note that when wrapping around, you still should count by N as you wrap around. Therefore, index 9 in this row is not the first note in the sequence, it is the second. This is because for a 15 note sequence, index 8 when counting by twos is the last note. The next note needs to be skipped and so the next skipped note is the first note in the second pass through the sequence.

The process that is used for the ratio 2:1 is also applied to 4:1 and 8:1 with the only difference being the "count by" amounts.

If you can follow things this far, let's now get to the observation that demonstrates why the sequence self replicates at multiple rhythms as noted above. The note corresponding to an index at any of the replication ratios is always the same. To see how this is true for the sequence example in this table, choose different note index values for the dropdown menu Highlight Ratio Index. These indexes will be highlighted in the table and the note corresponding to these indices will also be highlighted. No matter what index you choose, the highlighted notes in the top row are always the same note.

Sequence Length

One important thing to note about generating these sequences is that that the sequence length (number of notes) matters. In his book Self-Similar Melodies, Johnson writes of melodic loops, "The limitation is that if you want one to be self-replicating at the ration of n : 1, n has to be prime with the number of notes in the loop" (p. 237) [2]. (As another aside, go read this book! It is a treasure trove of techniques for generative melodies.) For practical purposes in my own work, I simply use sequence lengths of 2n - 1 because I am also only generating sequences that self-replicate at rations of 2n. This preserves the ability to let a sequence loop and maintain self-similarity.

In Johnson's video for "Rational Melody XV" he mentions the French researcher Emmanuel Amiot as a leading expert on self-similar melodies, which Amiot calls "autosimilar melodies." For an in-depth (though beyond my personal comprehension) look at the math behind self-similar melodies, see Amiot's article "Autosimilar Melodies" [3].

Basic Implementation

Below is a basic implementation for generating this kind of self-replicating melody in JavaScript. It will produce self-replication at powers of 2. It is not extremely efficient and may end up overwriting values in the sequence (with their previous value of course). It works by seeding the first two sequence steps from a list of notes and then repeatedly filling out the remaining steps until the sequence at powers of 2 until the sequence is complete. Copy the code and log the state of the sequence at each iteration of the loop to see how it progresses.

const selfReplicate = (noteList, length) => {

  let sequence = new Array(length).fill(-1);
  sequence[0]  = noteList[0];
  sequence[1]  = noteList[1];

  let contiguousSequence, currentNote, stepAmount, nextNote;
  let nextEmpty = sequence.findIndex(note => note == -1),
      count = 2;

  // Build a self replicating melody by powers of 2 until all notes are filled.
  do {
    contiguousSequence = sequence.slice(0, nextEmpty);

    for (let noteIndex = 0; noteIndex < contiguousSequence.length; noteIndex++) {
      // For each note in the contiguous sequence...
      currentNote = contiguousSequence[noteIndex];

      // Determine the self replicating step amounts by computing the powers of 2 for
      // non-redundant step amounts based on the target length
      for (let power = 1; power <= Math.log2(length); power++) {
        stepAmount = 2**power;

        // Fill in the melody's future step indices with the current replicating note.
        sequence[(noteIndex * stepAmount) % length] = currentNote;
      }
    }

    // If the sequence still has empty spots, find the first one and fill it with the next
    // note in the input note list.
    nextNote  = noteList[count % noteList.length];
    nextEmpty = sequence.findIndex(note => note == -1);
    if (nextEmpty != -1) sequence[nextEmpty] = nextNote;
    count++;
  } while (nextEmpty != -1);

  return sequence;
}


let noteList = ["C2", "D2", "Eb2", "F2", "G2"];
let length   = 15;
let sequence = selfReplicate(noteList, length);

References

  1. Johnson, Tom. "Illustrated Music #6, Rational Melody XV." Illustrated Music. 14 Aug. 2018. https://www.youtube.com/watch?v=Bqn7cLC6bak
  2. Johnson, Tom. Self-Similar Melodies. 1996. Fourth printing, Editions 75, 2017.
  3. Amiot, Emmanuel. "Autosimilar Melodies." Journal of Mathematics and Music, vol. 2, no. 3, 2008, pp. 157-180. DOI: 10.1080/17459730802598146