> module HSoM.Examples.RandomMusic where
> import Euterpea
> import System.Random
> import System.Random.Distributions
> import qualified Data.MarkovChain as M
> sGen :: StdGen
> sGen = mkStdGen 42
> randInts :: StdGen -> [Int]
> randInts g = let (x,g') = next g
> in x : randInts g'
> randFloats :: [Float]
> randFloats = randomRs (1,1) sGen
> randIntegers :: [Integer]
> randIntegers = randomRs (0,100) sGen
> randString :: String
> randString = randomRs ('a','z') sGen
> randIO :: IO Float
> randIO = randomRIO (0,1)
> randIO' :: IO ()
> randIO' = do r1 <- randomRIO (0,1) :: IO Float
> r2 <- randomRIO (0,1) :: IO Float
> print (r1 == r2)
> toAbsP1 :: Float -> AbsPitch
> toAbsP1 x = round (40*x + 30)
> mkNote1 :: AbsPitch -> Music Pitch
> mkNote1 = note tn . pitch
> mkLine1 :: [AbsPitch] -> Music Pitch
> mkLine1 rands = line (take 32 (map mkNote1 rands))
uniform distribution
> m1 :: Music Pitch
> m1 = mkLine1 (randomRs (30,70) sGen)
linear distribution
> m2 :: Music Pitch
> m2 = let rs1 = rands linear sGen
> in mkLine1 (map toAbsP1 rs1)
exponential distribution
> m3 :: Float -> Music Pitch
> m3 lam = let rs1 = rands (exponential lam) sGen
> in mkLine1 (map toAbsP1 rs1)
Gaussian distribution
> m4 :: Float -> Float -> Music Pitch
> m4 sig mu = let rs1 = rands (gaussian sig mu) sGen
> in mkLine1 (map toAbsP1 rs1)
Gaussian distribution with mean set to 0
> m5 :: Float -> Music Pitch
> m5 sig = let rs1 = rands (gaussian sig 0) sGen
> in mkLine2 50 (map toAbsP2 rs1)
exponential distribution with mean adjusted to 0
> m6 :: Float -> Music Pitch
> m6 lam = let rs1 = rands (exponential lam) sGen
> in mkLine2 50 (map (toAbsP2 . subtract (1/lam)) rs1)
> toAbsP2 :: Float -> AbsPitch
> toAbsP2 x = round (5*x)
> mkLine2 :: AbsPitch -> [AbsPitch] -> Music Pitch
> mkLine2 start rands =
> line (take 64 (map mkNote1 (scanl (+) start rands)))
> m2' = let rs1 = rands linear sGen
> in sum (take 1000 rs1) / 1000 :: Float
> m5' sig = let rs1 = rands (gaussian sig 0) sGen
> in sum (take 1000 rs1)
> m6' lam = let rs1 = rands (exponential lam) sGen
> rs2 = map (subtract (1/lam)) rs1
> in sum (take 1000 rs2)
some sample training sequences
> ps0,ps1,ps2 :: [Pitch]
> ps0 = [(C,4), (D,4), (E,4)]
> ps1 = [(C,4), (D,4), (E,4), (F,4), (G,4), (A,4), (B,4)]
> ps2 = [ (C,4), (E,4), (G,4), (E,4), (F,4), (A,4), (G,4), (E,4),
> (C,4), (E,4), (G,4), (E,4), (F,4), (D,4), (C,4)]
functions to package up run and runMulti
> mc ps n = mkLine3 (M.run n ps 0 (mkStdGen 42))
> mcm pss n = mkLine3 (concat (M.runMulti n pss 0
> (mkStdGen 42)))
music-making functions
> mkNote3 :: Pitch -> Music Pitch
> mkNote3 = note tn
> mkLine3 :: [Pitch] -> Music Pitch
> mkLine3 ps = line (take 64 (map mkNote3 ps))
testing the Markov output directly
> lc ps n = take 1000 (M.run n ps 0 (mkStdGen 42))
> lcl pss n m = take 1000 (M.runMulti n pss 0 (mkStdGen 42) !! m)