]> Git — Sourcephile - tmp/julm/arpeggigon.git/blob - src/RMCA/Layer/Board.hs
Refactoring to FRP.
[tmp/julm/arpeggigon.git] / src / RMCA / Layer / Board.hs
1 {-# LANGUAGE Arrows #-}
2
3 module RMCA.Layer.Board where
4
5 import qualified Data.IntMap as M
6 import Data.List ((\\))
7 import FRP.Yampa
8 import RMCA.Auxiliary
9 import RMCA.Global.Clock
10 import RMCA.Layer.LayerConf
11 import RMCA.Semantics
12
13 data RunStatus = Running | Stopped
14
15 automaton :: [PlayHead]
16 -> SF (Board, DynLayerConf, Event BeatNo)
17 (Event [Note], [PlayHead])
18 automaton iphs = proc (b, DynLayerConf { relPitch = rp
19 , strength = s
20 }, ebno) -> do
21 enphs <- accumBy advanceHeads' (iphs,[])
22 -< ebno `tag` (b, fromEvent ebno, rp, s)
23 (ephs,en) <- arr splitE -< enphs
24 phs <- hold iphs -< ephs
25 returnA -< (en, phs)
26 where advanceHeads' (ph,_) (board,bno,rp,s) = advanceHeads board bno rp s ph
27
28
29 layer :: SF (Event AbsBeat, Board, LayerConf, Event RunStatus)
30 (Event [Note], [PlayHead])
31 layer = layerStopped
32 where switchStatus (rs, slc, iphs) = case rs of
33 Stopped -> layerStopped
34 Running -> layerRunning slc iphs
35
36 layerStopped = switch lsAux switchStatus
37
38 layerRunning slc iphs = switch (lrAux slc iphs) switchStatus
39
40 lsAux = proc (_, b, (slc,_,_), ers) -> do
41 en <- never -< ()
42 phs <- constant [] -< ()
43 e <- notYet -< fmap (\rs -> (rs, slc, startHeads b)) ers
44 returnA -< ((en,phs),e)
45
46 lrAux slc iphs = proc (eab, b, (slc',dlc,_), ers) -> do
47 ebno <- layerMetronome slc -< (eab, dlc)
48 enphs@(_,phs) <- automaton iphs -< (b, dlc, ebno)
49 r <- (case repeatCount slc of
50 Nothing -> never
51 Just n -> countTo (n * beatsPerBar slc)) -< ebno
52 let ers' = ers `lMerge` (r `tag` Running)
53 e <- notYet -< fmap (\rs -> (rs, slc', phs ++ startHeads b)) ers'
54 returnA -< (enphs,e)
55
56 layers :: M.IntMap a
57 -> SF (Tempo, Event RunStatus,
58 M.IntMap (Board,LayerConf,Event RunStatus))
59 (M.IntMap (Event [Note], [PlayHead]))
60 layers imap = proc (t,erun,map) -> do
61 elc <- edgeBy diffSig (M.keys imap) -< M.keys map
62 let e = fmap switchCol elc
63 newMetronome Running = metronome
64 newMetronome Stopped = never
65 eabs <- rSwitch metronome -< (t, newMetronome <$> erun)
66 rpSwitch routing (imap $> layer) -< ((eabs,erun,map),e)
67 where routing (eabs,erun,map) sfs = M.intersectionWith (,)
68 (fmap (\(b,l,er) -> (eabs,b,l,erun `lMerge` er)) map) sfs
69
70 diffSig :: [Int] -> [Int] -> Maybe ([Int],[Int])
71 diffSig oL nL
72 | oL == nL = Nothing
73 | otherwise = Just (oL \\ nL, nL \\ oL)
74
75 switchCol (oldSig,newSig) col =
76 foldr (\k m -> M.insert k layer m)
77 (foldr M.delete col oldSig) newSig