packages feed

vocoder-dunai-0.1.0.0: example/ProcessingTree.hs

{-# LANGUAGE ScopedTypeVariables #-}
module ProcessingTree where

import Control.Monad.Writer
import Control.Monad.Except
import FRP.Rhine
import Vocoder
import Vocoder.Filter

type STFTMSF m = MSF m [[STFTFrame]] [STFTFrame]

data ProcessingTree m = PTSource Int
                      | PTNamed String
                      | PTBind String (ProcessingTree m)
                      | PTMSF (MSF m [STFTFrame] [STFTFrame]) (ProcessingTree m)
                      | PTFilter (Filter m) (ProcessingTree m)
                      | PTBinary (STFTFrame -> STFTFrame -> STFTFrame) (ProcessingTree m) (ProcessingTree m)

elaboratePT :: forall m. Monad m
            => m FreqStep
            -> ProcessingTree m
            -> Maybe (STFTMSF m)
elaboratePT mfs t0 = either (const Nothing) Just r where
    (r, e0) = runWriter $ runExceptT $ g e0 t0
    g :: [(String, STFTMSF m)]
      -> ProcessingTree m
      -> ExceptT () (Writer [(String, STFTMSF m)]) (STFTMSF m)
    g _ (PTSource k) = return $ arr (!! k)
    g e (PTNamed n) | Just v <- lookup n e = return v
                    | otherwise = throwError ()
    g e (PTBind n t) = g e t >>= (\v -> tell [(n, v)] >> return v)
    g e (PTMSF f t) = (>>> f) <$> g e t
    g e (PTFilter f t) = (>>> arrM (\x -> mfs >>= forM x . f)) <$> g e t
    g e (PTBinary f t1 t2) = (\m1 m2 -> zipWith f <$> m1 <*> m2) <$> g e t1 <*> g e t2

numSourcesPT :: (ProcessingTree m) -> Int
numSourcesPT (PTSource k) = k+1
numSourcesPT (PTNamed _)  = 0
numSourcesPT (PTBind _ t) = numSourcesPT t
numSourcesPT (PTMSF _ t) = numSourcesPT t
numSourcesPT (PTFilter _ t) = numSourcesPT t
numSourcesPT (PTBinary _ t1 t2) = numSourcesPT t1 `max` numSourcesPT t2