module Examples.Simple.Filters where import Prelude hiding (break) import Core import Interpretation import Examples.Simple.Expr import Frontend.Signal (Sig) import Frontend.Stream (Str, Stream(..)) import Backend.Compiler.Compiler import qualified Frontend.Signal as S import qualified Frontend.Stream as Str import qualified Backend.C as B import Control.Monad import Control.Monad.Operational (Program) import Text.PrettyPrint.Mainland import Data.IORef import Data.Array.IO.Safe import qualified System.IO as IO import qualified Text.Printf as Printf -------------------------------------------------------------------------------- -- * Misc Types -------------------------------------------------------------------------------- type E = Expr type S = Sig E type P = Program (CMD E) -------------------------------------------------------------------------------- -- | classical for loop for :: E Int -> E Int -> (E Int -> P ()) -> P () for lo hi body = do ir <- newRef lo while (do i <- unsafeGetRef ir; return (leq i hi)) (do i <- unsafeGetRef ir a <- body i setRef ir (i+1) return a ) -- unsafeGetRef is fine because writing to the reference is the last thing -- that happens in each iteration -------------------------------------------------------------------------------- -- * FIR Filter Example -------------------------------------------------------------------------------- fir :: [E Float] -> S Float -> S Float fir as = sums . muls as . delays ds where ds = replicate (length as) 0 sums :: [S Float] -> S Float sums = foldr1 (+) muls :: [E Float] -> [S Float] -> [S Float] muls as = zipWith (*) (map S.repeat as) delays :: [E Float] -> S Float -> [S Float] delays as s = scanl (flip S.delay) s as -------------------------------------------------------------------------------- -- * IIR Filter Examples -------------------------------------------------------------------------------- iir :: [E Float] -> [E Float] -> S Float -> S Float iir (a:as) bs s = o where u = fir bs s l = fir as $ S.delay 0 o o = (1 / S.repeat a) * (u - l) -------------------------------------------------------------------------------- -- * FFT Filter Examples -------------------------------------------------------------------------------- -- todo -------------------------------------------------------------------------------- -- * Testing of filters -------------------------------------------------------------------------------- -- for eval you will need to make sure there is an input file, called "input", -- to read from. Its a standard file of numbers seperated by a space. test_fir = comp (fir [1,2,3]) eval_fir = eval (fir [1,2,3]) test_iir = comp (iir [1,2] [3,4]) -- crashes! why?!.. eval_iir = eval (iir [1,2] [3,4]) -------------------------------------------------------------------------------- crash = test (fir [1,2,3,4]) -------------------------------------------------------------------------------- -- | eval :: (S Float -> S Float) -> IO () eval = connect_io >=> B.runProgram -- | ... comp :: (S Float -> S Float) -> IO Doc comp = connect_io >=> B.cgen . mkFunction "main" -- | test :: (S Float -> S Float) -> IO Doc test = inspect_io >=> B.cgen . mkFunction "test" -------------------------------------------------------------------------------- connect_io :: (S Float -> S Float) -> IO (P ()) connect_io s = do prg <- compiler s return $ do inp <- open "input" outp <- open "output" let (Stream init) = prg $ Str.stream $ return $ do i <- fget inp isEOF <- feof inp iff isEOF break (return ()) -- Apparently EOF can only be detected after one has tried to read past the end return i let setty = fput outp getty <- init while (return $ litExp True) (do v <- getty setty v) close inp close outp -------------------------------------------------------------------------------- inspect_io :: (S Float -> S Float) -> IO (P ()) inspect_io s = do prg <- inspect_compiler s return $ do inp <- open "input" outp <- open "output" let (Stream init) = prg $ Str.stream $ return $ do i <- fget inp isEOF <- feof inp iff isEOF break (return ()) -- Apparently EOF can only be detected after one has tried to read past the end return i let setty = fput outp getty <- init while (return $ litExp True) (do v <- getty setty v) close inp close outp