Thanks - fixed that.
I’ve also noticed that there’s a division by zero error if the number of bars is set to 1, so I’ll need to fix that also.
Or we could change the default in Click Track to 8
In most cases I’d expect that the user would set this value to suit there needs and using the default would be pretty rare.
If I was going to explain that I’d just say that it makes the tempo speed up or slow down by the specified number of beats per minute - which is pretty well what the control says.
I suppose it’s not obvious that the speed changes from bar to bar rather than from beat to beat (so the tempo within any one bar is constant). I don’t think that it justifies a built-in help screen but I’ll add a text file with some documentation. The “Swing” and “Randomize” settings may also be worth a note.
The problem is line numbers 272 - 273.
(setf measure (sim measure
(stretch-abs (* sig beatlen) (const 0.0))))
(stretch-abs) performs a linear time transformation to make 1 second of silence (created at the control sample rate) stretch (approximately) to the length of the bar, but depending on the precise bar length and sample rate, the final (stretched) length may not be exact.
A more accurate method would be to use (s-rest [duration]) to generate silence of the required length, so those lines would become:
(setf measure (sim measure (s-rest (* sig beatlen))))
Because s-rest is generated at the current sound sample rate it will be accurate to within 1 sample (per bar).
This gives an accuracy at 130 bpm, 1 beat per bar, of about 2 ms over a 5 minute track at 48 kHz.
I think the worst case scenario should be if the tempo were such that the bar length fell in the middle between 2 samples. This would give an error of 0.011337868 ms per bar at a sample rate of 44100 Hz.
I’d say that it was pretty tiny (about 0.0023%), but for some tempos it can be worse (129 bpm with 1 beat per bar at 48kHz sample rate gives an error of over 0.12 seconds) and its better if it’s right.
Something like this is probably the neatest solution as it avoids cumulative errors altogether. Looking back to lines 272 - 273 we see that these lines are now redundant as we are not using the length of the measure to set the start position of the next measure.
The only drawback to this is that we then loose the trailing silence at the end of the track, so we could add that on at the end by replacing:
(setf result (if (= offset 0) result
(sim (s-rest offset) (at-abs offset (cue result)))))
; return [click track] result
(seq (s-rest offset)(cue result)(s-rest(- beatlen ticklen)))
as this returns the final click track the last couple of lines are not required.
David’s code is probably not the best example of code formatting - he did not tend to use line indentations because he was blind. While trying to unravel his code I’ve added some indentations which will hopefully make it a little easier to follow. I’ve also restructured his error checking code so that it’s no longer checking double negatives. The only other change that I’ve made is to remove “0 0” from the start of two (pwl) functions as t=0 l=0 is implicit with (pwl).
The only change that I made to your code was to use (1+ x) rather than (+ x 1).
I’ve attached a revised version, renamed as clicktrack2.ny. The changes have turned out to be somewhat more extensive than I originally intended so it would be helpful if it could be tested by as many people as possible - particularly the error checking aspects. This effect will be listed as “Click Track 2…” so that it can be installed alongside the original version.
clicktrack2.ny (9.74 KB)