get it:
- install haskell (easiest way)
- install supercollider
- in the terminal:
cabal install vivid
- on linux, start Jack:
jackd -d alsa
- start the supercollider server. in the terminal:
export SC_JACK_DEFAULT_INPUTS="system" export SC_JACK_DEFAULT_OUTPUTS="system" scsynth -u 57110
{-# LANGUAGE DataKinds, ExtendedDefaultRules #-}

import Vivid

wobble = sd (0 ::I "note") $ do
   s <- 50 ~* sinOsc (freq_ 10) ? KR
   s1 <- 0.1 ~* sinOsc (freq_ $ midiCPS (V::V "note") ~+ s)
   out 0 [s1, s1]

main = do
   s <- synth wobble ()
   let notes = take 12 $
         [ x | x <- [38..], (x `mod` 12) `elem` [0,3,5] ]
   forM_ (cycle notes) $ \note -> do
      set s (toI note ::I "note")
      wait 0.2
{-# LANGUAGE DataKinds, ExtendedDefaultRules #-}

import Vivid

tone = sd (0::I "note") $ do
   a <- lfTri (freq_ 0.2) ? KR ~* 0.5 ~+ 0.5
   freq <- lag (in_ $ midiCPS (V::V "note"), lagSecs_ 1.25) ? KR
   b <- 0.1 ~* varSaw (freq_ freq, width_ a)
   out 0 [b, b]

main = do
   s <- synth tone (45::I "note")
   forever $ forM_ [45, 57, 64, 55] $ \freq -> do
      set s (freq :: I "note")
      wait 2.5
Using Vivid with TidalCycles (how to do it)
docs
the best place for questions is currently the livecode mailing list

FAQ

These answers mainly come from questions asked on the mailing list. If you've got a question not answered here, ask there!

How do I use Vivid with TidalCycles?


This is a bit old. It's probably simpler now.



How do I convert to an "I" type?

If you want a I "foo" but all you've got is a Double or Int or even a I "bar" (any Real number), you can convert it with the toI function.

Here's an example:

a = 5 :: Double
b = toI a :: "foo"

c = 5 :: I "bar"
d = toI c :: I "foo"

Here's how you might use it in a performance:

{-# LANGUAGE DataKinds, ExtendedDefaultRules #-}

import Vivid

myNums :: [Double]
myNums = [1..10]

sd0 = undefined :: SynthDef '["freq"]
sd1 = undefined :: SynthDef '["amp"]

main = do
   s0 <- synth sd0 ()
   s1 <- synth sd1 ()
   forM_ myNums $ \n -> do
      set s0 (toI n :: I "freq")
      set s1 (toI n :: I "amp")

How do I ensure sample-accurate timing?

If you have a piece of music - let's say:
mySong = do
   fork $ do
      wait 1
      s1 <- synth foo ()
      wait 1
      free s
   s2 <- synth bar ()
   wait 1.5
   free s2
It has the type:
mySong :: VividAction m => m ()
If you call mySong in GHCi, it will be a IO () action and the timing will be handled by Haskell. It won't be sample-accurate. But, if you call
doScheduledIn 0.2 mySong
the timing will be sample-accurate, scheduled on SC's server (0.2 seconds from now). There's also doScheduledAt which - with getTime and addSecs - gives us the absolute-time version.

In addition, if you call:

writeNRT "foo.wav" mySong
the song will be rendered (much) faster than real time to the file, also sample-accurate.