Tidal icon indicating copy to clipboard operation
Tidal copied to clipboard

Viewing and resetting the cycle count

Open yaxu opened this issue 6 years ago • 3 comments

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

yaxu avatar Jan 09 '19 13:01 yaxu

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

gilfuser avatar Jan 09 '19 17:01 gilfuser

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.

yaxu avatar Aug 26 '19 08:08 yaxu

Related #709

jarmitage avatar Sep 03 '20 06:09 jarmitage