194 Polyrhythm Trainer


Greetings fellow Rubyists,

This week’s quiz is to create a polyrhythm training program. The user will be prompted to tap out a rhythm with two keys: left and right. Each time the user presses a key the program will display how close to the correct timing the key press occurred. The program will be configurable to train the user in any polyrhythm 2:3, 5:4, 11:17, and so on. The program will also have a configurable tempo. After a number of complete rhythms the program will display the ratio of how many notes were successfully struck, success determined by being within a threshold around the perfect timing.

The display can be as simple as a console application or use a full graphical interface. Ruby Inside recently had an article about graphical toolkits if you are interested.

Polyrhythm is the simultaneous sounding of two or more independent rhythms.


This quiz may be worthy of a revisit in the future. Until then here is my solution, the beginnings of an “Annoyance” trainer.

# rhythm.rb

class Rhythm
  BPM = 20
  def initialize(n, sym)
    @sym = sym
    @seconds_per_hit = SECONDS_PER_MINUTE/(BPM*n)
    @last_hit = @seconds_per_hit
    @hit_count = 0
    @time = 0
    puts @seconds_per_hit
  def elapse(time_elapsed)
    hit = false
    if @last_hit >= @seconds_per_hit
      @hit_count += 1
      @last_hit -= @seconds_per_hit
      puts "#{"%1.3f" % @time}: #{@sym}"
      hit = true
    @time += time_elapsed
    @last_hit += time_elapsed
    return hit

s = '@'

rhythms = ARGV.map{|arg| Rhythm.new(arg.to_i, s = s.succ)}

delta = 0.05
time = 0

while true
  hit = rhythms.map{|r| r.elapse(delta)}.inject(false) {|hit, r| hit || r}
  print "\a" if hit
  time += delta
  sleep delta

The program will beep indefinitely, producing a sound every time the rhythm should be struck (to the nearest 20th of a second).

Usage: ruby rhythm.rb [rhythms]

EX: > ruby rhythm.rb 3 2
0.000: A
0.000: B
1.000: A
1.500: B
2.000: A
3.000: A
3.000: B
4.000: A
4.500: B
5.000: A

Crank up the volume on your PC speaker and have a blast near your co-workers!

Sunday, March 01, 2009