Tidal
Tidal copied to clipboard
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