diff --git a/src/Synthesizer/ApplicativeUtility.hs b/src/Synthesizer/ApplicativeUtility.hs
--- a/src/Synthesizer/ApplicativeUtility.hs
+++ b/src/Synthesizer/ApplicativeUtility.hs
@@ -1,7 +1,7 @@
 -- this is also used by synthesizer-dimensional and synthesizer-inference
 module Synthesizer.ApplicativeUtility where
 
-import Control.Applicative (Applicative, pure, (<*>), (<$>), liftA2, )
+import Control.Applicative (Applicative, (<*>), (<$>), liftA2, )
 import Data.Traversable (Traversable, sequenceA, )
 
 import Control.Monad.Fix (fix, )
@@ -73,9 +73,9 @@
 -- (.^) f = (.:) (pure f)
 
 {-# INLINE ($#) #-}
-($#) :: (Applicative f) => f (a -> b) -> a -> f b
-($#) f x = f $: pure x
--- ($#) = flip
+($#) :: (Functor f) => f (a -> b) -> a -> f b
+($#) f x = fmap ($x) f
+-- ($#) f x = f $: pure x
 
 
 {- |
diff --git a/src/Synthesizer/Causal/ToneModulation.hs b/src/Synthesizer/Causal/ToneModulation.hs
--- a/src/Synthesizer/Causal/ToneModulation.hs
+++ b/src/Synthesizer/Causal/ToneModulation.hs
@@ -129,7 +129,7 @@
 {- ToDo:
 Both lengthAtMost and dropMarginRem seek through the list.
 Maybe an improved version of dropMargin could avoid this.
-E.g. dropMarginRem :: dropMarginRem :: Int -> Int -> sig y -> (Maybe Int, sig y),
+E.g. dropMarginRem :: Int -> Int -> sig y -> (Maybe Int, sig y),
 where return value (Just 0) means,
 that drop could actually drop the requested number of elements,
 but that we reached the end of the list.
diff --git a/src/Synthesizer/Filter/Basic.hs b/src/Synthesizer/Filter/Basic.hs
--- a/src/Synthesizer/Filter/Basic.hs
+++ b/src/Synthesizer/Filter/Basic.hs
@@ -12,7 +12,7 @@
 import NumericPrelude
 import PreludeBase
 
-{- todo:
+{- ToDo:
     - support of data before time 0
        - the problem is that all past data has to be kept,
          the garbage collector can't flush it :-(
diff --git a/src/Synthesizer/Filter/Composition.hs b/src/Synthesizer/Filter/Composition.hs
--- a/src/Synthesizer/Filter/Composition.hs
+++ b/src/Synthesizer/Filter/Composition.hs
@@ -19,7 +19,7 @@
 import PreludeBase
 import NumericPrelude
 
-{- todo:
+{- ToDo:
     - functions that build a FilterComposition for specific filters
         (1st order, universal, allpass, butterworth, chebyshev)
     - functions that turn physical filter parameters into
diff --git a/src/Synthesizer/Frame/Stereo.hs b/src/Synthesizer/Frame/Stereo.hs
--- a/src/Synthesizer/Frame/Stereo.hs
+++ b/src/Synthesizer/Frame/Stereo.hs
@@ -8,14 +8,23 @@
 import qualified Sound.Sox.Frame as Frame
 
 import qualified Synthesizer.Interpolation.Class as Interpol
-import qualified Algebra.Module   as Module
-import qualified Algebra.Additive as Additive
 
+import qualified Algebra.NormedSpace.Maximum   as NormedMax
+import qualified Algebra.NormedSpace.Euclidean as NormedEuc
+import qualified Algebra.NormedSpace.Sum       as NormedSum
+
+import qualified Algebra.Module    as Module
+import qualified Algebra.Algebraic as Algebraic
+import qualified Algebra.Additive  as Additive
+
 import Foreign.Storable (Storable (..), )
 import qualified Foreign.Storable.Record as Store
 
 import Control.Applicative (liftA2, )
+import Control.Monad (liftM2, )
 
+import Test.QuickCheck (Arbitrary(..), )
+
 import NumericPrelude
 import PreludeBase hiding (map)
 import Prelude ()
@@ -24,8 +33,20 @@
 
 -- cf. Sound.Sox.Frame.Stereo
 data T a = Cons {left, right :: !a}
+   deriving (Eq)
 
 
+instance Show a => Show (T a) where
+   showsPrec p x =
+      showParen (p >= 10)
+         (showString "Stereo.cons " . showsPrec 11 (left x) .
+          showString " " . showsPrec 11 (right x))
+
+instance (Arbitrary a) => Arbitrary (T a) where
+   arbitrary = liftM2 cons arbitrary arbitrary
+   coarbitrary = error "Stereo.coarbitrary not implemented"
+
+
 {-# INLINE cons #-}
 cons :: a -> a -> T a
 cons = Cons
@@ -62,14 +83,30 @@
    (-)    (Cons xl xr) (Cons yl yr) = Cons (xl-yl) (xr-yr)
    negate (Cons xl xr)              = Cons (negate xl) (negate xr)
 
-instance (Module.C a b) => Module.C a (T b) where
+instance (Module.C a v) => Module.C a (T v) where
    {-# INLINE (*>) #-}
    s *> (Cons l r)   = Cons (s *> l) (s *> r)
 
-instance Interpol.C a b => Interpol.C a (T b) where
+instance Interpol.C a v => Interpol.C a (T v) where
    {-# INLINE scaleAndAccumulate #-}
    scaleAndAccumulate =
       Interpol.makeMac2 Cons left right
+
+
+instance (Additive.C a, NormedSum.C a v) => NormedSum.C a (T v) where
+   norm (Cons l r) =
+      NormedSum.norm l + NormedSum.norm r
+
+instance (NormedEuc.Sqr a v) => NormedEuc.Sqr a (T v) where
+   normSqr (Cons l r) =
+      NormedEuc.normSqr l + NormedEuc.normSqr r
+
+instance (Algebraic.C a, NormedEuc.Sqr a v) => NormedEuc.C a (T v) where
+   norm = NormedEuc.defltNorm
+
+instance (Ord a, NormedMax.C a v) => NormedMax.C a (T v) where
+   norm (Cons l r) =
+      max (NormedMax.norm l) (NormedMax.norm r)
 
 
 instance Frame.C a => Frame.C (T a) where
diff --git a/src/Synthesizer/FusionList/Control.hs b/src/Synthesizer/FusionList/Control.hs
--- a/src/Synthesizer/FusionList/Control.hs
+++ b/src/Synthesizer/FusionList/Control.hs
@@ -16,6 +16,7 @@
 
 -- import Synthesizer.FusionList.Displacement (raise)
 import qualified Synthesizer.FusionList.Signal as Sig
+import Synthesizer.State.Control (splitDurations, )
 
 import qualified Algebra.Module                as Module
 import qualified Algebra.Transcendental        as Trans
@@ -175,15 +176,7 @@
 -- * piecewise curves
 
 
-splitDurations :: (RealField.C t) =>
-   [t] -> [(Int, t)]
-splitDurations ts0 =
-   let (ds,ts) =
-           unzip $ scanl
-              (\(_,fr) d -> splitFraction (fr+d))
-              (0,1) ts0
-   in  zip (tail ds) (map (subtract 1) ts)
-
+{-# DEPRECATED Piece, piecewise "use Synthesizer.Generic.Piece instead" #-}
 {-# INLINE piecewise #-}
 piecewise :: (RealField.C a) =>
    Piecewise.T a a (a -> Sig.T a) -> Sig.T a
diff --git a/src/Synthesizer/Generic/Control.hs b/src/Synthesizer/Generic/Control.hs
--- a/src/Synthesizer/Generic/Control.hs
+++ b/src/Synthesizer/Generic/Control.hs
@@ -217,6 +217,7 @@
 
 
 
+{-# DEPRECATED Control "use Synthesizer.Generic.Piece instead" #-}
 {- |
 The curve type of a piece of a piecewise defined control curve.
 -}
diff --git a/src/Synthesizer/Generic/Filter/NonRecursive.hs b/src/Synthesizer/Generic/Filter/NonRecursive.hs
--- a/src/Synthesizer/Generic/Filter/NonRecursive.hs
+++ b/src/Synthesizer/Generic/Filter/NonRecursive.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts #-}
 {- |
-Copyright   :  (c) Henning Thielemann 2008
+Copyright   :  (c) Henning Thielemann 2008-2009
 License     :  GPL
 
 Maintainer  :  synthesizer@henning-thielemann.de
@@ -10,8 +11,11 @@
 module Synthesizer.Generic.Filter.NonRecursive where
 
 import qualified Synthesizer.Generic.Signal as SigG
+import qualified Synthesizer.Generic.Signal2 as SigG2
 
 import qualified Synthesizer.Generic.Control as Ctrl
+import qualified Synthesizer.State.Signal as SigS
+import qualified Synthesizer.Plain.Filter.NonRecursive as Filt
 
 import qualified Algebra.Transcendental as Trans
 import qualified Algebra.Module         as Module
@@ -23,10 +27,10 @@
 import Algebra.Module( {- linearComb, -} (*>), )
 
 import Data.Function.HT (nest, )
+import Data.Tuple.HT (mapSnd, mapPair, )
 
 import PreludeBase
-import NumericPrelude
-
+import NumericPrelude as NP
 
 
 {- * Envelope application -}
@@ -240,16 +244,25 @@
 sums n = SigG.mapTails (SigG.sum . SigG.take n)
 
 
-{-
-sumsDownsample2 :: (Additive.C v) => sig v -> sig v
-sumsDownsample2 (x0:x1:xs) = (x0+x1) : sumsDownsample2 xs
-sumsDownsample2 xs         = xs
+sumsDownsample2 ::
+   (Additive.C v, SigG.Write sig v) =>
+   SigG.LazySize -> sig v -> sig v
+sumsDownsample2 cs =
+   SigG.unfoldR cs (\xs ->
+      flip fmap (SigG.viewL xs) $ \xxs0@(x0,xs0) ->
+         SigG.switchL xxs0 {- xs0 is empty -}
+            (\ x1 xs1 -> (x0+x1, xs1))
+            xs0)
 
-downsample2 :: sig a -> sig a
-downsample2 (x0:_:xs) = x0 : downsample2 xs
-downsample2 xs        = xs
+downsample2 ::
+   (SigG.Write sig v) =>
+   SigG.LazySize -> sig v -> sig v
+downsample2 cs =
+   SigG.unfoldR cs
+      (fmap (mapSnd SigG.laxTail) . SigG.viewL)
 
 
+{-
 {- |
 Given a list of numbers
 and a list of sums of (2*k) of successive summands,
@@ -305,6 +318,96 @@
          zipWith3 (\x y z -> x==y && y==z) naive rec pyramid
 
 -}
+
+sumRange ::
+   (Additive.C v, SigG.Transform sig v) =>
+   sig v -> (Int,Int) -> v
+sumRange =
+   Filt.sumRangePrepare $ \ (l,r) ->
+   SigG.sum . SigG.take (r-l) . SigG.drop l
+
+pyramid ::
+   (Additive.C v, SigG.Write sig v) =>
+   Int -> sig v -> ([Int], [sig v])
+pyramid height sig =
+   let sizes =
+          reverse $ take (1+height) $ iterate (2*) 1
+   in  (sizes,
+        scanl (flip sumsDownsample2) sig (map SigG.LazySize $ tail sizes))
+
+sumRangeFromPyramid ::
+   (Additive.C v, SigG.Write sig v) =>
+   [sig v] -> (Int,Int) -> v
+sumRangeFromPyramid =
+   Filt.sumRangePrepare $ \(l0,r0) pyr0 ->
+   case pyr0 of
+      [] -> error "empty pyramid"
+      (ps0:pss) ->
+         foldr
+            (\psNext k (l,r) ps s ->
+               case r-l of
+                  0 -> s
+                  1 -> s + SigG.index ps l
+                  _ ->
+                     let (lh,ll) = NP.negate $ divMod (NP.negate l) 2
+                         (rh,rl) = divMod r 2
+                         {-# INLINE inc #-}
+                         inc b x = if b==0 then id else (x+)
+                     in  k (lh,rh) psNext $
+                         inc ll (SigG.index ps l) $
+                         inc rl (SigG.index ps (r-1)) $
+                         s)
+            (\(l,r) ps s ->
+               s + (SigG.sum $ SigG.take (r-l) $ SigG.drop l ps))
+            pss (l0,r0) ps0 zero
+
+sumsPosModulated ::
+   (Additive.C v, SigG2.Transform sig (Int,Int) v) =>
+   sig (Int,Int) -> sig v -> sig v
+sumsPosModulated ctrl xs =
+   SigG2.zipWithTails (flip sumRange) ctrl xs
+
+
+{- |
+Moving average, where window bounds must be always non-negative.
+
+The laziness granularity is @2^height@.
+-}
+sumsPosModulatedPyramid ::
+   (Additive.C v, SigG.Transform sig (Int,Int), SigG.Write sig v) =>
+   Int -> sig (Int,Int) -> sig v -> sig v
+sumsPosModulatedPyramid height ctrl xs =
+   let (sizes,pyr0) = pyramid height xs
+       blockSize = head sizes
+       pyrStarts =
+          iterate (zipWith SigG.drop sizes) pyr0
+       ctrlBlocks =
+          SigS.toList $
+          SigG.sliceVertical blockSize ctrl
+   in  SigG.concat $
+       zipWith
+          (\pyr ->
+              SigG.fromState (SigG.LazySize blockSize) .
+              SigS.map (sumRangeFromPyramid pyr) .
+              SigS.zipWith (\d -> mapPair ((d+), (d+))) (SigS.iterate (1+) 0) .
+              SigG.toState)
+          pyrStarts ctrlBlocks
+
+{- |
+The first argument is the amplification.
+The main reason to introduce it,
+was to have only a Module constraint instead of Field.
+This way we can also filter stereo signals.
+-}
+movingAverageModulatedPyramid ::
+   (Field.C a, Module.C a v,
+    SigG2.Transform sig Int (Int,Int), SigG.Write sig v) =>
+   a -> Int -> Int -> sig Int -> sig v -> sig v
+movingAverageModulatedPyramid amp height maxC ctrl xs =
+   SigG.zipWith (\c x -> (amp / fromIntegral (2*c+1)) *> x) ctrl $
+   sumsPosModulatedPyramid height
+      (SigG2.map (\c -> (maxC - c, maxC + c)) ctrl)
+      (delay maxC xs)
 
 
 
diff --git a/src/Synthesizer/Generic/Piece.hs b/src/Synthesizer/Generic/Piece.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/Generic/Piece.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{- |
+These are pieces that can be assembled to a control curve.
+This was formerly part of the @Control@ module
+but because of the overlap with immediate control curve generators
+I created a new module.
+-}
+module Synthesizer.Generic.Piece (
+   T, run,
+   step, linear, exponential,
+   cosine, halfSine, cubic,
+   FlatPosition(..),
+   ) where
+
+import qualified Synthesizer.Generic.Control as Ctrl
+import qualified Synthesizer.Piecewise as Piecewise
+import Synthesizer.Generic.Displacement (raise, )
+
+import qualified Synthesizer.Generic.Cut as CutG
+import qualified Synthesizer.Generic.Signal as SigG
+-- import qualified Synthesizer.State.Signal as Sig
+import Synthesizer.State.Control (splitDurations, FlatPosition(..), )
+
+import qualified Algebra.Transcendental        as Trans
+import qualified Algebra.RealField             as RealField
+import qualified Algebra.Field                 as Field
+import qualified Algebra.Ring                  as Ring
+import qualified Algebra.Additive              as Additive
+
+import qualified Prelude as P
+import PreludeBase
+import NumericPrelude
+
+
+
+{-# INLINE run #-}
+run :: (RealField.C a, CutG.Transform (sig a)) =>
+   SigG.LazySize ->
+   Piecewise.T a a (SigG.LazySize -> a -> sig a) ->
+   sig a
+run lazySize xs =
+   SigG.concat $ zipWith
+      (\(n, t) (Piecewise.PieceData c yi0 yi1 d) ->
+           SigG.take n $ Piecewise.computePiece c yi0 yi1 d lazySize t)
+      (splitDurations $ map Piecewise.pieceDur xs)
+      xs
+
+
+type T sig a =
+   Piecewise.Piece a a
+      (SigG.LazySize -> a {- fractional start time -} -> sig a)
+
+
+{-# INLINE step #-}
+step :: (SigG.Write sig a) => T sig a
+step =
+   Piecewise.pieceFromFunction $ \ y0 _y1 _d lazySize _t0 ->
+      Ctrl.constant lazySize y0
+
+{-# INLINE linear #-}
+linear :: (Field.C a, SigG.Write sig a) => T sig a
+linear =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      let s = (y1-y0)/d
+      in  Ctrl.linear lazySize s (y0-t0*s)
+
+{-# INLINE exponential #-}
+exponential :: (Trans.C a, SigG.Write sig a) => a -> T sig a
+exponential saturation =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      let y0' = y0-saturation
+          y1' = y1-saturation
+          yd  = y0'/y1'
+      in  raise saturation
+             (Ctrl.exponential lazySize (d / log yd) (y0' * yd**(t0/d)))
+
+{-# INLINE cosine #-}
+cosine :: (Trans.C a, SigG.Write sig a) => T sig a
+cosine =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      SigG.map
+         (\y -> ((1+y)*y0+(1-y)*y1)/2)
+         (Ctrl.cosine lazySize t0 (t0+d))
+
+
+{- |
+> Graphics.Gnuplot.Simple.plotList [] $ Sig.toList $ run $ 1 |# (10.9, halfSine FlatRight) #| 2
+-}
+{-# INLINE halfSine #-}
+halfSine :: (Trans.C a, SigG.Write sig a) => FlatPosition -> T sig a
+halfSine FlatLeft =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      SigG.map
+         (\y -> y*y0 + (1-y)*y1)
+         (Ctrl.cosine lazySize t0 (t0+2*d))
+halfSine FlatRight =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      SigG.map
+         (\y -> (1+y)*y0 - y*y1)
+         (Ctrl.cosine lazySize (t0-d) (t0+d))
+
+
+{-# INLINE cubic #-}
+cubic :: (Field.C a, SigG.Write sig a) => a -> a -> T sig a
+cubic yd0 yd1 =
+   Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
+      Ctrl.cubicHermite lazySize (t0,(y0,yd0)) (t0+d,(y1,yd1))
diff --git a/src/Synthesizer/Generic/Signal.hs b/src/Synthesizer/Generic/Signal.hs
--- a/src/Synthesizer/Generic/Signal.hs
+++ b/src/Synthesizer/Generic/Signal.hs
@@ -51,9 +51,9 @@
 import Data.Tuple.HT (mapPair, mapFst, )
 
 import Prelude
-   (Bool, Int, Maybe(Just), maybe, snd,
-    flip, uncurry, (.), ($), id,
-    fmap, return, )
+   (Bool, Int, Maybe(Just), maybe, snd, (<),
+    flip, uncurry, const, (.), ($), id, (++),
+    fmap, return, error, show, )
 
 
 class Cut.Read (sig y) => Read sig y where
@@ -395,6 +395,14 @@
 tails =
    SigS.unfoldR (fmap (\x -> (x, fmap snd (viewL x)))) . Just
 
+{- |
+Like 'tail', but for an empty signal it simply returns an empty signal.
+-}
+{-# INLINE laxTail #-}
+laxTail :: (Transform sig y) => sig y -> sig y
+laxTail xs =
+   switchL xs (flip const) xs
+
 {-# INLINE mapAdjacent #-}
 mapAdjacent :: (Read sig a, Transform sig a) =>
    (a -> a -> a) -> sig a -> sig a
@@ -496,6 +504,20 @@
    (+) = mix
    negate = map Additive.negate
 -}
+
+
+
+{-
+ToDo: make a method of Read class
+-}
+index :: (Transform sig a) => sig a -> Int -> a
+index xs n =
+   if n<0
+     then error $ "Generic.index: negative index " ++ show n
+     else switchL
+             (error $ "Generic.index: index too large " ++ show n)
+             const
+             (Cut.drop n xs)
 
 
 {-
diff --git a/src/Synthesizer/Generic/Tutorial.hs b/src/Synthesizer/Generic/Tutorial.hs
--- a/src/Synthesizer/Generic/Tutorial.hs
+++ b/src/Synthesizer/Generic/Tutorial.hs
@@ -13,6 +13,7 @@
 import qualified Synthesizer.Plain.Tutorial as Tutorial -- needed for Haddock
 
 import qualified Sound.Sox.Play as Play
+import qualified Sound.Sox.Write as Write
 import qualified Sound.Sox.Option.Format as SoxOpt
 import qualified Synthesizer.Basic.Binary as BinSmp
 import qualified Synthesizer.Storable.Signal as SigSt
@@ -23,10 +24,12 @@
 import Control.Arrow ((&&&), (^<<), (<<^), (<<<), )
 
 import qualified Synthesizer.Generic.Oscillator as Osci
+import qualified Synthesizer.Generic.Piece as Piece
 import qualified Synthesizer.Generic.Filter.NonRecursive as Filt
 import qualified Synthesizer.Plain.Filter.Recursive as FiltRec
 import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
 import qualified Synthesizer.Basic.Wave as Wave
+import Synthesizer.Piecewise ((#|-), (-|#), (#|), (|#), )
 
 import qualified Synthesizer.State.Control as CtrlS
 import qualified Synthesizer.State.Oscillator as OsciS
@@ -62,6 +65,37 @@
 oscillator :: IO ExitCode
 oscillator =
    play (Osci.static SigG.defaultLazySize Wave.sine zero (0.01::Double))
+
+
+{- |
+A routine just for the case that we want to post-process a signal somewhere else.
+-}
+write :: FilePath -> SigSt.T Double -> IO ExitCode
+write name =
+   Write.simple SigSt.hPut SoxOpt.none name 44100 .
+   SigSt.map BinSmp.int16FromDouble
+
+{- |
+The simple brass sound demonstrates
+how to generate piecewise defined curves.
+Some infix operators are used in order to make the pieces fit in height.
+There are also operators for intended jumps.
+-}
+brass :: IO ExitCode
+brass =
+--   write "brass.aiff" $
+   play $
+   Filt.envelope
+      (Piece.run SigG.defaultLazySize $
+       0    |# ( 3000, Piece.cubic 0.002 0) #|-
+       0.7 -|# (50000, Piece.step) #|-
+       0.7 -|# (10000, Piece.exponential 0) #| (0.01::Double)) $
+   SigG.fromState SigG.defaultLazySize $
+   Filt.amplify 0.5 $
+   SigG.mix
+      (OsciS.static Wave.saw zero (0.00499::Double))
+      (OsciS.static Wave.saw zero (0.00501::Double))
+
 
 {- |
 We rewrite the filter example 'Tutorial.filterSaw'
diff --git a/src/Synthesizer/Piecewise.hs b/src/Synthesizer/Piecewise.hs
--- a/src/Synthesizer/Piecewise.hs
+++ b/src/Synthesizer/Piecewise.hs
@@ -3,7 +3,11 @@
 -}
 module Synthesizer.Piecewise where
 
-
+{-
+ToDo:
+Make it a new data type with Monoid and Generic.Cut instances.
+However there is no fast and generic way for splitting a piece.
+-}
 type T t y sig = [PieceData t y sig]
 
 {- |
diff --git a/src/Synthesizer/Plain/Control.hs b/src/Synthesizer/Plain/Control.hs
--- a/src/Synthesizer/Plain/Control.hs
+++ b/src/Synthesizer/Plain/Control.hs
@@ -326,6 +326,7 @@
 
 
 
+{-# DEPRECATED Control "use Synthesizer.State.Piece instead" #-}
 {- |
 The curve type of a piece of a piecewise defined control curve.
 -}
diff --git a/src/Synthesizer/Plain/Filter/NonRecursive.hs b/src/Synthesizer/Plain/Filter/NonRecursive.hs
--- a/src/Synthesizer/Plain/Filter/NonRecursive.hs
+++ b/src/Synthesizer/Plain/Filter/NonRecursive.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {- |
-Copyright   :  (c) Henning Thielemann 2006
+Copyright   :  (c) Henning Thielemann 2006-2009
 License     :  GPL
 
 Maintainer  :  synthesizer@henning-thielemann.de
@@ -22,6 +22,8 @@
 import Algebra.Module(linearComb, (*>))
 
 import Data.Function.HT (nest, )
+import Data.Tuple.HT (mapPair, )
+import Data.List.HT (sliceVertical, )
 import Data.List (tails, )
 
 -- import Control.Monad.Trans.State (StateT)
@@ -204,7 +206,7 @@
 and a list of sums of (2*k) of successive summands,
 compute a list of the sums of (2*k+1) or (2*k+2) summands.
 
-Eample for 2*k+1
+Example for 2*k+1
 
 @
  [0+1+2+3, 2+3+4+5, 4+5+6+7, ...] ->
@@ -243,10 +245,123 @@
    in  aux
 
 
-{-
-*Synthesizer.Plain.Filter.NonRecursive> movingAverageModulated 10 (replicate 10 (3::Double) ++ [1.1,2.2,2.6,0.7,0.1,0.1]) (repeat (1::Double))
-[0.5,0.6666666666666666,0.8333333333333333,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.9999999999999999,1.0,0.9999999999999998,0.999999999999999,0.9999999999999942,0.9999999999999942]
+{- |
+Compute the sum of the values from index l to (r-1).
+(I.e. somehow a right open interval.)
+This can be used for implementation of a moving average filter.
+However, its counterpart 'sumRangeFromPyramid'
+is much faster for large windows.
 -}
+sumRange :: (Additive.C v) => Sig.T v -> (Int,Int) -> v
+sumRange =
+   sumRangePrepare $ \ (l,r) ->
+   sum . take (r-l) . drop l
+
+pyramid :: (Additive.C v) => Sig.T v -> [Sig.T v]
+pyramid = iterate sumsDownsample2
+
+sumRangePrepare :: (Additive.C v) =>
+   ((Int,Int) -> source -> v) ->
+   (source -> (Int,Int) -> v)
+sumRangePrepare f pyr (l,r) =
+   case compare l r of
+      LT -> f (l,r) pyr
+      GT -> negate $ f (r,l) pyr
+      EQ -> zero
+
+{- |
+This function should be much faster than 'sumRange'
+but slower than the recursively implemented @movingAverage@.
+However in contrast to @movingAverage@
+it should not suffer from cancelation.
+-}
+sumRangeFromPyramid :: (Additive.C v) => [Sig.T v] -> (Int,Int) -> v
+sumRangeFromPyramid =
+   sumRangePrepare $ \(l0,r0) pyr0 ->
+   sum $
+   case pyr0 of
+      [] -> error "empty pyramid"
+      (ps0:pss) ->
+         foldr
+            (\psNext k ((l,r), ps) ->
+               let (lh,ll) = - divMod (-l) 2
+                   (rh,rl) =   divMod   r  2
+                   ls = if ll==0 then [] else [ps!!l]
+                   rs = if rl==0 then [] else [ps!!(r-1)]
+               in  case r-l of
+                     0 -> []
+                     1 -> [ps!!l]
+                     _ -> ls ++ rs ++ k ((lh,rh), psNext))
+            (\((l,r), ps) -> take (r-l) $ drop l ps)
+            pss ((l0,r0), ps0)
+
+{- mapAccumL cannot work since the pyramid might be infinitely high
+   sum $ takeWhileJust $ snd $
+   mapAccumL () (l0,r0) $
+   zip pyr0 $
+   tail (Match.replicate pyr0 False ++ [True])
+-}
+
+sumRangeFromPyramidRec :: (Additive.C v) => [Sig.T v] -> (Int,Int) -> v
+sumRangeFromPyramidRec =
+   let recourse s (l,r) pyr =
+          case pyr of
+             (ps:[]) ->
+                s + (sum $ take (r-l) $ drop l ps)
+             (ps:pss) ->
+                let (lh,ll) = - divMod (-l) 2
+                    (rh,rl) =   divMod   r  2
+                    ls = if ll==0 then zero else ps!!l
+                    rs = if rl==0 then zero else ps!!(r-1)
+                in  case r-l of
+                      0 -> s
+                      1 -> s+ps!!l
+                      _ -> recourse (s + ls + rs) (lh,rh) pss
+             [] -> error "empty pyramid"
+   in  sumRangePrepare (recourse zero)
+
+sumsPosModulated :: (Additive.C v) =>
+   Sig.T (Int,Int) -> Sig.T v -> Sig.T v
+sumsPosModulated ctrl xs =
+   zipWith sumRange (tails xs) ctrl
+
+{- |
+Moving average, where window bounds must be always non-negative.
+
+The laziness granularity is @2^height@.
+-}
+sumsPosModulatedPyramid :: (Additive.C v) =>
+   Int -> Sig.T (Int,Int) -> Sig.T v -> Sig.T v
+sumsPosModulatedPyramid height ctrl xs =
+   let blockSize = 2 ^ fromIntegral height
+       sizes =
+          reverse $ take (1+height) $ iterate (2*) 1
+       pyrStarts =
+          iterate (zipWith drop sizes) $
+          take (1+height) $ pyramid xs
+       ctrlBlocks =
+          map (zipWith (\d -> mapPair ((d+), (d+))) $ iterate (1+) 0) $
+          sliceVertical blockSize ctrl
+   in  concat $
+       zipWith
+          (\pyr -> map (sumRangeFromPyramid pyr))
+          pyrStarts ctrlBlocks
+
+{- |
+The first argument is the amplification.
+The main reason to introduce it,
+was to have only a Module constraint instead of Field.
+This way we can also filter stereo signals.
+-}
+movingAverageModulatedPyramid ::
+   (Field.C a, Module.C a v) =>
+   a -> Int -> Int -> Sig.T Int -> Sig.T v -> Sig.T v
+movingAverageModulatedPyramid amp height maxC ctrl xs =
+   zipWith (\c x -> (amp / fromIntegral (2*c+1)) *> x) ctrl $
+   sumsPosModulatedPyramid height
+      (map (\c -> (maxC - c, maxC + c)) ctrl)
+      (delay maxC xs)
+
 
 
 {- * Filter operators from calculus -}
diff --git a/src/Synthesizer/Plain/Filter/Recursive/MovingAverage.hs b/src/Synthesizer/Plain/Filter/Recursive/MovingAverage.hs
--- a/src/Synthesizer/Plain/Filter/Recursive/MovingAverage.hs
+++ b/src/Synthesizer/Plain/Filter/Recursive/MovingAverage.hs
@@ -133,6 +133,11 @@
        negXs = sumDiffsModulated d0 (map (d0-) ds) delXs
    in  Integration.run (posXs - negXs)
 
+{-
+*Synthesizer.Plain.Filter.NonRecursive> movingAverageModulated 10 (replicate 10 (3::Double) ++ [1.1,2.2,2.6,0.7,0.1,0.1]) (repeat (1::Double))
+[0.5,0.6666666666666666,0.8333333333333333,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.9999999999999999,1.0,0.9999999999999998,0.999999999999999,0.9999999999999942,0.9999999999999942]
+-}
+
 modulatedFrac :: (RealField.C a, Module.C a v) =>
    Int -> Sig.T a -> Sig.T v -> Sig.T v
 modulatedFrac maxDInt ds xs =
diff --git a/src/Synthesizer/State/Control.hs b/src/Synthesizer/State/Control.hs
--- a/src/Synthesizer/State/Control.hs
+++ b/src/Synthesizer/State/Control.hs
@@ -29,6 +29,8 @@
 -- import Number.Complex (cis,real)
 -- import qualified Number.Complex as Complex
 
+import Data.Ix (Ix, )
+
 import qualified Prelude as P
 import PreludeBase
 import NumericPrelude
@@ -243,8 +245,30 @@
 cosinePiece =
    Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
       Sig.map
-         (\y -> (1+y)*(y0/2)+(1-y)*(y1/2))
+         (\y -> ((1+y)*y0+(1-y)*y1)/2)
          (cosine t0 (t0+d))
+
+
+data FlatPosition =
+   FlatLeft | FlatRight
+      deriving (Show, Eq, Ord, Ix, Enum)
+
+{- |
+> Graphics.Gnuplot.Simple.plotList [] $ Sig.toList $ piecewise $ 1 |# (10.9, halfSinePiece FlatRight) #| 2
+-}
+{-# INLINE halfSinePiece #-}
+halfSinePiece :: (Trans.C a) => FlatPosition -> Piece a
+halfSinePiece FlatLeft =
+   Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
+      Sig.map
+         (\y -> y*y0 + (1-y)*y1)
+         (cosine t0 (t0+2*d))
+halfSinePiece FlatRight =
+   Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
+      Sig.map
+         (\y -> (1+y)*y0 - y*y1)
+         (cosine (t0-d) (t0+d))
+
 
 {-# INLINE cubicPiece #-}
 cubicPiece :: (Field.C a) => a -> a -> Piece a
diff --git a/src/Synthesizer/State/Signal.hs b/src/Synthesizer/State/Signal.hs
--- a/src/Synthesizer/State/Signal.hs
+++ b/src/Synthesizer/State/Signal.hs
@@ -32,6 +32,7 @@
 
 import qualified Synthesizer.Storable.Signal as SigSt
 import qualified Data.StorableVector.Lazy.Pattern as SVL
+import qualified Data.StorableVector as V
 import Foreign.Storable (Storable)
 
 import qualified Data.List.HT as ListHT
@@ -106,6 +107,13 @@
 toStorableSignal size (Cons f a) =
    SigSt.unfoldr size (runStateT f) a
 
+{-# INLINE toStrictStorableSignal #-}
+toStrictStorableSignal ::
+   (Storable a) =>
+   Int -> T a -> V.Vector a
+toStrictStorableSignal size (Cons f a) =
+   fst $ V.unfoldrN size (runStateT f) a
+
 -- needed in synthesizer-alsa
 {-# INLINE toStorableSignalVary #-}
 toStorableSignalVary ::
@@ -582,15 +590,20 @@
 --   map fromList . Sig.sliceVert n . toList
    List.map (take n) . List.takeWhile (not . null) . List.iterate (drop n)
 
+{-# DEPRECATED zapWith, zapWithAlt "use mapAdjacent" #-}
 {-# INLINE zapWith #-}
 zapWith :: (a -> a -> b) -> T a -> T b
-zapWith f =
-   switchL empty
-      (crochetL (\y x -> Just (f x y, y)))
+zapWith = mapAdjacent
 
 zapWithAlt :: (a -> a -> b) -> T a -> T b
 zapWithAlt f xs =
    zipWith f xs (switchL empty (curry snd) xs)
+
+{-# INLINE mapAdjacent #-}
+mapAdjacent :: (a -> a -> b) -> T a -> T b
+mapAdjacent f =
+   switchL empty
+      (crochetL (\y x -> Just (f x y, y)))
 
 {-# INLINE modifyStatic #-}
 modifyStatic :: Modifier.Simple s ctrl a b -> ctrl -> T a -> T b
diff --git a/src/Synthesizer/Storable/Cut.hs b/src/Synthesizer/Storable/Cut.hs
--- a/src/Synthesizer/Storable/Cut.hs
+++ b/src/Synthesizer/Storable/Cut.hs
@@ -24,9 +24,6 @@
 import NumericPrelude
 
 
-{- |
-ChunkSize is only required for zero padding.
--}
 {-# INLINE arrange #-}
 arrange :: (Storable v, Additive.C v) =>
        Sig.ChunkSize
@@ -36,7 +33,23 @@
                 of the previous event. -}
     -> Sig.T v
             {-^ The mixed signal. -}
-arrange size =
+arrange =
+   arrangeEquidist
+
+{- |
+Chunk sizes are adapted to the time differences.
+Explicit ChunkSize parameter is only required for zero padding.
+Since no ST monad is needed, this can be generalized to Generic.Signal.Transform class.
+-}
+arrangeAdaptive :: (Storable v, Additive.C v) =>
+       Sig.ChunkSize
+    -> EventList.T NonNeg.Int (Sig.T v)
+            {-^ A list of pairs: (relative start time, signal part),
+                The start time is relative to the start time
+                of the previous event. -}
+    -> Sig.T v
+            {-^ The mixed signal. -}
+arrangeAdaptive size =
    uncurry Sig.append .
    flip runState Sig.empty .
    fmap (Sig.concat . EventList.getTimes) .
@@ -87,6 +100,11 @@
 
 {- |
 The result is a Lazy StorableVector with chunks of the given size.
+The output is always infinite.
+If the input is a finite list of finite length sounds,
+then the output is padded with zeros.
+Even if we try to terminate the output after the last sound,
+we would not finish immediately but only at chunk boundaries.
 -}
 {-# INLINE arrangeEquidist #-}
 arrangeEquidist :: (Storable v, Additive.C v) =>
@@ -104,7 +122,7 @@
               xs =
                  AbsEventList.toPairList $
                  EventList.toAbsoluteEventList 0 $
-                 EventListTM.switchTimeR (const) now
+                 EventListTM.switchTimeR const now
               (chunk,newAcc) =
                  runST
                     (do v <- SVST.new sz zero
@@ -122,7 +140,24 @@
 
 addToBuffer :: (Storable a, Additive.C a) =>
    SVST.Vector s a -> Int -> Sig.T a -> ST s (Sig.T a)
-addToBuffer v start =
+addToBuffer v start xs =
+   let n = SVST.length v
+       (now,future) = Sig.splitAt (n Additive.- start) xs
+   in  Sig.foldr
+          (\x continue i ->
+             SVST.modify v i (x Additive.+) >>
+             continue (succ i))
+          (const $ return ()) now start
+        >> return future
+
+
+{-
+Using @Sig.switchL@ in an inner loop
+is slower than using @Sig.foldr@.
+-}
+addToBufferSwitchL :: (Storable a, Additive.C a) =>
+   SVST.Vector s a -> Int -> Sig.T a -> ST s (Sig.T a)
+addToBufferSwitchL v start =
    let n = SVST.length v
        {-# INLINE go #-}
        go i =
diff --git a/src/Synthesizer/Storable/Filter/NonRecursive.hs b/src/Synthesizer/Storable/Filter/NonRecursive.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/Storable/Filter/NonRecursive.hs
@@ -0,0 +1,202 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts #-}
+{- |
+Copyright   :  (c) Henning Thielemann 2008-2009
+License     :  GPL
+
+Maintainer  :  synthesizer@henning-thielemann.de
+Stability   :  provisional
+Portability :  requires multi-parameter type classes
+-}
+module Synthesizer.Storable.Filter.NonRecursive where
+
+import qualified Synthesizer.Storable.Signal as SigSt
+import qualified Data.StorableVector as V
+import qualified Data.StorableVector.Lazy as VL
+import qualified Data.StorableVector.Lazy.Pattern as VP
+
+import qualified Synthesizer.Generic.Signal as SigG
+import qualified Synthesizer.State.Signal as SigS
+import qualified Synthesizer.Plain.Filter.NonRecursive as Filt
+import qualified Synthesizer.Generic.Filter.NonRecursive as FiltG
+
+import qualified Algebra.Module         as Module
+import qualified Algebra.Field          as Field
+import qualified Algebra.Ring           as Ring
+import qualified Algebra.Additive       as Additive
+
+import Foreign.Storable (Storable, )
+import Foreign.Storable.Tuple ()
+
+import Algebra.Module( {- linearComb, -} (*>), )
+
+import Control.Monad (mplus, )
+
+import qualified Data.List as List
+import Data.Tuple.HT (mapFst, mapSnd, mapPair, swap, )
+
+import qualified Numeric.NonNegative.Chunky as NonNegChunky
+
+import PreludeBase
+import NumericPrelude as NP
+import qualified Prelude as P
+
+
+{- |
+The Maybe type carries an unpaired value from one block to the next one.
+-}
+sumsDownsample2Strict ::
+   (Additive.C v, Storable v) =>
+   Maybe v -> V.Vector v -> (Maybe v, V.Vector v)
+sumsDownsample2Strict carry ys =
+   mapFst (\v -> fmap fst $ V.viewL . snd =<< v) $ swap $
+   V.unfoldrN (div (V.length ys + maybe 0 (const 1) carry) 2) (\(carry0,xs0) ->
+      do (x0,xs1) <- mplus (fmap (\c -> (c, xs0)) carry0) (V.viewL xs0)
+         (x1,xs2) <- V.viewL xs1
+         return (x0+x1, (Nothing, xs2)))
+      (carry, ys)
+
+sumsDownsample2 ::
+   (Additive.C v, Storable v) =>
+   SigSt.T v -> SigSt.T v
+sumsDownsample2 =
+   SigSt.fromChunks .
+   filter (not . V.null) .
+   (\(carry, chunks) ->
+      chunks ++ maybe [] (\cr -> [V.singleton cr]) carry) .
+   List.mapAccumL sumsDownsample2Strict Nothing .
+   SigSt.chunks
+
+sumsDownsample2Alt ::
+   (Additive.C v, Storable v) =>
+   SigSt.T v -> SigSt.T v
+sumsDownsample2Alt ys =
+   fst .
+   VP.unfoldrN (halfLazySize $ VP.length ys) (\xs ->
+      flip fmap (SigS.viewL xs) $ \xxs0@(x0,xs0) ->
+         SigS.switchL xxs0 {- xs0 is empty -}
+            (\ x1 xs1 -> (x0+x1, xs1))
+            xs0)
+    . SigS.fromStorableSignal $ ys
+
+halfLazySize :: NonNegChunky.T VP.ChunkSize -> NonNegChunky.T VP.ChunkSize
+halfLazySize =
+   NonNegChunky.fromChunks .
+   filter (VL.ChunkSize zero /=) .
+   (\(c,ls) -> ls ++ [VL.ChunkSize c]) .
+   List.mapAccumL (\c (VL.ChunkSize l) ->
+      mapSnd VL.ChunkSize $ swap $ divMod (c+l) 2) zero .
+   NonNegChunky.toChunks
+
+{- |
+offset must be zero or one.
+-}
+downsample2Strict ::
+   (Storable v) =>
+   Int -> V.Vector v -> V.Vector v
+downsample2Strict offset ys =
+   fst $
+   V.unfoldrN (- div (offset - V.length ys) 2)
+      (fmap (mapSnd laxTailStrict) . V.viewL) $
+   if offset == 0
+     then ys
+     else laxTailStrict ys
+
+laxTailStrict ::
+   (Storable v) =>
+   V.Vector v -> V.Vector v
+laxTailStrict ys =
+   V.switchL ys (flip const) ys
+
+downsample2 ::
+   (Storable v) =>
+   SigSt.T v -> SigSt.T v
+downsample2 =
+   SigSt.fromChunks .
+   filter (not . V.null) .
+   snd .
+   List.mapAccumL
+      (\k c ->
+         (mod (k + V.length c) 2, downsample2Strict k c)) zero .
+   SigSt.chunks
+
+
+pyramid ::
+   (Additive.C v, Storable v) =>
+   Int -> SigSt.T v -> [SigSt.T v]
+pyramid height =
+   take (1+height) . iterate sumsDownsample2
+
+{-
+This function uses the efficient Storable.index function.
+If @Generic.index@ becomes as fast as @Storable.index@
+then we can replace this function by its generic counterpart.
+-}
+sumRangeFromPyramid ::
+   (Additive.C v, Storable v) =>
+   [SigSt.T v] -> (Int,Int) -> v
+sumRangeFromPyramid =
+   Filt.sumRangePrepare $ \(l0,r0) pyr0 ->
+   case pyr0 of
+      [] -> error "empty pyramid"
+      (ps0:pss) ->
+         foldr
+            (\psNext k (l,r) ps s ->
+               case r-l of
+                  0 -> s
+                  1 -> s + VL.index ps l
+                  _ ->
+                     let (lh,ll) = NP.negate $ divMod (NP.negate l) 2
+                         (rh,rl) = divMod r 2
+                         {-# INLINE inc #-}
+                         inc b x = if b==0 then id else (x+)
+                     in  k (lh,rh) psNext $
+                         inc ll (VL.index ps l) $
+                         inc rl (VL.index ps (r-1)) $
+                         s)
+            (\(l,r) ps s ->
+               s + (SigG.sum $ SigSt.take (r-l) $ SigSt.drop l ps))
+            pss (l0,r0) ps0 zero
+
+{- |
+Moving average, where window bounds must be always non-negative.
+
+The laziness granularity of the input signal is maintained.
+-}
+sumsPosModulatedPyramid ::
+   (Additive.C v, Storable (Int,Int), Storable v) =>
+   Int -> SigSt.T (Int,Int) -> SigSt.T v -> SigSt.T v
+sumsPosModulatedPyramid height ctrl xs =
+   let pyr0 = pyramid height xs
+       sizes =
+          reverse $ take (1+height) $ iterate (2*) 1
+       blockSize = head sizes
+       pyrStarts =
+          iterate (zipWith SigSt.drop sizes) pyr0
+       ctrlBlocks =
+          SigS.toList $
+          SigG.sliceVertical blockSize ctrl
+   in  SigSt.fromChunks $
+       zipWith
+          (\pyr ->
+              SigS.toStrictStorableSignal blockSize .
+              SigS.map (sumRangeFromPyramid pyr) .
+              SigS.zipWith (\d -> mapPair ((d+), (d+))) (SigS.iterate (1+) 0) .
+              SigS.fromStorableSignal)
+          pyrStarts ctrlBlocks
+
+{- |
+The first argument is the amplification.
+The main reason to introduce it,
+was to have only a Module constraint instead of Field.
+This way we can also filter stereo signals.
+-}
+movingAverageModulatedPyramid ::
+   (Field.C a, Module.C a v,
+    Storable Int, Storable v) =>
+   a -> Int -> Int -> SigSt.T Int -> SigSt.T v -> SigSt.T v
+movingAverageModulatedPyramid amp height maxC ctrl xs =
+   SigSt.zipWith (\c x -> (amp / fromIntegral (2*c+1)) *> x) ctrl $
+   sumsPosModulatedPyramid height
+      (SigSt.map (\c -> (maxC - c, maxC + c)) ctrl)
+      (FiltG.delay maxC xs)
diff --git a/src/Synthesizer/Storable/Signal.hs b/src/Synthesizer/Storable/Signal.hs
--- a/src/Synthesizer/Storable/Signal.hs
+++ b/src/Synthesizer/Storable/Signal.hs
@@ -34,6 +34,7 @@
       splitAtPad,
       Vector.null,
       Vector.fromChunks,
+      Vector.foldr,
       -- for Storable.Filter.Comb
       delay,
       delayLoop,
@@ -54,6 +55,10 @@
       zipWithAppend,
       -- for Storable.ALSA.MIDI
       Vector.switchR,
+      -- for Test.Filter
+      toList,
+      -- for Storable.Filter.NonRecursive
+      Vector.chunks,
 
       -- just for fun
       fromFusionList,
@@ -290,6 +295,10 @@
 {-# INLINE fromList #-}
 fromList :: (Storable a) => ChunkSize -> [a] -> T a
 fromList = Vector.pack
+
+{-# INLINE toList #-}
+toList :: (Storable a) => T a -> [a]
+toList = Vector.unpack
 
 
 {-
diff --git a/src/Test/Sound/Synthesizer/Plain/Filter.hs b/src/Test/Sound/Synthesizer/Plain/Filter.hs
--- a/src/Test/Sound/Synthesizer/Plain/Filter.hs
+++ b/src/Test/Sound/Synthesizer/Plain/Filter.hs
@@ -3,17 +3,33 @@
 import qualified Synthesizer.Plain.Filter.Recursive.MovingAverage as MA
 import qualified Synthesizer.Plain.Filter.NonRecursive as FiltNR
 import qualified Synthesizer.Plain.Signal as Sig
+import qualified Synthesizer.Generic.Filter.NonRecursive as FiltNRG
+import qualified Synthesizer.Generic.Signal as SigG
+import qualified Synthesizer.Storable.Filter.NonRecursive as FiltNRSt
+import qualified Synthesizer.Storable.Signal as SigSt
+import qualified Synthesizer.Frame.Stereo as Stereo
 
+import qualified Data.StorableVector.Lazy.Pattern as VP
+
+import Foreign.Storable.Tuple ()
+
 import Test.QuickCheck (test, {- Property, (==>) -})
--- import Test.Utility (equalList, approxEqualListAbs, approxEqualListRel, )
+import Test.Utility (equalList, {- approxEqualListAbs, approxEqualListRel, -} )
 
 -- import qualified Algebra.Module                as Module
 -- import qualified Algebra.RealField             as RealField
 -- import qualified Algebra.Ring                  as Ring
 -- import qualified Algebra.Additive              as Additive
 
+import qualified Number.GaloisField2p32m5 as GF
 import qualified Number.NonNegative       as NonNeg
 
+import qualified Numeric.NonNegative.Chunky as Chunky
+
+import Data.Tuple.HT (mapPair, )
+
+-- import Debug.Trace (trace, )
+
 import NumericPrelude
 import PreludeBase
 import Prelude ()
@@ -31,8 +47,105 @@
        and $ zipWith3 (\x y z -> x==y && y==z) naive rec pyramid
        -- equalList $ naive : pyramid : rec : []
 
+sumRange :: NonNeg.Int -> (NonNeg.Int, NonNeg.Int) -> Sig.T Int -> Bool
+sumRange nheight (nl,nr) xs =
+   let wrap n = mod (NonNeg.toNumber n) (length xs + 1)
+       height = 1 + NonNeg.toNumber nheight
+       rng = (wrap nl, wrap nr)
+   in  equalList $
+       FiltNR.sumRange xs rng :
+       FiltNR.sumRangeFromPyramid (take height (FiltNR.pyramid xs)) rng :
+       FiltNR.sumRangeFromPyramidRec (take height (FiltNR.pyramid xs)) rng :
+       FiltNRSt.sumRangeFromPyramid
+          (FiltNRSt.pyramid height
+             (SigSt.fromList SigSt.defaultChunkSize xs)) rng :
+       []
 
+sumsPosModulated ::
+   NonNeg.Int -> Sig.T (NonNeg.Int,NonNeg.Int) -> (Int, Sig.T Int) -> Bool
+sumsPosModulated nheight nctrl xsc =
+   let ctrl = map (mapPair (NonNeg.toNumber, NonNeg.toNumber)) nctrl
+       xs = cycle $ uncurry (:) xsc
+       height = min 10 $ NonNeg.toNumber nheight
+   in  -- trace (show (height, ctrl, xsc)) $
+       equalList $
+       FiltNR.sumsPosModulated ctrl xs :
+       FiltNR.sumsPosModulatedPyramid height ctrl xs :
+       FiltNRG.sumsPosModulatedPyramid height ctrl xs :
+       SigSt.toList
+          (FiltNRG.sumsPosModulatedPyramid
+             height
+             (SigSt.fromList SigSt.defaultChunkSize ctrl)
+             (SigSt.fromList SigSt.defaultChunkSize xs)) :
+       SigSt.toList
+          (FiltNRSt.sumsPosModulatedPyramid
+             height
+             (SigSt.fromList SigSt.defaultChunkSize ctrl)
+             (SigSt.fromList SigSt.defaultChunkSize xs)) :
+       []
+
+downSample2 ::
+   [Int] -> (Int, Sig.T Int) -> Bool
+downSample2 lazySize xsc =
+   let len = Chunky.fromChunks $ map (VP.chunkSize . succ . abs) lazySize
+       xs = VP.pack len $ cycle $ uncurry (:) xsc
+   in  equalList $
+       FiltNRG.downsample2 SigG.defaultLazySize xs :
+       FiltNRSt.downsample2 xs :
+       []
+
+sumsDownSample2 ::
+   [Int] -> (Int, Sig.T Int) -> Bool
+sumsDownSample2 lazySize xsc =
+   let len = Chunky.fromChunks $ map (VP.chunkSize . succ . abs) lazySize
+       xs = VP.pack len $ cycle $ uncurry (:) xsc
+   in  equalList $
+       FiltNRG.sumsDownsample2 SigG.defaultLazySize xs :
+       FiltNRSt.sumsDownsample2 xs :
+       FiltNRSt.sumsDownsample2Alt xs :
+       []
+
+{-
+sumsDownSample2 ::
+   [VP.ChunkSize] -> (Int, Sig.T Int) -> Bool
+sumsDownSample2 lazySize xsc =
+   let len = Chunky.fromChunks $ filter (0/=) lazySize
+       xs = VP.pack len $ cycle $ uncurry (:) xsc
+   in  equalList $
+       FiltNRG.sumsDownsample2 SigG.defaultLazySize xs :
+       FiltNRSt.sumsDownsample2 xs :
+       FiltNRSt.sumsDownsample2Alt xs :
+       []
+-}
+
+movingAverageModulatedPyramid ::
+   NonNeg.Int -> Sig.T NonNeg.Int ->
+   (Stereo.T GF.T, Sig.T (Stereo.T GF.T)) -> Bool
+movingAverageModulatedPyramid nheight nctrl xsc =
+   let ctrl = map NonNeg.toNumber nctrl
+       xs = uncurry (:) xsc
+       pack ys = SigSt.fromList SigSt.defaultChunkSize ys
+       maxC = maximum ctrl
+       height = min 10 $ NonNeg.toNumber nheight
+       onegf :: GF.T
+       onegf = one
+   in  -- trace (show (height, ctrl, xsc)) $
+       equalList $
+       pack (FiltNR.movingAverageModulatedPyramid onegf
+          height maxC ctrl (cycle xs)) :
+       FiltNRG.movingAverageModulatedPyramid onegf
+          height maxC (pack ctrl) (SigG.cycle $ pack xs) :
+       FiltNRSt.movingAverageModulatedPyramid onegf
+          height maxC (pack ctrl) (SigG.cycle $ pack xs) :
+       []
+
+
 tests :: [(String, IO ())]
 tests =
    ("sums", test sums) :
+   ("sumRange", test sumRange) :
+   ("sumsPosModulated", test sumsPosModulated) :
+   ("downSample2", test downSample2) :
+   ("sumsDownSample2", test sumsDownSample2) :
+   ("movingAverageModulatedPyramid", test movingAverageModulatedPyramid) :
    []
diff --git a/synthesizer-core.cabal b/synthesizer-core.cabal
--- a/synthesizer-core.cabal
+++ b/synthesizer-core.cabal
@@ -1,5 +1,5 @@
 Name:           synthesizer-core
-Version:        0.2
+Version:        0.2.1
 License:        GPL
 License-File:   LICENSE
 Author:         Henning Thielemann <haskell@henning-thielemann.de>
@@ -51,7 +51,7 @@
 
 
 Source-Repository this
-  Tag:         0.2
+  Tag:         0.2.1
   Type:        darcs
   Location:    http://code.haskell.org/synthesizer/core/
 
@@ -64,15 +64,16 @@
     transformers >=0.0.1 && <0.2,
     event-list >=0.0.8 && <0.1,
     non-negative >=0.0.5 && <0.1,
-    numeric-prelude >=0.1.1 && <0.2,
+    numeric-prelude >=0.1.2 && <0.2,
     numeric-quest >= 0.1 && <0.2,
     utility-ht >=0.0.5 && <0.1,
     sox >=0.0 && <0.1,
     filepath >=1.1 && <1.2,
     bytestring >= 0.9 && <0.10,
     binary >=0.1 && <1,
-    storablevector >=0.2.3 && <0.3,
+    storablevector >=0.2.4 && <0.3,
     storable-record >=0.0.1 && <0.1,
+    storable-tuple >=0.0.1 && <0.1,
     QuickCheck >=1 && <2
 
   If flag(splitBase)
@@ -163,6 +164,7 @@
     Synthesizer.Storable.Cut
     Synthesizer.Storable.Oscillator
     Synthesizer.Storable.Signal
+    Synthesizer.Storable.Filter.NonRecursive
     Synthesizer.State.Analysis
     Synthesizer.State.Control
     Synthesizer.State.Cut
@@ -196,6 +198,7 @@
     Synthesizer.Generic.Interpolation
     Synthesizer.Generic.Noise
     Synthesizer.Generic.Oscillator
+    Synthesizer.Generic.Piece
     Synthesizer.Generic.Signal
     Synthesizer.Generic.Signal2
     Synthesizer.Generic.Wave
