packages feed

hsc3-graphs-0.11: src/chain-saw.hs

-- chain saw (jrhb)

{- this graph generates long chains of unit generators and may require
increasing the stack limit of the haskell run time system -}

import Control.Monad
import qualified Sound.SC3.Lang.Random.IO as R
import Sound.SC3.Monadic

coinIf :: Double -> a -> a -> IO a
coinIf n a b = do
  r <- R.coin n
  return (if r then a else b)

exprange :: UGen -> UGen -> UGen -> UGen
exprange s = linExp s (-1) 1

chain :: Monad m => Int -> (b -> m b) -> b -> m b
chain n fn = foldr (<=<) return (replicate n fn)

mceProduct :: UGen -> UGen
mceProduct = mceEdit (\l -> [product l])

clipu :: BinaryOp a => a -> a
clipu s = clip2 s 1

dup :: UGen -> UGen
dup a = mce2 a a

chain_saw :: IO UGen
chain_saw = do
  let f s1 = do xr <- fmap dup (expRand 0.1 2)
                n1 <- lfNoise1 KR xr
                n2 <- lfNoise1 KR xr
                n3 <- lfNoise1 KR xr
                f1 <- coinIf 0.6 (exprange n1 0.01 10) (exprange n2 10 50)
                s2 <- coinIf 0.5 (1 - s1) (mceReverse s1)
                let f2 = linExp s1 (-1) 1 f1 (f1 * exprange n3 2 10)
                    u1 = lfSaw KR f2 0
                    u2 = lfSaw KR (f1 * 0.1) 0 * 0.1 + 1
                return . clipu =<< coinIf 0.5 (u1 * s2) (u1 * u2)
      inp = lfSaw KR (0.2 * mce2 1 1.1) 0
      b_freq = mce [70, 800, 9000, 5242]
  ff <- chain 8 f inp
  let c_saw = mceProduct (saw AR (exprange ff 6 11000))
      b_saw = dup (mix (bpf c_saw b_freq 0.2))
  return (b_saw * 0.3)

main :: IO ()
main = audition . out 0 =<< chain_saw