Viewing and resetting the cycle count
For linear compositions and so on, for example when using seqP, seqPLoop, and ur, it makes sense to reset the clock, so that a loop can be started 'now'.
There is a quick hack for resetting the cycle currently implemented, resetCycles. It's hacky because it resets the cycle count to minus 0.5, otherwise the first event of a currently playing pattern will often get missed. The tempo code needs some refactoring to clean up this race condition.
Also, the documentation refers to getNow, but that isn't currently implemented: https://tidalcycles.org/index.php/seqP#seqPLoop
Here's a way to make it:
import Control.Concurrent.MVar (readMVar)
import qualified Sound.OSC.FD as O
import Sound.Tidal.Tempo
let getNow = do tempo <- readMVar $ sTempoMV tidal
time <- O.time
return $ timeToCycles tempo time
Running getNow will give a rational value that isn't easy for a normal human to understand. sam <$> getNow will get the current cycle count as an integer. It'd be nice to have a way to visualise this as part of the editor (one for feedforward, at least). Here's something for visualising the cycle with the help of a fish:
import Control.Concurrent (threadDelay)
import qualified Control.Monad as CM
wave n = drop i s ++ take i s
where
s = "¸.·´¯`·.´¯`·.¸¸.·´¯`·.¸.·<º)))><" :: String
i = n `mod` (length s)
tick n = do now <- getNow
threadDelay $ 1000000 `div` 20
let steps = 16
n' = floor $ sam (now * 16)
cycles = n' `div` 16
CM.when (n /= n') $
putStr $ show cycles ++ " | " ++ wave n' ++ "\r"
tick n'
showFish = tick 0
showFish
In practice you might not want to reset the clock, but delay introduction of a pattern until the next modulo of the cycle count, or something like that.
So three things really
- [ ] Thing for quickly viewing / visualising the current cycle count
- [ ] Better way to reset the clock
- [ ] A way (probably as a transition function) to schedule individual patterns to start 'now', or at some future sam
Hi yaxu. I'm getting an error when I evaluate
wave n = drop i s ++ take i s
where
s = "¸.·´¯`·.´¯`·.¸¸.·´¯`·.¸.·<º)))><" :: String
i = n `mod` (length s)
tick n = do now <- getNow
threadDelay $ 1000000 `div` 20
let steps = 16
n' = floor $ sam (now * 16)
cycles = n' `div` 16
CM.when (n /= n') $
putStr $ show cycles ++ " | " ++ wave n' ++ "\r"
tick n'
showFish = tick 0
The error is <interactive>:52:5: error: parse error on input 'tick'
I'm using tidal-vim
I tried the version in lurk tidal channel which looks the same, but it make everything else stop working. Does it make sense?
bests, Gil
Work on #501 is a step towards accurate clock resetting.
Currently though, resetCycles doesn't take latency into account, so events get missed from the start of the cycle. For now a workaround is this resetCyclesTo function:
import qualified Sound.Tidal.Tempo as T
resetCyclesTo n = T.changeTempo (sTempoMV tidal) (\t tempo -> tempo {T.atTime = t, T.atCycle = n})
Then you can do resetCyclesTo (-0.05), adjusting the value of -0.05 until you get close to an immediate change without lost events.
Related #709