Hi there -- I&#39;ve recently started playing with Impromptu, and am thoroughly enjoying it (thanks!).  However, I&#39;ve found that the make-metre function doesn&#39;t always &quot;sync&quot; properly to the metronome.  Often, when I ask for beat 1 (for example), it returns #f at a time when it should return #t.  I debugged the problem and found that the problem seems to be in floating-point rounding.<div>
<br></div><div>I notice that in the documentation for fmod (which make-metre uses) you say Impromptu rounds to 4 decimal places to &quot;try to avoid some floating point precision problems.&quot;  I&#39;m still seeing them, in my programs (basically variants on the Messiaen tutorial).  Rather than doing rounding, perhaps you might consider using a tolerance/epsilon value in time comparisons.</div>
<div><br></div><div>I modified make-metre to a version which &quot;always&quot; (so far, at least ;-) returns the expected result, regardless of the metronome value and the total metre length (I&#39;m using a length of 12 beats -- one bar in 12/8 time).  In case it&#39;s useful for anyone, I&#39;ll post it here (this can replace the version in time-lib.scm)...  With this, my examples work reliably -- without it, every now and then (depending on what value the metronome has at time of first call) my &quot;composing&quot; callback function just does nothing, missing all the beats, especially beat 1!  The other problem, specific to queries for beat 1.0 was that often (if the metronome time was a fractional bit below the next beat, e.g. 11.9999), it would compare with &quot;metre-length + 1&quot;, i.e. 13, rather than with 1, and so return #f.  I added a test for this specific case, which solves all the problems I was having.</div>
<div><br></div><div>;=============== (a bit of time-lib.scm)</div><div><br></div><div><div>; x and y are the numbers to compare</div><div>; tol is the fractional tolerance of the smaller number below</div><div>; which they will be considered &quot;close enough&quot;</div>
<div>(define close-rel (lambda (x y tol)</div><div>                     (&lt;= (abs (- x y)) (* (abs tol) (min (abs x) (abs y)) ) )</div><div>                     )</div><div>   )</div><div><br></div><div>; this is another version, with an absolute</div>
<div>; tolerance (in units of x and y, not relative in percentage)</div><div>(define close-abs (lambda (x y tol)</div><div>                     (&lt;= (abs (- x y)) (abs tol))</div><div>                     )</div><div>   )</div>
<div><br></div><div>(define *metre-tol* 1.0e-3)</div><div><br></div><div>; creates a meter where metre is a list of numerators </div><div>; and base is a shared denominator (relative to impromptu beats. i.e. 1 = crotchet,  0.5 = eighth etc.)</div>
<div>; </div><div>; e.g.  (define *metre* (make-metre &#39;(2 3 2) 0.5)) = 2/8 3/8 2/8 rotating cycle.</div><div>; </div><div>; then call meter with time and beat </div><div>; if beat matches time then #t else #f</div><div>
;</div><div>; e.g. give the above define</div><div>;      (*metre* 2.5 1.0) =&gt; #t because 0.0 = 1, 0.5 = 2, 1.0 = 1, 1.5 = 2, 2.0 = 3, 2.5 = 1, 3.0 = 2 and repeat.</div><div>(define make-metre</div><div>   (lambda (metre base)</div>
<div>      (let ((metre-length (apply + metre)))</div><div>         (lambda (time beat)</div><div>            (close-abs (let loop ((qtime (fmod (/ time base) metre-length))</div><div>                              (lst metre)</div>
<div>                              (valuea (car metre))</div><div>                              (valueb 0))</div><div>                          (if (close-abs qtime metre-length *metre-tol*)</div><div>                             1.0</div>
<div>                             (if (&lt; qtime valuea)</div><div>                                (+ 1.0 (- qtime valueb))</div><div>                                (loop qtime (cdr lst) (+ valuea (cadr lst)) (+ valueb (car lst)) ) )</div>
<div>                          )</div><div>                       )</div><div>                       beat *metre-tol*)</div><div>         )</div><div>      )</div><div>   )</div><div>)</div><div><br></div><div><div>;===============</div>
<div><br></div><div>Hope this is helpful.  Keep up the great work with Impromptu,</div><div>Glen F.</div><div><br></div></div></div>