https://alexanderacker-com.github.io/blog/feed.xml

Linearize rhythm: Program that describes how to count polyrhythms

2024-02-05

I made a neat tool in a few minutes for analyzing rhythms and find it kind of fascinating.

Main idea

  • The tool lets you write many independent rhythm patterns as input
  • The tool then puts all these patterns together into a multi-voice pattern
    • (as if these patterns were all played over the same duration)
  • This multi-voice pattern makes it easier to play complex rhythms together

The full main.rs can be found in this gist.

Simple example

Ignoring the rest of the program the polyrhythm is hard-coded in the main function.

If we modify the inputs to only contain two patterns we can "explain" a 3/2 polyrhythm

  • We tell the program as input to play a triplet and two-half notes over each other
fn main() {
    let triple =
        AbsolutePatternSingleVoice::new(3, vec![(1, true), (1, true), (1, true)]).unwrap();
    let half = AbsolutePatternSingleVoice::new(2, vec![(1, true), (1, true)]).unwrap();

    let combined_pattern = AbsolutePatternMultipleVoice::from_many(vec![triple, half]);
    println!("{}", combined_pattern);
}
  • The main function will give us an explanation of how to play the pattern including the number of beats
  • And now we can see a simpler way to think about this polyrhythm is the following:
Beats: 6
1: 0 1 
2: 
3: 0 
4: 1 
5: 0 
6: 
  • So rather than 3/2 we think 6 beats
  • First beat both voices play
  • Then on beat 3 they do an alternating triplet pattern

Full example

We evenly fit 3 patterns into the same duration of time:

  • 4 notes
  • 3 notes (triplet) with the middle dropped out
  • 2 notes
fn main() {
    let quarter =
        AbsolutePatternSingleVoice::new(4, vec![(1, true), (1, true), (1, true), (1, true)])
            .unwrap();
    let triple =
        AbsolutePatternSingleVoice::new(3, vec![(1, true), (1, false), (1, true)]).unwrap();
    let half = AbsolutePatternSingleVoice::new(2, vec![(1, true), (1, true)]).unwrap();

    let combined_pattern = AbsolutePatternMultipleVoice::from_many(vec![quarter, triple, half]);
    println!("{}", combined_pattern);
}

We get a 12 beat pattern:

Beats: 12
1: 0 1 2 
2: 
3: 
4: 0 
5: 
6: 
7: 0 2 
8: 
9: 1 
10: 0 
11: 
12: 
  • Now if you count a measure with 12 beats
  • And play voices 0-2 on the right beats
  • You will be playing the 3 polyrhythms over each other