Tidal
Tidal copied to clipboard
setCycle, similar to resetCycle but for jumping to a specific cycle
import qualified Sound.Tidal.Tempo as T
_setCycle c tempoMV = T.changeTempo tempoMV (\t tempo -> tempo {T.atTime = t, T.atCycle = c})
streamSetCycle c s = do _ <- _setCycle c (sTempoMV s)
return ()
setCycle c = streamSetCycle c stream
d1 $ s "bd"
setCycle 10
setCycle 100
setCycle 50
setCycle 150
If you run the above, what you'll notice is that jumping backwards by n cycles seems to work fine, however jumping forwards results in a lot of messages being sent before normal service is resumed.
I'll post an OSC log or two here soon to demonstrate...
To work out what to query the pattern for, tidal first works out what the end of the time arc should be, based on the tempo. Rather than work out the start of the time arc, it just takes the end of the previous time arc. This is so that nothing is lost due to floating point error (cps is still floating point rather than rational), or due to the tempo changing.
This seems to works fine if travelling back in time, I guess because you end up with an arc that ends before it begins and returns nothing, so you lose one tick (1/20th of a second)'s worth of events (that might possibly explain while resetCycles
misses the start of the cycle..). It doesn't work if travelling forward in time, because you can end up with a very large arc.
The scheduler does skip frames if it gets too far behind/ahead, but not cycles. I think it's not straightforward to do that, as probably extreme changes in tempo would legitimately result in a large number of cycles being generated..
I think the fix would be adding a flag to the tempo datatype to indicate that the tempo has been reset and that the ticks should too.
that might possibly explain while resetCycles misses the start of the cycle..
Ah ha!
That all totally makes sense, thanks for explaining. So we're looking for a resetTicks
function to go along with this?
That all totally makes sense, thanks for explaining. So we're looking for a
resetTicks
function to go along with this?
Yes, although that would probably be an internal function, called from within resetCycles / setCycle
I think the fix would be adding a flag to the tempo datatype to indicate that the tempo has been reset and that the ticks should too.
Just coming back to this. Why is the tempo being reset? Isn't it just the cycles that are being reset/changed?
So something like this?
Add reset
flag here:
data Tempo = Tempo {atTime :: O.Time,
atCycle :: Rational,
cps :: O.Time,
paused :: Bool,
nudged :: Double,
localUDP :: O.UDP,
remoteAddr :: N.SockAddr,
synched :: Bool,
reset:: Bool
}
deriving Show
Set flag to True
when using _setCycle
:
_setCycle c tempoMV = T.changeTempo tempoMV (\t tempo -> tempo {T.atTime = t, T.atCycle = c, reset = True})
Watch for flag in clocked
, reset ticks
if needed, then reset flag. I don't know how to do this part :)