packages feed

hsc3-graphs-0.11: src/cds-070701.hs

-- | cds-070701 (rd)
--
-- The 'source' data are breakpoint sets normalized over the time
-- interval (0,1).  There are a fixed number of 'locations' per cycle.
-- The data sets are sampled at these locations and loaded into
-- buffers.  The buffers are read using dbufrd.  One of the data sets
-- gives the time interval to step forward.
import Sound.OpenSoundControl
import Sound.SC3.Monadic

-- | Real
type R = Double

-- | Point
type P = (R,R)

-- | Data set
type D = [P]

-- | Points that bracket a time.
pts :: D -> R -> (P,P)
pts d n =
    case d of
      p0:p1:r -> let (t,_) = p1
                 in if n <= t
                    then (p0,p1)
                    else pts (p1:r) n
      _ -> error "pts"

-- | Linear interpolation.
--
-- > lerp 0.5 (0,0) (1,1) == (0.5,0.5)
-- > lerp 0.25 (0,0) (0.5,1) == (0.25,0.5)
lerp :: R -> P -> P -> P
lerp n (t0,d0) (t1,d1) =
  let n' = (n - t0) / (t1 - t0)
      f i = d0 + ((d1 - d0) * i)
  in (n,f n')

-- | Linear interpolating lookup.
fetch :: D -> R -> P
fetch t n =
  let (p0,p1) = pts t n
  in lerp n p0 p1

-- | Linearize in time (ie. /t/ is in equal steps).
rescale :: D -> Int -> D
rescale t n = map (fetch t) [0,1 / fromIntegral n .. 1]

-- | Allocate data buffers for linearized envelopes.
alloc_data :: Int -> IO ()
alloc_data n = do
  let alloc fd b = async fd (b_alloc b n 1)
  withSC3 (\fd -> mapM_ (alloc fd) [10,11,12,13])

-- | Data can be loaded while nodes are running, ie. edited online.
load_data :: Int -> (D,D,D,D) -> IO ()
load_data n (t,f,a,p) = do
  let setup d = map snd (rescale d n)
  withSC3 (\fd -> do send fd (b_setn 10 [(0,setup t)])
                     send fd (b_setn 11 [(0,setup f)])
                     send fd (b_setn 12 [(0,setup a)])
                     send fd (b_setn 13 [(0,setup p)]))

-- | Simple synthesis of data.
play_data :: IO ()
play_data = do
  let inf_sc = 9e8
  phase <- dseries inf_sc 0 1
  t' <- dbufrd 10 phase Loop
  f' <- dbufrd 11 phase Loop
  a' <- dbufrd 12 phase Loop
  p' <- dbufrd 13 phase Loop
  let tr = tDuty AR t' 0 DoNothing 1 0
      f'' = demand tr 0 f'
      a'' = demand tr 0 a'
      p'' = demand tr 0 p'
  audition (out 0 (pan2 (ringz tr f'' 0.2) p'' a''))

-- | Sample data sets, load using 'load_data'.
data_1 :: (D,D,D,D)
data_1 = ([(0,0.1),(0.65,0.025),(1,0.1)]
         ,[(0,200),(0.35,8900),(1,200)]
         ,[(0,0.35),(0.65,0.65),(1,0.35)]
         ,[(0,-1),(0.3,1),(1,-1)])

data_2 :: (D,D,D,D)
data_2 = ([(0,0.1),(0.5,0.005),(1,0.1)]
         ,[(0,100),(0.5,13900),(1,200)]
         ,[(0,0.75),(0.5,0.25),(1,0.75)]
         ,[(0,1),(0.5,-1),(1,1)])

data_3 :: (D,D,D,D)
data_3 = ([(0,0.01),(0.5,0.25),(1,0.01)]
         ,[(0,770),(0.5,77),(1,770)]
         ,[(0,0.9),(0.5,0.6),(1,0.9)]
         ,[(0,0),(0.5,1),(1,0)])

-- | Switch between data sets at /dd/ at time interval /t/.
data_switch :: [(D,D,D,D)] -> R -> IO ()
data_switch dd t =
    let w d = load_data 64 d >> pauseThread t
    in mapM_ w dd >> data_switch dd t

main :: IO ()
main = do
  alloc_data 64
  load_data 64 data_1
  play_data
  data_switch [data_1,data_2,data_3] 4