I am trying to make a timer that keeps track of how long a signal is above a threshold. So I thought of using SystemClock:
h = SystemClock.seconds.asInt.value //start timer
b = (SystemClock.seconds).asInt-h //calculate elapsed time
v = b //store elapsed time
h = SystemClock.seconds.asInt.value //restart timer
b = (SystemClock.seconds).asInt-h //calculate elapsed time
x = v+b //total of elapsed times
…
Is there any good practice to make this kind of timer smarter?
thanks. The ‘signal’ is on the client side, sorry, should have been clearer. It’s basically a float going up and down between 0.0 and 50.0. The threshold is around 10.0.
a = 12 //signal
//wait a few seconds;
a = 9
//wait a few seconds;
a = 11
//wait a few seconds;
a = 9
//wait a few seconds;
a = 15
//wait a few seconds;
a = 7
~timer
To post formatted code inline, enclose the `code` in single backticks.
```
To post blocks of formatted code, use three backticks on a line by themselves at the start and end of the block.
```
Your code does work, and I don’t know exactly what you mean by “smarter”, but here are a few quick observations that might help you clean things up:
If ~switch is a boolean value there’s no need for if(~switch == true), just call ~switch.if.
There’s no need to call SystemClock.seconds.asInt.value – SystemClock.seconds.asInt is already an Integer.
You can just call a and b~signal and ~threshold if you find yourself needing comments to remember that they refer to a signal and a threshold.
Similarly, it’s usually okay to use some type of IdentityDictionary instead of an Array to keep track of a group of related values. ~timer[\start] is easier for you and others to read than ~timer[0] etc.
As for your algorithm, because the resolution with which you can measure time is determined by how often the Routine yields, you don’t even need to use SystemClock, just an accumulator inside the Routine.
Here’s an example:
(
// this Routine just creates a fluctuating "signal" to test
// ~signal can be any Object that implements >=
~signal = 0;
~signalRoutine = Routine.new({
var str = Pbrown.new(0, 20, 1, inf).asStream;
inf.do({
~signal = str.next;
("Signal:" + ~signal).postln;
0.1.yield
})
});
// this Routine actually tests the value of ~signal over time
~testRoutine = Routine.new({
var counter, threshold, resolution, switch, zSwitch;
counter = 0;
threshold = 10;
resolution = 0.1;
switch = false;
zSwitch = false;
inf.do({
(~signal >= threshold).if {
counter = counter + resolution;
zSwitch.not.if { switch = true }
} {
zSwitch.if {
("Above threshold for" + counter + "seconds").postln;
counter = 0;
switch = false
}
};
zSwitch = switch;
resolution.yield
})
})
)
(
// start both Routines
~signalRoutine.play;
~testRoutine.play
)
(
// stop both Routines
~signalRoutine.stop;
~testRoutine.stop
)
Both! I wouldn’t worry too much about speed for its own sake at this scale, but it’s good practice to avoid the unnecessary comparison regardless. If you’re curious, you can benchmark the speed of a Function by calling bench on it. Results will vary depending on a lot of factors but this should give you a general idea of what is and isn’t good design.
For the results to be meaningful, you’ll want to benchmark a lot of iterations at once. For example: