Skip to content

Instantly share code, notes, and snippets.

@jarmitage
Last active December 26, 2017 23:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarmitage/128b104302299135669bfbfca02c4ccc to your computer and use it in GitHub Desktop.
Save jarmitage/128b104302299135669bfbfca02c4ccc to your computer and use it in GitHub Desktop.
Turning a TidalCycles pattern into JSON
import qualified Data.Aeson as A
data TidalEvent =
TidalEvent { arc1 :: Arc,
pmap :: ParamMap
} deriving Show
instance A.ToJSON TidalEvent where
toJSON (TidalEvent arc1 pmap) =
A.object [ "arc1" A..= arc1,
"pmap" A..= pmap
]
{-
Error for above:
• No instance for (A.ToJSONKey Param) arising from a use of ‘A..=’
• In the expression: "pmap" A..= pmap
In the first argument of ‘A.object’, namely
‘["arc1" A..= arc1, "pmap" A..= pmap]’
In the expression: A.object ["arc1" A..= arc1, "pmap" A..= pmap]
-}
-- Added to https://github.com/tidalcycles/Tidal/blob/1d05c6119aba8c7547bbf1512ce1f901e38e1d6c/Sound/Tidal/Stream.hs
import qualified Data.Aeson as A
-- ...
instance A.ToJSON Value where
toJSON (VS s) = A.toJSON s
toJSON (VF d) = A.toJSON d
toJSON (VI i) = A.toJSON i

Notes

The goal is to take a Tidal pattern (www.tidalcycles.org) and turn it into JSON, so it can be sent to a web app for visualisation

To do this first we need to be able to encode a Tidal pattern as JSON

A Tidal pattern such as this

n "1" # gain 1 # cutoff "100"

When turned into an Arc like so...

arc (n "1" # gain 1 # cutoff "100") (now, now + 1)

Will produce an output like this, which we want to turn into JSON

[((728 % 1,729 % 1),(728 % 1,729 % 1),fromList [(cutoff,100.0),(gain,1.0),(n,1)])]

If we look at the type of arc (n "1" # gain 1 # cutoff "100") (now, now + 1) we get

[Event ParamMap]

An Event is two Arcs plus a pattern or ParamMap

type Event = (Arc, Arc, a) https://github.com/tidalcycles/Tidal/blob/master/Sound/Tidal/Time.hs#L27

An Arc is a 'start' and 'end' time

type Arc = (Time, Time) https://github.com/tidalcycles/Tidal/blob/master/Sound/Tidal/Time.hs#L18 type Time = Rational https://github.com/tidalcycles/Tidal/blob/master/Sound/Tidal/Time.hs#L14

A pattern is a ParamMap

type ParamMap = Map.Map Param Value https://github.com/tidalcycles/Tidal/blob/1d05c6119aba8c7547bbf1512ce1f901e38e1d6c/Sound/Tidal/Stream.hs#L75

    data Param = S {name :: String, sDefault :: Maybe String}
               | F {name :: String, fDefault :: Maybe Double}
               | I {name :: String, iDefault :: Maybe Int}
      deriving Typeable -- https://github.com/tidalcycles/Tidal/blob/1d05c6119aba8c7547bbf1512ce1f901e38e1d6c/Sound/Tidal/Stream.hs#L29
    
    data Value = VS { svalue :: String } | VF { fvalue :: Double } | VI { ivalue :: Int }
           deriving (Eq,Ord,Typeable) -- https://github.com/tidalcycles/Tidal/blob/1d05c6119aba8c7547bbf1512ce1f901e38e1d6c/Sound/Tidal/Stream.hs#L48

To encode something into JSON you need to use Data.Aeson and create instances of your data. See https://artyom.me/aeson, https://www.schoolofhaskell.com/school/starting-with-haskell/libraries-and-frameworks/text-manipulation/json

-- Added to https://github.com/tidalcycles/Tidal/blob/master/Sound/Tidal/Time.hs
import qualified Data.Aeson as A
-- ...
data TidalTime = TidalTime { time :: Time } deriving Show
instance A.ToJSON TidalTime where
toJSON (TidalTime time) = A.toJSON time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment