Visualizing the tempo changes and the beat progression in a group

This how-to details a possible approach to visualize the local position progression and the local tempo change in an arbitrary group. We illustrate the approach on a specifioc example but the reader may adapt it immediately to its proper needs.

We suppose that some external process drive a tempovar $pos_to_play. To make the example self-contened, we emulate this process by a loop that shrink in time:

@tempovar $pos_to_play(85,1) := 100

$p := 1
Loop DRIVE $p s
  $ref_tempo := 60./$p
  $old_p := $p
  if ($p > 0.5) { $p *= 0.9 }
  $pos_to_play := 1
} during [20#]

The loop DRIVE is used as a kind of metronome implementing an accelerando. The period is given by $p and starts at 1 second, i.e. a tempo of 60 BPM. At each iteration, the period is shortened until it drops below 0.5, i.e. a tempo of 120.

The tempovar is initialized with a tempo of 80. Therefore, the tempo computed by the tempovar will start to decrease (slowly) and then increase until is alignment to the tempo fixed by the limit valiuue of $p.

We suppose that the tempovar is used to control the timing of a loop spanned by a whenever:

$graincurvesduration := 50

$t := []
$tt := []
$pos := []
$rpos := []
$rcpos := []
$tpo := []
$ftpo := []
$xx := []
$top_x := []
$top_t := []  
$top_delta := []  

whenever ($pos_to_play == $pos_to_play)
  @local $x := 0

     _ := $tt.push_back($NOW)
     _ := $ftpo.push_back(60./$p)

     Loop L  $graincurvesduration ms 
        @sync $pos_to_play
        @Abort {
         $top_x.push_back(60. * $x)
             $x +=  $graincurvesduration/1000.
             _ := $t.push_back($NOW)         
             _ := $pos.push_back($pos_to_play.position)      
             _ := $rpos.push_back($pos_to_play.rnow)         
             _ := $rcpos.push_back($pos_to_play.rcnow)       
             _ := $tpo.push_back($pos_to_play.tempo)
             _ := $xx.push_back(60.*$x)

The nternal loop L is used to emulate an activity whose timing is driven by the tempovar. The period is fixed in absolute time and the variable $x is incremented at each iteration. The others variables are tabs recording various informations during the run.

The expression ::antescofo $pos_to_play.position returns the current position (in beat) of the tempovar. This expression could have been replaced by @local_beat_position() which is more general. Function @local_beat_position returns the position in beat of the current temporal scope. So it can be used for any kind of synchronization reference. Similarly for ::antescofo $pos_to_play.tempo and @local_tempo.

The information recorded can be ploted using @gnuplot:

11 s
$gnuplot_path := "/usr/local/bin/gnuplot"
  ; $gnuplot_linestyle := "lines"

  _ := @gnuplot(
        "tempo", $t, $tpo,
        "forced tempo", $tt, $ftpo,
        "position", $t, $pos,
        "rnow", $t, $rpos,
        "curveX", $t, $xx,
        "maxX", $top_t, $top_x

and the execution of the full program builds the following plot:

local tempo and position progression

The timing and synchronization behavior can be read as follow:

  • The violet staircase curve tempo represents the tempo computed by the tempovar. It decrease and the it converges to the tempo forced by the DRIVE loop. The curve is a staircase because the tempo computed by a tempovar (using the E. Large approach) is updated only when the tempovar is updated.

  • The tempo emulated by the DRIVE loop is pictured in green (curve labeled forced tempo). It increases starting from 60 until it exceeds 120.

  • The value of $x starts at 0 eachtime the whenever is activated. It increase linearly with the iteration of the loop L. It is ploted in yellow and labeled curveX. The body of this loop records also the local tempo and the local position.

  • When the whenever is activated, the previous activation is killed (as a result of the @exclusive attribute). The abord handler of the internal loop is used to record the maximal value reached by $x. This value is ploted on the blue circled curve labeled _maxX_q. Because the period is shrinking, the maximal value reached by $x decreases until the period stabilizes.