I have a data “audioalization” (like in visualization) project that requires fairly expensive preparatory calculations (several seconds) before starting any loops. Then, I get a timing error (“thread got too far behind in time”).
My guess is that SP’s timer is already running, thus causing the error. Is there any possibility to prevent that? E.g. to reset the timer?
Here is some code that should reproduce the behaviour:
# Fake calculation to simulate expensive pre-processing
for i in range(0, 10000000)
x = 1 / 100.0
end
live_loop :tick do
sample :elec_plip, rate: 2
sleep sec_per_day
end
I know that I could use set_sched_ahead_time!, but the duration of the pre-processing is not really predictable as it depends on the amout of data.
# Fake calculation to simulate expensive pre-processing
for i in range(0, 10000000)
x = 1 / 100.0
end
wait(4)
live_loop :tick do
sample :elec_plip, rate: 2
sleep 1
end
Set the live_loop's delay:
# Fake calculation to simulate expensive pre-processing
for i in range(0, 10000000)
x = 1 / 100.0
end
live_loop :tick, delay: 4 do
sample :elec_plip, rate: 2
sleep 1
end
To make it work with the unpredictable duration, I will presumably have to measure the time it actually takes. But as Ruby’s Time class is available in SP, this should well be possible. I will try and report the solution here.
Works well with measuring time elapsed. The demonstrate by extending the example, it can be done like this:
start = Time.now
for i in range(0, 10000000)
x = 1 / 100.0
end
duration = Time.now - start
live_loop :tick, delay: duration + 0.5 do
sample :elec_plip, rate: 2
sleep 1
end
By the way, you may have realised this, but the difference between approaches 1 and 2 is that delay is non-blocking. To illustrate that, here’s a sample program using in_thread, which also has a delay option:
in_thread do
puts "test"
end
wait 1
in_thread delay: 1 do
puts "test wait & delay"
end
in_thread do
puts "test wait"
end
So far, I used delay: 0.01 in most of my projects to sync loops with a “metronome” main loop without delaying the other loops by one iteration. So, “unconsciously”, I already made use of this fact. Thanks!
Another option is of course to forego the use of arbitrary delays, and to use the sync: option of live_loops to sync on a cue that you emit once your preprocessing has completed
Ah, that would simplify things! I can’t seem to figure it out however, whether I place the calculations and cue before or after the live_loop
Here’s a straightforwardly erroneous attempt with cue placed before the live_loop:
# Fake calculation to simulate expensive pre-processing
for i in range(0, 10000000)
x = 1 / 100.0
end
cue :start
live_loop :tick, sync: :start do
sample :elec_plip, rate: 2
sleep 1
end
I know that calling cue before sync means that sync will never detect a cue, so I tried placing the calculation and cue after the live_loop. This didn’t work either:
live_loop :tick, sync: :start do
sample :elec_plip, rate: 2
sleep 1
end
# Fake calculation to simulate expensive pre-processing
for i in range(0, 10000000)
x = 1 / 100.0
end
cue :start